diff --git a/fhem/FHEM/59_Twilight.pm b/fhem/FHEM/59_Twilight.pm
index 05abb8682..da21a3897 100644
--- a/fhem/FHEM/59_Twilight.pm
+++ b/fhem/FHEM/59_Twilight.pm
@@ -4,6 +4,7 @@
# 59_Twilight.pm
# Copyright by Sebastian Stuecker
# erweitert von Dietmar Ortmann
+# Maintained by igami since 02-2018
#
# used algorithm see: http://lexikon.astronomie.info/zeitgleichung/
#
@@ -37,7 +38,7 @@ use warnings;
use POSIX;
use HttpUtils;
use Math::Trig;
-use Time::Local 'timelocal_nocheck';
+use Time::Local 'timelocal_nocheck';
sub Twilight_calc($$);
sub Twilight_my_gmt_offset();
@@ -108,30 +109,30 @@ sub Twilight_Define($$)
if(int(@a)>4) { if ($a[4] =~ /^[\+-]*[0-9]*\.*[0-9]*$/ && $a[4] !~ /^[\. ]*$/ ) {
$indoor_horizon = $a[4];
if($indoor_horizon > 20) { $indoor_horizon=20;}
- # minimal indoor_horizon makes values like civil_sunset and civil_sunrise
+ # minimal indoor_horizon makes values like civil_sunset and civil_sunrise
if($indoor_horizon < -6) { $indoor_horizon= -6;}
}else{
return "Argument Indoor_Horizon is not a valid number";}
}
-
+
$hash->{WEATHER_HORIZON} = 0;
$hash->{INDOOR_HORIZON} = $indoor_horizon;
$hash->{LATITUDE} = $latitude;
$hash->{LONGITUDE} = $longitude;
$hash->{WEATHER} = $weather;
- $hash->{VERSUCHE} = 0;
+ $hash->{VERSUCHE} = 0;
$hash->{DEFINE} = 1;
$hash->{CONDITION} = 50;
$hash->{SUNPOS_OFFSET} = 5*60;
-
+
$attr{$name}{verbose} = 4 if ($name =~ /^tst.*$/ );
-
+
my $mHash = { HASH=>$hash };
- Twilight_sunpos($mHash);
+ Twilight_sunpos($mHash);
Twilight_Midnight($mHash);
delete $hash->{DEFINE};
-
+
return undef;
}
################################################################################
@@ -152,14 +153,14 @@ sub myInternalTimer($$$$$) {
my ($modifier, $tim, $callback, $hash, $waitIfInitNotDone) = @_;
my $timerName = "$hash->{NAME}_$modifier";
- my $mHash = { HASH=>$hash, NAME=>"$hash->{NAME}_$modifier", MODIFIER=>$modifier};
+ my $mHash = { HASH=>$hash, NAME=>"$hash->{NAME}_$modifier", MODIFIER=>$modifier};
if (defined($hash->{TIMER}{$timerName})) {
Log3 $hash, 1, "[$hash->{NAME}] possible overwriting of timer $timerName - please delete first";
stacktrace();
} else {
$hash->{TIMER}{$timerName} = $mHash;
}
-
+
Log3 $hash, 5, "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim);
InternalTimer($tim, $callback, $mHash, $waitIfInitNotDone);
return $mHash;
@@ -191,12 +192,12 @@ sub myRemoveInternalTimer($$) {
################################################################################
sub myGetHashIndirekt ($$) {
my ($myHash, $function) = @_;
-
+
if (!defined($myHash->{HASH})) {
- Log 3, "[$function] myHash not valid";
+ Log 3, "[$function] myHash not valid";
return undef;
- };
- return $myHash->{HASH};
+ };
+ return $myHash->{HASH};
}
################################################################################
sub Twilight_midnight_seconds($) {
@@ -207,12 +208,12 @@ sub Twilight_midnight_seconds($) {
}
################################################################################
#sub Twilight_ssTimeAsEpoch($) {
-# my ($zeit) = @_;
+# my ($zeit) = @_;
# my ($hour, $min, $sec) = split(":",$zeit);
#
# my $days=0;
-# if ($hour>=24) {$days = 1; $hour -=24};
-#
+# if ($hour>=24) {$days = 1; $hour -=24};
+#
# my @jetzt_arr = localtime(time());
# #Stunden Minuten Sekunden
# $jetzt_arr[2] = $hour; $jetzt_arr[1] = $min; $jetzt_arr[0] = $sec;
@@ -224,21 +225,21 @@ sub Twilight_midnight_seconds($) {
################################################################################
sub Twilight_calc($$) {
my ($deg, $idx) = @_;
-
+
my $midnight = time() - Twilight_midnight_seconds(time());
my $sr = sunrise_abs("Horizon=$deg");
my $ss = sunset_abs ("Horizon=$deg");
my ($srhour, $srmin, $srsec) = split(":",$sr); $srhour -= 24 if($srhour>=24);
- my ($sshour, $ssmin, $sssec) = split(":",$ss); $sshour -= 24 if($sshour>=24);
+ my ($sshour, $ssmin, $sssec) = split(":",$ss); $sshour -= 24 if($sshour>=24);
my $sr1 = $midnight + 3600*$srhour+60*$srmin+$srsec;
my $ss1 = $midnight + 3600*$sshour+60*$ssmin+$sssec;
-
- return (0,0) if (abs ($sr1 - $ss1) < 30);
+
+ return (0,0) if (abs ($sr1 - $ss1) < 30);
#return Twilight_ssTimeAsEpoch($sr) + 0.01*$idx,
- # Twilight_ssTimeAsEpoch($ss) - 0.01*$idx;
+ # Twilight_ssTimeAsEpoch($ss) - 0.01*$idx;
return ($sr1 + 0.01*$idx), ($ss1 - 0.01*$idx);
}
################################################################################
@@ -258,32 +259,32 @@ sub Twilight_TwilightTimes(@) {
foreach my $horizon (@horizons) {
$idx++; next if ($whitchTimes eq "weather" && !($horizon =~ m/weather/) );
- my ($name, $deg) = split(":", $horizon);
- my $sr = "sr$name"; my $ss = "ss$name";
+ my ($name, $deg) = split(":", $horizon);
+ my $sr = "sr$name"; my $ss = "ss$name";
$hash->{TW}{$sr}{NAME} = $sr; $hash->{TW}{$ss}{NAME} = $ss;
$hash->{TW}{$sr}{DEG} = $deg; $hash->{TW}{$ss}{DEG} = $deg;
$hash->{TW}{$sr}{LIGHT} = $idx+1;$hash->{TW}{$ss}{LIGHT} = $idx;
$hash->{TW}{$sr}{STATE} = $idx+1;$hash->{TW}{$ss}{STATE} = 12 - $idx;
$hash->{TW}{$sr}{SWIP} = $swip; $hash->{TW}{$ss}{SWIP} = $swip;
-
+
($hash->{TW}{$sr}{TIME}, $hash->{TW}{$ss}{TIME}) = Twilight_calc ($deg, $idx);
-
+
if ($hash->{TW}{$sr}{TIME} == 0) {
Log3 $hash, 4, "[$Name] hint: $hash->{TW}{$sr}{NAME}, $hash->{TW}{$ss}{NAME} are not defined(HORIZON=$deg)";
}
}
- $attr{global}{latitude} = $lat;
- $attr{global}{longitude} = $long;
+ $attr{global}{latitude} = $lat;
+ $attr{global}{longitude} = $long;
# ------------------------------------------------------------------------------
readingsBeginUpdate ($hash);
foreach my $ereignis (keys %{$hash->{TW}}) {
next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) );
readingsBulkUpdate($hash, $ereignis, $hash->{TW}{$ereignis}{TIME} == 0 ? "undefined" : FmtTime($hash->{TW}{$ereignis}{TIME}));
- }
+ }
if ($hash->{CONDITION} != 50 ) {
readingsBulkUpdate ($hash,"condition", $hash->{CONDITION});
readingsBulkUpdate ($hash,"condition_txt",$hash->{CONDITION_TXT});
- }
+ }
readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1));
# ------------------------------------------------------------------------------
my @horizonsOhneDeg = map {my($e, $deg)=split(":",$_); "$e"} @horizons;
@@ -296,18 +297,18 @@ sub Twilight_TwilightTimes(@) {
my $lastMitternacht = $now-$secSinceMidnight;
my $nextMitternacht = ($secSinceMidnight > 12*3600) ? $lastMitternacht+24*3600 : $lastMitternacht;
my $jetztIstMitternacht = abs($now+5-$nextMitternacht)<=10;
-
+
my @keyListe = qw "DEG LIGHT STATE SWIP TIME NAMENEXT";
foreach my $ereignis (sort keys %{$hash->{TW}}) {
next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) );
-
+
myRemoveInternalTimer($ereignis, $hash); # if(!$jetztIstMitternacht);
if($hash->{TW}{$ereignis}{TIME} > 0) {
$myHash = myInternalTimer($ereignis, $hash->{TW}{$ereignis}{TIME}, "Twilight_fireEvent", $hash, 0);
- map {$myHash->{$_} = $hash->{TW}{$ereignis}{$_} } @keyListe;
+ map {$myHash->{$_} = $hash->{TW}{$ereignis}{$_} } @keyListe;
}
}
-# ------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
return 1;
}
################################################################################
@@ -318,7 +319,7 @@ sub Twilight_fireEvent($) {
return if (!defined($hash));
my $name = $hash->{NAME};
-
+
my $event = $myHash->{MODIFIER};
my $deg = $myHash->{DEG};
my $light = $myHash->{LIGHT};
@@ -330,18 +331,18 @@ sub Twilight_fireEvent($) {
my $delta = int($eventTime - time());
my $oldState = ReadingsVal($name,"state","0");
-
+
my $nextEventTime = ($hash->{TW}{$nextEvent}{TIME} > 0) ? FmtTime($hash->{TW}{$nextEvent}{TIME}) : "undefined";
-
+
my $doTrigger = !(defined($hash->{LOCAL})) && ( abs($delta)<6 || $swip && $state gt $oldState);
#Log3 $hash, 3, "[$hash->{NAME}] swip-delta-oldState-doTrigger===>$swip/$delta/$oldState/$doTrigger";
-
+
Log3 $hash, 4,
sprintf ("[$hash->{NAME}] %-10s %-19s ", $event, FmtDateTime($eventTime)).
- sprintf ("(%2d/$light/%+5.1f°/$doTrigger) ", $state, $deg).
+ sprintf ("(%2d/$light/%+5.1f°/$doTrigger) ", $state, $deg).
sprintf ("===> %-10s %-19s ", $nextEvent, $nextEventTime);
-
+
readingsBeginUpdate($hash);
readingsBulkUpdate ($hash, "state", $state);
readingsBulkUpdate ($hash, "light", $light);
@@ -355,11 +356,11 @@ sub Twilight_fireEvent($) {
}
################################################################################
sub Twilight_Midnight($) {
- my ($myHash) = @_;
+ my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
- return if (!defined($hash));
-
- $hash->{SWIP} = 0;
+ return if (!defined($hash));
+
+ $hash->{SWIP} = 0;
my $param = Twilight_CreateHttpParameterAndGetData($myHash, "Mid");
}
################################################################################
@@ -367,24 +368,24 @@ sub Twilight_Midnight($) {
sub Twilight_WeatherTimerUpdate($) {
my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
- return if (!defined($hash));
+ return if (!defined($hash));
- $hash->{SWIP} = 1;
+ $hash->{SWIP} = 1;
my $param = Twilight_CreateHttpParameterAndGetData($myHash, "weather");
-}
+}
################################################################################
sub Twilight_CreateHttpParameterAndGetData($$) {
my ($myHash, $mode) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
- return if (!defined($hash));
-
+ return if (!defined($hash));
+
my $location = $hash->{WEATHER};
my $verbose = AttrVal($hash->{NAME}, "verbose", 3 );
-
+
my $URL = "http://query.yahooapis.com/v1/public/yql?q=select%%20*%%20from%%20weather.forecast%%20where%%20woeid=%s%%20and%%20u=%%27c%%27&format=%s&env=store%%3A%%2F%%2Fdatatables.org%%2Falltableswithkeys";
my $url = sprintf($URL, $location, "json");
Log3 $hash, 4, "[$hash->{NAME}] url=$url";
-
+
my $param = {
url => $url,
timeout => defined($hash->{DEFINE}) ? 10 :10,
@@ -394,23 +395,23 @@ sub Twilight_CreateHttpParameterAndGetData($$) {
header => "User-Agent: Mozilla/5.0\r\nAccept: application/xml",
callback => \&Twilight_WeatherCallback,
mode => $mode };
-
+
if (defined($hash->{DEFINE})) {
delete $param->{callback};
my ($err, $result) = HttpUtils_BlockingGet($param);
Twilight_WeatherCallback($param, $err, $result);
} else {
HttpUtils_NonblockingGet($param);
- }
-
+ }
+
}
################################################################################
sub Twilight_WeatherCallback(@) {
my ($param, $err, $result) = @_;
-
+
my $hash = $param->{hash};
return if (!defined($hash));
-
+
if ($err) {
Log3 $hash, 3, "[$hash->{NAME}] got no weather info from yahoo. Error code: $err";
$result = undef;
@@ -418,22 +419,22 @@ sub Twilight_WeatherCallback(@) {
Log3 $hash, 4, "[$hash->{NAME}] got weather info from yahoo for $hash->{WEATHER}";
Log3 $hash, 5, "[$hash->{NAME}] answer=$result" if defined $result;
}
-
+
Twilight_getWeatherHorizon($hash, $result);
- #$hash->{CONDITION} = 50;
-
+ #$hash->{CONDITION} = 50;
+
if ($hash->{CONDITION} == 50 && $hash->{VERSUCHE} <= 10) {
$hash->{VERSUCHE} += 1;
Twilight_RepeatTimerSet($hash, $param->{mode});
return;
}
-
+
Twilight_TwilightTimes ($hash, $param->{mode}, $result);
-
+
Log3 $hash, 3, "[$hash->{NAME}] " . ($hash->{VERSUCHE}+1) . " attempt(s) needed to get valid weather data from yahoo" if ($hash->{CONDITION} != 50 && $hash->{VERSUCHE} > 0);
Log3 $hash, 3, "[$hash->{NAME}] " . ($hash->{VERSUCHE}+1) . " attempt(s) needed got NO valid weather data from yahoo" if ($hash->{CONDITION} == 50 && $hash->{VERSUCHE} > 0);
- $hash->{VERSUCHE} = 0;
-
+ $hash->{VERSUCHE} = 0;
+
Twilight_StandardTimerSet ($hash);
}
################################################################################
@@ -446,8 +447,8 @@ sub Twilight_RepeatTimerSet($$) {
myInternalTimer ("Midnight", $midnight, "Twilight_Midnight", $hash, 0);
} else {
myInternalTimer ("Midnight", $midnight, "Twilight_WeatherTimerUpdate", $hash, 0);
- }
-
+ }
+
}
################################################################################
sub Twilight_StandardTimerSet($) {
@@ -484,13 +485,13 @@ sub Twilight_sunposTimerSet($) {
sub Twilight_getWeatherHorizon(@)
{
my ($hash, $result) = @_;
-
+
my $location=$hash->{WEATHER};
if ($location == 0) {
$hash->{WEATHER_HORIZON}="0";
- $hash->{CONDITION}="0";
+ $hash->{CONDITION}="0";
return 1;
- }
+ }
my $mod = "[".$hash->{NAME} ."] ";
my @faktor_cond_code = (10,10,10,10, 9, 7, 7, 7, 7, 7,
@@ -504,39 +505,39 @@ sub Twilight_getWeatherHorizon(@)
my ($cond_code, $cond_txt, $temperatur, $aktTemp);
if (defined($result)) {
-
+
# ersetze in result(json) ": durch "=>
# dadurch entsteht ein Perlausdruck, der direkt geparst werden kann
-
+
my $perlAusdruck = $result;
#$perlAusdruck = "
could";
$perlAusdruck =~ s/("[\w ]+")(\s*)(:)/$1=>/g;
$perlAusdruck =~ s/null/undef/g;
$perlAusdruck =~ s/true/1/g;
$perlAusdruck =~ s/false/0/g;
- $perlAusdruck = 'return ' .$perlAusdruck;
-
+ $perlAusdruck = 'return ' .$perlAusdruck;
+
my $anonymSub = eval "sub {$perlAusdruck}";
Log3 $hash, 3, "[$hash->{NAME}] error $@ parsing $result" if($@);
if (!$@) {
- my $resHash = $anonymSub->() if ($anonymSub gt "");
+ my $resHash = $anonymSub->() if ($anonymSub gt "");
Log3 $hash, 3, "[$hash->{NAME}] error $@ parsing $result" if($@);
#Log3 $hash, 3, "jsonAsPerl". Dumper $resHash->{query}{results}{channel}{item}{condition};
if (!$@) {
-
+
$cond_code = $resHash->{query}{results}{channel}{item}{condition}{code};
$cond_txt = $resHash->{query}{results}{channel}{item}{condition}{text};
$temperatur = $resHash->{query}{results}{channel}{item}{condition}{temp};
- }
+ }
}
}
-
+
# wenn kein Code ermittelt werden kann, wird ein Pseudocode gesetzt
if (!defined($cond_code) ) {
$cond_code = "50"; # eigener neutraler Code
$cond_txt = "undefined";
$temperatur = "undefined";
- } else {
+ } else {
$hash->{WEATHER_CORRECTION} = $faktor_cond_code[$cond_code] / 25 * 20;
$hash->{WEATHER_HORIZON} = $hash->{WEATHER_CORRECTION} + $hash->{INDOOR_HORIZON};
$hash->{CONDITION} = $cond_code;
@@ -544,15 +545,15 @@ sub Twilight_getWeatherHorizon(@)
$hash->{TEMPERATUR} = $temperatur;
Log3 $hash, 4, "[$hash->{NAME}] $cond_code=$cond_txt $temperatur, correction: $hash->{WEATHER_CORRECTION}°";
}
-
- my $doy = strftime("%j",localtime);
+
+ my $doy = strftime("%j",localtime);
my $declination = 0.4095*sin(0.016906*($doy-80.086));
if($hash->{WEATHER_HORIZON} > (89-$hash->{LATITUDE}+$declination) ){
$hash->{WEATHER_HORIZON} = 89-$hash->{LATITUDE}+$declination;
}
-
+
return 1;
-
+
}
################################################################################
sub Twilight_sunpos($)
@@ -640,7 +641,7 @@ sub Twilight_sunpos($)
my $twilight = int(($dElevation+12.0)/18.0 * 1000)/10;
$twilight = 100 if ($twilight>100);
$twilight = 0 if ($twilight< 0);
-
+
my $twilight_weather ;
if( (my $ExtWeather = AttrVal($hashName, "useExtWeather", "")) eq "") {
@@ -648,17 +649,17 @@ sub Twilight_sunpos($)
Log3 $hash, 5, "[$hash->{NAME}] " . "Original weather readings";
} else {
my($extDev,$extReading) = split(":",$ExtWeather);
- my $extWeatherHorizont = ReadingsVal($extDev,$extReading,-1);
+ my $extWeatherHorizont = ReadingsVal($extDev,$extReading,-1);
if ($extWeatherHorizont >= 0){
$extWeatherHorizont = 100 if ($extWeatherHorizont > 100);
- Log3 $hash, 5, "[$hash->{NAME}] " . "New weather readings from: ".$extDev.":".$extReading.":".$extWeatherHorizont;
+ Log3 $hash, 5, "[$hash->{NAME}] " . "New weather readings from: ".$extDev.":".$extReading.":".$extWeatherHorizont;
$twilight_weather = $twilight - int(0.007 * ($extWeatherHorizont ** 2)); ## SCM: 100% clouds => 30% light (rough estimation)
} else {
$twilight_weather = int(($dElevation-$hash->{WEATHER_HORIZON}+12.0)/18.0 * 1000)/10;
- Log3 $hash, 3, "[$hash->{NAME}] " . "Error with external readings from: ".$extDev.":".$extReading." , taking original weather readings";
+ Log3 $hash, 3, "[$hash->{NAME}] " . "Error with external readings from: ".$extDev.":".$extReading." , taking original weather readings";
}
- }
-
+ }
+
$twilight_weather = 100 if ($twilight_weather>100);
$twilight_weather = 0 if ($twilight_weather< 0);
@@ -759,7 +760,7 @@ sub twilight($$$$) {
indoor_horizon
- The parameter indoor_horizon gives a virtual horizon, that shall be used for calculation of indoor twilight. Minimal value -6 means indoor values are the same like civil values.
+ The parameter indoor_horizon gives a virtual horizon, that shall be used for calculation of indoor twilight. Minimal value -6 means indoor values are the same like civil values.
indoor_horizon 0 means indoor values are the same as real values. indoor_horizon > 0 means earlier indoor sunset resp. later indoor sunrise.
Weather_Position
@@ -899,8 +900,8 @@ Example:
indoor_horizon
- Der Parameter indoor_horizon bestimmt einen virtuellen Horizont, der für die Berechnung der Dämmerung innerhalb von Rämen genutzt werden kann. Minimalwert ist -6 (ergibt gleichen Wert wie Zivile Dämmerung). Bei 0 fallen
- indoor- und realer Dämmerungswert zusammen. Werte grösser 0 ergeben frühere Werte für den Abend bzw. spätere für den Morgen.
+ Der Parameter indoor_horizon bestimmt einen virtuellen Horizont, der für die Berechnung der Dämmerung innerhalb von Rämen genutzt werden kann. Minimalwert ist -6 (ergibt gleichen Wert wie Zivile Dämmerung). Bei 0 fallen
+ indoor- und realer Dämmerungswert zusammen. Werte grösser 0 ergeben frühere Werte für den Abend bzw. spätere für den Morgen.
Weather_Position
@@ -925,7 +926,7 @@ Example:
Azimut, Elevation, Twilight (Seitenwinkel, Höhenwinkel, Dämmerung)
Das Modul berechnet zusätzlich Azimuth und Elevation der Sonne. Diese Werte können zur Rolladensteuerung verwendet werden.
-
+
Das Reading Twilight wird als neuer "(twi)light" Wert hinzugefügt. Er wird aus der Elevation der Sonne mit folgender Formel abgeleitet: (Elevation+12)/18 * 100). Das erlaubt eine detailliertere Kontrolle der Lampen während Sonnenauf - und untergang. Dieser Wert ist zwischen 0% und 100% wenn die Elevation zwischen -12° und 6°
@@ -990,7 +991,7 @@ Wissenswert dazu ist, dass die Sonne, abhägnig vom Breitengrad, bestimmte E
useExtWeather <device>:<reading>
Nutzt Daten von einem anderen Device um twilight_weather zu berechnen.
Das Reading sollte sich im Intervall zwischen 0 und 100 bewegen, z.B. das Reading c_clouds in einemopenweathermap device, bei dem 0 heiteren und 100 bedeckten Himmel bedeuten.
- Wird diese Attribut genutzt , werden Wettereffekte wie Starkregen oder Gewitter fuer die Berechnung von twilight_weather nicht mehr herangezogen.
+ Wird diese Attribut genutzt , werden Wettereffekte wie Starkregen oder Gewitter fuer die Berechnung von twilight_weather nicht mehr herangezogen.
diff --git a/fhem/FHEM/98_Heating_Control.pm b/fhem/FHEM/98_Heating_Control.pm
index d850f970a..27a566d1f 100644
--- a/fhem/FHEM/98_Heating_Control.pm
+++ b/fhem/FHEM/98_Heating_Control.pm
@@ -3,6 +3,7 @@
#
# 98_Heating_Control.pm
# written by Dietmar Ortmann
+# Maintained by igami since 02-2018
#
# This file is part of fhem.
#
@@ -36,7 +37,7 @@ sub Heating_Control_Initialize($)
# Consumer
$hash->{SetFn} = "Heating_Control_Set";
- $hash->{AttrFn} = "Heating_Control_Attr";
+ $hash->{AttrFn} = "Heating_Control_Attr";
$hash->{DefFn} = "Heating_Control_Define";
$hash->{UndefFn} = "Heating_Control_Undef";
$hash->{GetFn} = "Heating_Control_Get";
@@ -47,21 +48,21 @@ sub Heating_Control_Initialize($)
################################################################################
sub Heating_Control_Set($@) {
my ($hash, @a) = @_;
-
+
return "no set value specified" if(int(@a) < 2);
return "Unknown argument $a[1], choose one of enable disable " if($a[1] eq "?");
-
+
my $name = shift @a;
my $v = join(" ", @a);
Log3 $hash, 3, "[$name] set $name $v";
-
+
if ($v eq "enable") {
- fhem("attr $name disable 0");
+ fhem("attr $name disable 0");
} elsif ($v eq "disable") {
- fhem("attr $name disable 1");
+ fhem("attr $name disable 1");
}
- return undef;
+ return undef;
}
########################################################################
sub Heating_Control_Get($@) {
@@ -92,8 +93,8 @@ sub Heating_Control_SetTimerOfDay($) {
########################################################################
sub Heating_Control_Attr($$$$) {
my ($cmd, $name, $attrName, $attrVal) = @_;
-
- WeekdayTimer_Attr($cmd, $name, $attrName, $attrVal);
+
+ WeekdayTimer_Attr($cmd, $name, $attrName, $attrVal);
return undef;
}
########################################################################
@@ -101,15 +102,15 @@ sub Heating_Control_SetTimer($) {
my ($hash) = @_;
WeekdayTimer_DeleteTimer($hash);
WeekdayTimer_SetTimer($hash);
-}
+}
########################################################################
sub Heating_Control_SetTemp($) {
my ($name) = @_;
-
+
my $hash = $modules{Heating_Control}{defptr}{$name};
if(defined $hash) {
Heating_Control_SetTimer($hash);
- }
+ }
}
########################################################################
sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
@@ -170,12 +171,12 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
profile
Define the weekly profile. All timings are separated by space. A switchingtime is defined
by the following example:
-
+
[<weekdays>|]<time>|<parameter>
-
+
weekdays: optional, if not set every day of the week is used.
Otherwise you can define a day with its number or its shortname.
-
+
- 0,su sunday
- 1,mo monday
- 2,tu tuesday
@@ -236,26 +237,26 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
define HeizStatus2 notify Heating:. * {Heating_Control_SetAllTemps()}
Some definitions without comment:
-
- define hc Heating_Control HeizungKueche de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
- define hc Heating_Control HeizungKueche de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
- define hc Heating_Control HeizungKueche de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
-
- define hw Heating_Control HeizungKueche de mo-so, $we|{sunrise_abs_dat($date)}|18 mo-so, $we|{sunset_abs_dat($date)}|22
- define ht Heating_Control HeizungKueche de mo-so,!$we|{sunrise_abs_dat($date)}|18 mo-so,!$we|{sunset_abs_dat($date)}|22
-
- define hh Heating_Control HeizungKueche de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
- define hx Heating_Control HeizungKueche de 22:35|25 23:00|16
-
-
- the list of days can be set globaly for the whole Heating_Control:
-
- define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$we 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de $we 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de 78 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de 57 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein"))
+ define hc Heating_Control HeizungKueche de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
+ define hc Heating_Control HeizungKueche de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
+ define hc Heating_Control HeizungKueche de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
+
+ define hw Heating_Control HeizungKueche de mo-so, $we|{sunrise_abs_dat($date)}|18 mo-so, $we|{sunset_abs_dat($date)}|22
+ define ht Heating_Control HeizungKueche de mo-so,!$we|{sunrise_abs_dat($date)}|18 mo-so,!$we|{sunset_abs_dat($date)}|22
+
+ define hh Heating_Control HeizungKueche de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
+ define hx Heating_Control HeizungKueche de 22:35|25 23:00|16
+
+
+ the list of days can be set globaly for the whole Heating_Control:
+
+
+ define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$we 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de $we 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de 78 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de 57 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein"))
An example to be able to temporarily boost the temperature for one hour:
@@ -267,9 +268,9 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
define HeatingBath_Boost dummy
attr HeatingBath_Boost setList state:0,23,24,25
attr HeatingBath_Boost webCmd state
- define di_ResetBoostBath DOIF ([HeatingBath_Boost] > 0)
- ({Heating_Control_SetAllTemps()}, defmod di_ResetBoostBath_Reset at +01:00:00 set HeatingBath_Boost 0)
- DOELSE
+ define di_ResetBoostBath DOIF ([HeatingBath_Boost] > 0)
+ ({Heating_Control_SetAllTemps()}, defmod di_ResetBoostBath_Reset at +01:00:00 set HeatingBath_Boost 0)
+ DOELSE
({Heating_Control_SetAllTemps()})
attr di_ResetBoostBath do always
@@ -288,7 +289,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
Now you can set "HeatingBath_Boost" in the web interface for a one-hour boost of 3 degrees in the bath.
(you can trigger that using the PRESENCE function using your girlfriend's device... grin).
-
+
Easy to extend this with a vacation timer using another dummy variable, here VacationTemp
.
Then you can use the command
defmod defVacationEnd at 2016-12-30T00:00:00 set VacationTemp off, {Heating_Control_SetAllTemps()}
@@ -308,7 +309,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
}
Pray that the device does not restart during your vacation, as the define defVacationEnd ... at
is volatile and will be lost at restart!
-
+
@@ -321,32 +322,32 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
Attributes
- - delayedExecutionCond
- defines a delay Function. When returning true, the switching of the device is delayed until the function retruns a false value. The behavior is just like a windowsensor.
-
+ - delayedExecutionCond
+ defines a delay Function. When returning true, the switching of the device is delayed until the function retruns a false value. The behavior is just like a windowsensor.
+
Example:
- attr hc delayedExecutionCond isDelayed("%HEATING_CONTROL","%WEEKDAYTIMER","%TIME","%NAME","%EVENT")
+ attr hc delayedExecutionCond isDelayed("%HEATING_CONTROL","%WEEKDAYTIMER","%TIME","%NAME","%EVENT")
the parameters %HEATING_CONTROL(timer name) %TIME %NAME(device name) %EVENT are replaced at runtime by the correct value.
- Example of a function:
+ Example of a function:
sub isDelayed($$$$$) {
my($hc, $wdt, $tim, $nam, $event ) = @_;
-
+
my $theSunIsStillshining = ...
-
- return ($tim eq "16:30" && $theSunIsStillshining) ;
+
+ return ($tim eq "16:30" && $theSunIsStillshining) ;
}
-
+
- - switchInThePast
+ - switchInThePast
defines that the depending device will be switched in the past in definition and startup phase when the device is not recognized as a heating.
Heatings are always switched in the past.
-
+
- disable
- event-on-update-reading
@@ -404,19 +405,19 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
Wochentage: optionale Angabe, falls nicht gesetzt wird der Schaltpunkt jeden Tag ausgeführt.
Für die Tage an denen dieser Schaltpunkt aktiv sein soll, ist jeder Tag mit seiner
Tagesnummer (Mo=1, ..., So=0) oder Name des Tages (Mo, Di, ..., So) einzusetzen.
-
+
- 0,so Sonntag
- 1,mo Montag
- 2,di Dienstag
- 3,mi Mittwoch
- 4 ...
- 7,$we Wochenende ($we)
- - 8,!$we Wochentag (!$we)
+ - 8,!$we Wochentag (!$we)
- Es ist möglich $we or !$we in der Tagesliste zu definieren.
+ Es ist möglich $we or !$we in der Tagesliste zu definieren.
So ist es auf einfache Art möglich die Schaltzeitpunkte für das Wochenende oder Wochetage zu definieren.
- $we und!$we werden als 7 bzw. 8 spezifiziert, wenn die numerische Variante der Tagesliste gewählt wird.
- Uhrzeit:Angabe der Uhrzeit zu der geschaltet werden soll, Format: HH:MM:[SS](HH im 24 Stunden Format) oder eine Perlfunction wie {sunrise_abs()}.
+ $we und!$we werden als 7 bzw. 8 spezifiziert, wenn die numerische Variante der Tagesliste gewählt wird.
+ Uhrzeit:Angabe der Uhrzeit zu der geschaltet werden soll, Format: HH:MM:[SS](HH im 24 Stunden Format) oder eine Perlfunction wie {sunrise_abs()}.
In {} kannst du die Variable $date(epoch) nutzen, um die Schaltzeiten der Woche zu berechnen. Beispiel: {sunrise_abs_dat($date)}
Parameter:Angabe der zu setzenden Temperatur als Zahl mit Format 99.9 oder als symbolische Konstante eco
@@ -468,24 +469,24 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
define HeizStatus2 notify Heizung:.* {Heating_Control_SetAllTemps()}
Einige Definitionen ohne weitere Erklärung:
-
- define hc Heating_Control HeizungKueche de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
- define hc Heating_Control HeizungKueche de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
- define hc Heating_Control HeizungKueche de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
-
- define hw Heating_Control HeizungKueche de mo-so, $we|{sunrise_abs_dat($date)}|18 mo-so, $we|{sunset_abs_dat($date)}|22
- define ht Heating_Control HeizungKueche de mo-so,!$we|{sunrise_abs_dat($date)}|18 mo-so,!$we|{sunset_abs_dat($date)}|22
-
- define hh Heating_Control HeizungKueche de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
- define hx Heating_Control HeizungKueche de 22:35|25 23:00|16
+
+ define hc Heating_Control HeizungKueche de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
+ define hc Heating_Control HeizungKueche de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
+ define hc Heating_Control HeizungKueche de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
+
+ define hw Heating_Control HeizungKueche de mo-so, $we|{sunrise_abs_dat($date)}|18 mo-so, $we|{sunset_abs_dat($date)}|22
+ define ht Heating_Control HeizungKueche de mo-so,!$we|{sunrise_abs_dat($date)}|18 mo-so,!$we|{sunset_abs_dat($date)}|22
+
+ define hh Heating_Control HeizungKueche de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
+ define hx Heating_Control HeizungKueche de 22:35|25 23:00|16
Die Tagesliste kann global für das ganze Heating_Control angegeben werden:
- define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$we 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de $we 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de 78 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de 57 09:00|19 (heizungAnAus("Ein"))
- define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$we 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de $we 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de 78 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de 57 09:00|19 (heizungAnAus("Ein"))
+ define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein"))
es ist möglich den Parameter als Perlcode zu spezifizieren:
@@ -493,12 +494,12 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
... 7|23:35|{getParameter(13,"this")} 7|23:36|{getParameter(14,"that")}
ein detailiertes Beispiel ist in Heating_Control(EN) beschrieben
-
+
- Set
+ Set
set <name> <value>
@@ -513,7 +514,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
set hc disable
set hc enable
-
+
Get
@@ -522,33 +523,33 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
Attributes
- delayedExecutionCond
- definiert eine Veroegerungsfunktion. Wenn die Funktion wahr liefert, wird die Schaltung des Geraets solage verzoegert, bis die Funktion wieder falsch liefert. Das Verhalten entspricht einem Fensterkontakt.
-
+ definiert eine Veroegerungsfunktion. Wenn die Funktion wahr liefert, wird die Schaltung des Geraets solage verzoegert, bis die Funktion wieder falsch liefert. Das Verhalten entspricht einem Fensterkontakt.
+
- Beispiel:
+ Beispiel:
- attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT")
+ attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT")
Die Parameter $HEATING_CONTROL(timer Name) $TIME $NAME(device Name) $EVENT werden zur Laufzeit durch die echten Werte ersetzt.
-
+
- Beispielfunktion:
+ Beispielfunktion:
sub isDelayed($$$$$) {
my($hc, $wdt, $tim, $nam, $event ) = @_;
-
+
my $theSunIsStillshining = ...
-
- return ($tim eq "16:30" && $theSunIsStillshining) ;
+
+ return ($tim eq "16:30" && $theSunIsStillshining) ;
}
-
+
- - switchInThePast
+ - switchInThePast
Definiert, dass ein abhängiges Gerät in der Start- oder Definitionsphase mit einem Wert aus der Vergangheit geschaltet wird auch wenn das Gerät nicht als Heizung erkannt wurde.
Heizungen werden immer mit einem Wert aus der Vergangenheit geschaltet.
-
+
+
-
- disable
- event-on-update-reading
- event-on-change-reading
@@ -558,4 +559,3 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
=end html_DE
=cut
-
diff --git a/fhem/FHEM/98_RandomTimer.pm b/fhem/FHEM/98_RandomTimer.pm
index 50651b082..9197c00df 100644
--- a/fhem/FHEM/98_RandomTimer.pm
+++ b/fhem/FHEM/98_RandomTimer.pm
@@ -3,6 +3,7 @@
#
# 98_RandomTimer_Initialize.pm
# written by Dietmar Ortmann
+# Maintained by igami since 02-2018
#
# This file is part of fhem.
#
@@ -96,7 +97,7 @@ sub RandomTimer_Define($$)
if(!($timeToSwitch =~ m/^[0-9]{2,4}$/i));
RandomTimer_setSwitchmode ($hash, "800/200") if (!defined $hash->{helper}{SWITCHMODE});
-
+
$hash->{NAME} = $name;
$hash->{DEVICE} = $device;
$hash->{helper}{TIMESPEC_START} = $timespec_start;
@@ -107,11 +108,11 @@ sub RandomTimer_Define($$)
$hash->{helper}{S_REP} = $srep;
$hash->{helper}{S_REL} = $srel;
$hash->{COMMAND} = Value($hash->{DEVICE});
-
+
#$attr{$name}{verbose} = 4;
-
+
readingsSingleUpdate ($hash, "TimeToSwitch", $hash->{helper}{TIMETOSWITCH}, 1);
-
+
myRemoveInternalTimer("SetTimer", $hash);
myInternalTimer ("SetTimer", time(), "RandomTimer_SetTimer", $hash, 0);
@@ -125,50 +126,50 @@ sub RandomTimer_SetTimer($) {
my $now = time();
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
-
+
RandomTimer_setActive($hash, 0);
RandomTimer_schaltZeitenErmitteln($hash, $now);
RandomTimer_setState($hash);
-
+
Log3 $hash, 4, "[".$hash->{NAME}."]" . " timings RandomTimer on $hash->{DEVICE}: "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime}));
-
+
my $secToMidnight = 24*3600 -(3600*$hour + 60*$min + $sec);
-
+
my $setExecTime = max($now, $hash->{helper}{startTime});
myRemoveInternalTimer("Exec", $hash);
myInternalTimer ("Exec", $setExecTime, "RandomTimer_Exec", $hash, 0);
if ($hash->{helper}{REP} gt "") {
- my $setTimerTime = max($now+$secToMidnight + 15,
+ my $setTimerTime = max($now+$secToMidnight + 15,
$hash->{helper}{stopTime}) + $hash->{helper}{TIMETOSWITCH}+15;
myRemoveInternalTimer("SetTimer", $hash);
myInternalTimer ("SetTimer", $setTimerTime, "RandomTimer_SetTimer", $hash, 0);
}
}
########################################################################
-# define Test RandomTimer +00:00:05 Brunnen +00:05:00 60 ;
-# attr Test room RandomTimerX ;
+# define Test RandomTimer +00:00:05 Brunnen +00:05:00 60 ;
+# attr Test room RandomTimerX ;
# attr Test verbose 5 ;
# define ds at +00:00:30 attr Test disable 1 ;
#
# delete RT_Test; define RT_Test RandomTimer *22:00:00 Brunnen 23:00:00 300
-# set RT_Test disable 0
+# set RT_Test disable 0
# delete RT_Test
sub RandomTimer_Exec($) {
my ($myHash) = @_;
-
+
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash));
-
+
my $now = time();
-
+
# Wenn aktiv aber disabled, dann timer abschalten, Meldung ausgeben.
my $active = RandomTimer_isAktive($hash);
my $disabled = RandomTimer_isDisabled($hash);
my $stopTimeReached = RandomTimer_stopTimeReached($hash);
-
+
if ($active) {
# wenn temporär ausgeschaltet
if ($disabled) {
@@ -207,16 +208,16 @@ sub RandomTimer_Exec($) {
RandomTimer_setActive($hash,0);
return;
}
- if (!$disabled) {
+ if (!$disabled) {
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." starting RandomTimer on $hash->{DEVICE}: "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{startTime})) . " - "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime}));
RandomTimer_setActive($hash,1);
- }
+ }
}
}
-
+
RandomTimer_setState($hash);
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) {
RandomTimer_device_toggle($hash) if (!$disabled);
@@ -254,7 +255,7 @@ sub RandomTimer_down($) {
########################################################################
sub RandomTimer_setState($) {
my ($hash) = @_;
-
+
if (RandomTimer_isDisabled($hash)) {
#$hash->{STATE} = "disabled";
readingsSingleUpdate ($hash, "state", "disabled", 0);
@@ -262,20 +263,20 @@ sub RandomTimer_setState($) {
my $state = $hash->{helper}{active} ? "on" : "off";
readingsSingleUpdate ($hash, "state", $state, 1);
}
-
+
}
########################################################################
sub RandomTimer_Attr($$$) {
my ($cmd, $name, $attrName, $attrVal) = @_;
my $hash = $defs{$name};
-
+
if( $attrName ~~ ["switchmode"] ) {
RandomTimer_setSwitchmode($hash, $attrVal);
}
-
+
if( $attrName ~~ ["disable","disableCond"] ) {
-
+
# Schaltung vorziehen, damit bei einem disable abgeschaltet wird.
myRemoveInternalTimer("Exec", $hash);
myInternalTimer ("Exec", time()+1, "RandomTimer_Exec", $hash, 0);
@@ -288,7 +289,7 @@ sub RandomTimer_setSwitchmode ($$) {
my ($hash, $attrVal) = @_;
my $mod = "[".$hash->{NAME} ."] ";
-
+
if(!($attrVal =~ m/^([0-9]{1,3})\/([0-9]{1,3})$/i)) {
Log3 undef, 3, $mod . "invalid switchMode <$attrVal>, use 999/999";
} else {
@@ -317,7 +318,7 @@ sub RandomTimer_schaltZeitenErmitteln ($$) {
RandomTimer_startZeitErmitteln($hash, $now);
RandomTimer_stopZeitErmitteln ($hash, $now);
-
+
readingsBeginUpdate($hash);
readingsBulkUpdate ($hash, "Startzeit", FmtDateTime($hash->{helper}{startTime}));
readingsBulkUpdate ($hash, "Stoppzeit", FmtDateTime($hash->{helper}{stopTime}));
@@ -385,7 +386,7 @@ sub RandomTimer_stopZeitErmitteln ($$) {
} else {
$stopTime = RandomTimer_zeitBerechnen($now, $hour, $min, $sec);
}
-
+
if (!AttrVal($hash->{NAME}, "forceStoptimeSameDay", 0)) {
if ($hash->{helper}{startTime} > $stopTime) {
$stopTime = RandomTimer_addDays($stopTime, 1);
@@ -403,9 +404,9 @@ sub RandomTimer_device_toggle ($) {
if ($status ne "on" && $status ne "off" ) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." result of function Value($hash->{DEVICE}) must be 'on' or 'off'";
}
-
- my $sigma = ($status eq "on")
- ? $hash->{helper}{SIGMAWHENON}
+
+ my $sigma = ($status eq "on")
+ ? $hash->{helper}{SIGMAWHENON}
: $hash->{helper}{SIGMAWHENOFF};
my $zufall = int(rand(1000));
@@ -413,13 +414,13 @@ sub RandomTimer_device_toggle ($) {
if ($zufall < $sigma ) {
$hash->{COMMAND} = ($status eq "on") ? "off" : "on";
- RandomTimer_device_switch($hash);
+ RandomTimer_device_switch($hash);
}
}
########################################################################
sub RandomTimer_device_switch ($) {
my ($hash) = @_;
-
+
my $command = "set @ $hash->{COMMAND}";
if ($hash->{COMMAND} eq "on") {
$command = AttrVal($hash->{NAME}, "onCmd", $command);
@@ -438,17 +439,17 @@ sub RandomTimer_device_switch ($) {
########################################################################
sub RandomTimer_isDisabled($) {
my ($hash) = @_;
-
- my $disable = AttrVal($hash->{NAME}, "disable", 0 );
+
+ my $disable = AttrVal($hash->{NAME}, "disable", 0 );
return $disable if($disable);
-
+
my $disableCond = AttrVal($hash->{NAME}, "disableCond", "nf" );
if ($disableCond eq "nf") {
return 0;
- } else {
+ } else {
$disable = eval ($disableCond);
if ($@) {
- $@ =~ s/\n/ /g;
+ $@ =~ s/\n/ /g;
Log3 ($hash, 3, "[$hash->{NAME}] ERROR: " . $@ . " EVALUATING " . $disableCond);
}
return $disable;
@@ -459,7 +460,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
foreach my $hc ( sort keys %{$modules{RandomTimer}{defptr}} ) {
my $hash = $modules{RandomTimer}{defptr}{$hc};
-
+
my $myHash->{HASH}=$hash;
RandomTimer_SetTimer($myHash);
Log3 undef, 3, "RandomTimer_Wakeup() for $hash->{NAME} done!";
@@ -470,7 +471,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
1;
=pod
-=item device
+=item device
=item summary imitates the random switch functionality of a timer clock (FS20 ZSU)
=item summary_DE bildet die Zufallsfunktion einer Zeitschaltuhr nach
=begin html
@@ -562,7 +563,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
Examples
attr ZufallsTimerZ disableCond (!isVerreist())
- attr ZufallsTimerZ disableCond (Value("presenceDummy") ne "present")
+ attr ZufallsTimerZ disableCond (Value("presenceDummy") ne "present")
@@ -589,8 +590,8 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
- the decision to switch on or off depends on the state of the device and is evaluated by the funktion Value(). Value() must
- evaluate one of the values "on" or "off". The behavior of devices that do not evaluate one of those values can be corrected by defining a statFormat:
+ the decision to switch on or off depends on the state of the device and is evaluated by the funktion Value(). Value() must
+ evaluate one of the values "on" or "off". The behavior of devices that do not evaluate one of those values can be corrected by defining a statFormat:
attr stateFormat EDIPlug_01 {(ReadingsVal("EDIPlug_01","state","nF") =~ m/(ON|on)/i) ? "on" : "off" }
@@ -598,8 +599,8 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
[EDIPlug] result of function Value(EDIPlug_01) must be 'on' or 'off'
-
-
+
+
switchmode
Setting the switchmode you can influence the behavior of switching on/off.
The parameter has the Format 999/999 and the default ist 800/200. The values are in "per mill".
@@ -610,7 +611,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
attr ZufallsTimerZ switchmode 400/400
-
+
=end html
-=cut
\ No newline at end of file
+=cut
diff --git a/fhem/FHEM/98_WeekdayTimer.pm b/fhem/FHEM/98_WeekdayTimer.pm
index 79ac41ca4..9812ad4a3 100644
--- a/fhem/FHEM/98_WeekdayTimer.pm
+++ b/fhem/FHEM/98_WeekdayTimer.pm
@@ -4,6 +4,7 @@
# 98_WeekdayTimer.pm
# written by Dietmar Ortmann
# modified by Tobias Faust
+# Maintained by igami since 02-2018
#
# This file is part of fhem.
#
@@ -45,7 +46,7 @@ sub WeekdayTimer_Initialize($){
$hash->{DefFn} = "WeekdayTimer_Define";
$hash->{UndefFn} = "WeekdayTimer_Undef";
$hash->{GetFn} = "WeekdayTimer_Get";
- $hash->{AttrFn} = "WeekdayTimer_Attr";
+ $hash->{AttrFn} = "WeekdayTimer_Attr";
$hash->{UpdFn} = "WeekdayTimer_Update";
$hash->{AttrList}= "disable:0,1 delayedExecutionCond switchInThePast:0,1 commandTemplate ".
$readingFnAttributes;
@@ -53,30 +54,30 @@ sub WeekdayTimer_Initialize($){
################################################################################
sub WeekdayTimer_InitHelper($) {
my ($hash) = @_;
-
+
$hash->{longDays} = { "de" => ["Sonntag", "Montag","Dienstag","Mittwoch", "Donnerstag","Freitag", "Samstag", "Wochenende", "Werktags" ],
"en" => ["Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "weekend", "weekdays" ],
"fr" => ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi","Samedi", "weekend", "jours de la semaine"]};
- $hash->{shortDays} = { "de" => ["so", "mo", "di", "mi", "do", "fr", "sa", '$we', '!$we' ],
+ $hash->{shortDays} = { "de" => ["so", "mo", "di", "mi", "do", "fr", "sa", '$we', '!$we' ],
"en" => ["su", "mo", "tu", "we", "th", "fr", "sa", '$we', '!$we' ],
"fr" => ["di", "lu", "ma", "me", "je", "ve", "sa", '$we', '!$we' ]};
}
################################################################################
sub WeekdayTimer_Set($@) {
my ($hash, @a) = @_;
-
+
return "no set value specified" if(int(@a) < 2);
return "Unknown argument $a[1], choose one of enable disable " if($a[1] eq "?");
-
+
my $name = shift @a;
my $v = join(" ", @a);
Log3 $hash, 3, "[$name] set $name $v";
-
+
if ($v eq "enable") {
- fhem("attr $name disable 0");
+ fhem("attr $name disable 0");
} elsif ($v eq "disable") {
- fhem("attr $name disable 1");
+ fhem("attr $name disable 1");
}
return undef;
}
@@ -107,7 +108,7 @@ sub WeekdayTimer_Undef($$) {
myRemoveInternalTimer("SetTimerOfDay", $hash);
delete $modules{$hash->{TYPE}}{defptr}{$hash->{NAME}};
return undef;
-}
+}
################################################################################
sub WeekdayTimer_Define($$) {
my ($hash, $def) = @_;
@@ -124,32 +125,32 @@ sub WeekdayTimer_Define($$) {
my $name = shift @a;
my $type = shift @a;
my $device = shift @a;
-
+
WeekdayTimer_DeleteTimer($hash);
- my $delVariables = "(CONDITION|COMMAND|profile|Profil)";
+ my $delVariables = "(CONDITION|COMMAND|profile|Profil)";
map { delete $hash->{$_} if($_=~ m/^$delVariables.*/g) } keys %{$hash};
-
+
my $language = WeekdayTimer_Language ($hash, \@a);
-
- my $idx = 0;
- $hash->{dayNumber} = {map {$_ => $idx++} @{$hash->{shortDays}{$language}}};
+
+ my $idx = 0;
+ $hash->{dayNumber} = {map {$_ => $idx++} @{$hash->{shortDays}{$language}}};
$hash->{helper}{daysRegExp} = '(' . join ("|", @{$hash->{shortDays}{$language}}) . ")";
$hash->{helper}{daysRegExpMessage} = $hash->{helper}{daysRegExp};
-
- $hash->{helper}{daysRegExp} =~ s/\$/\\\$/g;
- $hash->{helper}{daysRegExp} =~ s/\!/\\\!/g;
+
+ $hash->{helper}{daysRegExp} =~ s/\$/\\\$/g;
+ $hash->{helper}{daysRegExp} =~ s/\!/\\\!/g;
WeekdayTimer_GlobalDaylistSpec ($hash, \@a);
$hash->{NAME} = $name;
$hash->{DEVICE} = $device;
-
+
my @switchingtimes = WeekdayTimer_gatherSwitchingTimes ($hash, \@a);
my $conditionOrCommand = join (" ", @a);
# test if device is defined
Log3 ($hash, 3, "[$name] device <$device> in fhem not defined, but accepted") if(!$defs{$device});
-
+
# wenn keine switchintime angegeben ist, dann Fehler
Log3 ($hash, 3, "[$name] no valid Switchingtime found in <$conditionOrCommand>, check first parameter") if (@switchingtimes == 0);
@@ -159,66 +160,66 @@ sub WeekdayTimer_Define($$) {
$defs{$device}{STILLDONETIME} = 0 if($defs{$device});
$modules{$hash->{TYPE}}{defptr}{$hash->{NAME}} = $hash;
-
+
$hash->{CONDITION} = ""; $hash->{COMMAND} = "";
if($conditionOrCommand =~ m/^\(.*\)$/g) { #condition (*)
$hash->{CONDITION} = $conditionOrCommand;
} elsif(length($conditionOrCommand) > 0 ) {
$hash->{COMMAND} = $conditionOrCommand;
}
-
+
WeekdayTimer_Profile ($hash);
delete $hash->{VERZOEGRUNG};
delete $hash->{VERZOEGRUNG_IDX};
-
- $attr{$name}{commandTemplate} =
+
+ $attr{$name}{commandTemplate} =
'set $NAME '. WeekdayTimer_isHeizung($hash) .' $EVENT' if (!defined $attr{$name}{commandTemplate});
-
+
InternalTimer(time(), "$hash->{TYPE}_SetTimer", $hash, 0);
WeekdayTimer_SetTimerForMidnightUpdate( { HASH => $hash} );
-
+
return undef;
}
################################################################################
-sub WeekdayTimer_Profile($) {
+sub WeekdayTimer_Profile($) {
my $hash = shift;
-
+
my $language = $hash->{LANGUAGE};
- my %longDays = %{$hash->{longDays}};
-
+ my %longDays = %{$hash->{longDays}};
+
delete $hash->{profil};
- my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time());
-
- my $now = time();
+ my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time());
+
+ my $now = time();
# ---- Zeitpunkte den Tagen zuordnen -----------------------------------
my $idx = 0;
foreach my $st (@{$hash->{SWITCHINGTIMES}}) {
my ($tage,$time,$parameter) = WeekdayTimer_SwitchingTime ($hash, $st);
-
+
$idx++;
foreach my $d (@{$tage}) {
my @listeDerTage = ($d);
push (@listeDerTage, WeekdayTimer_getListeDerTage($d, $time)) if ($d>=7);
-
- map { my $day = $_;
+
+ map { my $day = $_;
my $dayOfEchteZeit = $day;
- $dayOfEchteZeit = ($wday>=1&&$wday<=5) ? 6 : $wday if ($day==7); # ggf. Samstag $wday ~~ [1..5]
+ $dayOfEchteZeit = ($wday>=1&&$wday<=5) ? 6 : $wday if ($day==7); # ggf. Samstag $wday ~~ [1..5]
$dayOfEchteZeit = ($wday==0||$wday==6) ? 1 : $wday if ($day==8); # ggf. Montag $wday ~~ [0, 6]
- my $echtZeit = WeekdayTimer_EchteZeit($hash, $dayOfEchteZeit, $time);
+ my $echtZeit = WeekdayTimer_EchteZeit($hash, $dayOfEchteZeit, $time);
$hash->{profile} {$day}{$echtZeit} = $parameter;
$hash->{profile_IDX}{$day}{$echtZeit} = $idx;
- } @listeDerTage;
+ } @listeDerTage;
}
}
# ---- Zeitpunkte des aktuellen Tages mit EPOCH ermitteln --------------
$idx = 0;
foreach my $st (@{$hash->{SWITCHINGTIMES}}) {
my ($tage,$time,$parameter) = WeekdayTimer_SwitchingTime ($hash, $st);
- my $echtZeit = WeekdayTimer_EchteZeit ($hash, $wday, $time);
- my ($stunde, $minute, $sekunde) = split (":",$echtZeit);
-
+ my $echtZeit = WeekdayTimer_EchteZeit ($hash, $wday, $time);
+ my ($stunde, $minute, $sekunde) = split (":",$echtZeit);
+
$idx++;
$hash->{profil}{$idx}{TIME} = $time;
$hash->{profil}{$idx}{PARA} = $parameter;
@@ -226,41 +227,41 @@ sub WeekdayTimer_Profile($) {
$hash->{profil}{$idx}{TAGE} = $tage;
}
# ---- Texte Readings aufbauen -----------------------------------------
- Log3 $hash, 4, "[$hash->{NAME}] " . sunrise_abs() . " " . sunset_abs() . " " . $longDays{$language}[$wday];
+ Log3 $hash, 4, "[$hash->{NAME}] " . sunrise_abs() . " " . sunset_abs() . " " . $longDays{$language}[$wday];
foreach my $d (sort keys %{$hash->{profile}}) {
my $profiltext = "";
foreach my $t (sort keys %{$hash->{profile}{$d}}) {
- $profiltext .= "$t " . $hash->{profile}{$d}{$t} . ", ";
+ $profiltext .= "$t " . $hash->{profile}{$d}{$t} . ", ";
}
my $profilKey = "Profil $d: $longDays{$language}[$d]";
$profiltext =~ s/, $//;
$hash->{$profilKey} = $profiltext;
- Log3 $hash, 4, "[$hash->{NAME}] $profiltext ($profilKey)";
+ Log3 $hash, 4, "[$hash->{NAME}] $profiltext ($profilKey)";
}
# für logProxy umhaengen
$hash->{helper}{SWITCHINGTIME} = $hash->{profile};
delete $hash->{profile};
}
-################################################################################
+################################################################################
sub WeekdayTimer_getListeDerTage($$) {
my ($d, $time) = @_;
my %hdays=();
@hdays{(0, 6)} = undef if ($d==7); # sa,so ( $we)
@hdays{(1..5)} = undef if ($d==8); # mo-fr (!$we)
-
+
my $wday;
my $now = time();
my ($sec,$min,$hour,$mday,$mon,$year,$nowWday,$yday,$isdst) = localtime($now);
-
- my @realativeWdays = (0..6);
+
+ my @realativeWdays = (0..6);
for (my $i=0;$i<=6;$i++) {
my $relativeDay = $i-$nowWday;
#Log 3, "relativeDay------------>$relativeDay";
- my ($stunde, $minute, $sekunde) = split (":",$time);
-
+ my ($stunde, $minute, $sekunde) = split (":",$time);
+
my $echteZeit = WeekdayTimer_zeitErmitteln ($now, $stunde, $minute, $sekunde, $relativeDay);
#Log 3, "echteZeit---$i---->>>$relativeDay<<<----->".FmtDateTime($echteZeit);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($echteZeit);
@@ -273,23 +274,23 @@ sub WeekdayTimer_getListeDerTage($$) {
delete $hdays{$i} if ($d==8); # !$we Tag herausnehmen
}
}
- }
-
+ }
+
#Log 3, "result------------>" . join (" ", sort keys %hdays);
return keys %hdays;
}
-################################################################################
+################################################################################
sub WeekdayTimer_SwitchingTime($$) {
my ($hash, $switchingtime) = @_;
-
+
my $name = $hash->{NAME};
my $globalDaylistSpec = $hash->{GlobalDaylistSpec};
- my @tageGlobal = @{WeekdayTimer_daylistAsArray($hash, $globalDaylistSpec)};
-
+ my @tageGlobal = @{WeekdayTimer_daylistAsArray($hash, $globalDaylistSpec)};
+
my (@st, $daylist, $time, $timeString, $para);
@st = split(/\|/, $switchingtime);
-
- if ( @st == 2) {
+
+ if ( @st == 2) {
$daylist = ($globalDaylistSpec gt "") ? $globalDaylistSpec : "0123456";
$time = $st[0];
$para = $st[1];
@@ -298,39 +299,39 @@ sub WeekdayTimer_SwitchingTime($$) {
$time = $st[1];
$para = $st[2];
}
-
- my @tage = @{WeekdayTimer_daylistAsArray($hash, $daylist)};
+
+ my @tage = @{WeekdayTimer_daylistAsArray($hash, $daylist)};
my $tage=@tage;
if ( $tage==0 ) {
Log3 ($hash, 1, "[$name] invalid daylist in $name <$daylist> use one of 012345678 or $hash->{helper}{daysRegExpMessage}");
- }
+ }
my %hdays=();
@hdays{@tageGlobal} = undef;
@hdays{@tage} = undef;
@tage = sort keys %hdays;
-
+
#Log3 $hash, 3, "Tage: " . Dumper \@tage;
return (\@tage,$time,$para);
}
-################################################################################
+################################################################################
sub WeekdayTimer_daylistAsArray($$){
my ($hash, $daylist) = @_;
-
+
my $name = $hash->{NAME};
my @days;
-
+
my %hdays=();
- $daylist = lc($daylist);
+ $daylist = lc($daylist);
# Angaben der Tage verarbeiten
# Aufzaehlung 1234 ...
if ( $daylist =~ m/^[0-8]{0,9}$/g) {
-
- Log3 ($hash, 3, "[$name] " . '"7" in daylist now means $we(weekend) - see dokumentation!!!' )
+
+ Log3 ($hash, 3, "[$name] " . '"7" in daylist now means $we(weekend) - see dokumentation!!!' )
if (index($daylist, '7') != -1);
-
+
@days = split("", $daylist);
@hdays{@days} = undef;
@@ -340,11 +341,11 @@ sub WeekdayTimer_daylistAsArray($$){
my @aufzaehlungen = split (",", $daylist);
foreach my $einzelAufzaehlung (@aufzaehlungen) {
my @days = split ("-", $einzelAufzaehlung);
- my $days = @days;
+ my $days = @days;
if ($days == 1) {
#einzelner Tag: Sa
- $hdays{$hash->{dayNumber}{$days[0]}} = undef;
- } else {
+ $hdays{$hash->{dayNumber}{$days[0]}} = undef;
+ } else {
# von bis Angabe: Mo-Di
my $von = $hash->{dayNumber}{$days[0]};
my $bis = $hash->{dayNumber}{$days[1]};
@@ -354,38 +355,38 @@ sub WeekdayTimer_daylistAsArray($$){
#@subDays = ($dayNumber{so} .. $bis, $von .. $dayNumber{sa});
@subDays = ( 00 .. $bis, $von .. 06);
}
- @hdays{@subDays}=undef;
+ @hdays{@subDays}=undef;
}
}
} else{
%hdays = ();
}
-
+
my @tage = sort keys %hdays;
return \@tage;
}
-################################################################################
+################################################################################
sub WeekdayTimer_EchteZeit($$$) {
- my ($hash, $d, $time) = @_;
-
+ my ($hash, $d, $time) = @_;
+
my $name = $hash->{NAME};
-
+
my $now = time();
- my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
+ my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
my $listOfDays = "";
- # Zeitangabe verarbeiten.
- $time = '"' . "$time" . '"' if($time !~ m/^\{.*\}$/g);
+ # Zeitangabe verarbeiten.
+ $time = '"' . "$time" . '"' if($time !~ m/^\{.*\}$/g);
my $date = $now+($d-$wday)*86400;
- my $timeString = '{ my $date='."$date;" .$time."}";
+ my $timeString = '{ my $date='."$date;" .$time."}";
my $eTimeString = eval( $timeString ); # must deliver HH:MM[:SS]
if ($@) {
- $@ =~ s/\n/ /g;
+ $@ =~ s/\n/ /g;
Log3 ($hash, 3, "[$name] " . $@ . ">>>$timeString<<<");
$eTimeString = "00:00:00";
}
-
+
if ($eTimeString =~ m/^[0-2][0-9]:[0-5][0-9]$/g) { # HH:MM
$eTimeString .= ":00"; # HH:MM:SS erzeugen
} elsif ($eTimeString =~ m/^[0-2][0-9](:[0-5][0-9]){2,2}$/g) { # HH:MM:SS
@@ -415,7 +416,7 @@ sub WeekdayTimer_gatherSwitchingTimes {
my $name = $hash->{NAME};
my @switchingtimes = ();
my $conditionOrCommand;
-
+
# switchingtime einsammeln
while (@$a > 0) {
@@ -423,16 +424,16 @@ sub WeekdayTimer_gatherSwitchingTimes {
my $element = "";
my @restoreElements = ();
E: while (@$a > 0) {
-
+
my $actualElement = shift @$a;
- push @restoreElements, $actualElement;
+ push @restoreElements, $actualElement;
$element = $element . $actualElement . " ";
Log3 $hash, 5, "[$name] $element - trying to accept as a switchtime";
-
+
# prüfen ob Anführungszeichen paarig sind
- my @quotes = ('"', "'" );
+ my @quotes = ('"', "'" );
foreach my $quote (@quotes){
- my $balancedSign = eval "((\$element =~ tr/$quote//))";
+ my $balancedSign = eval "((\$element =~ tr/$quote//))";
if ($balancedSign % 2) { # ungerade Anzahl quotes, dann verlängern
Log3 $hash, 5, "[$name] $element - unbalanced quotes: $balancedSign $quote found";
next E;
@@ -440,10 +441,10 @@ E: while (@$a > 0) {
}
# prüfen ob öffnende/schliessende Klammern paarig sind
- my %signs = ('('=>')', '{'=>'}');
+ my %signs = ('('=>')', '{'=>'}');
foreach my $signOpened (keys(%signs)) {
my $signClosed = $signs{$signOpened};
- my $balancedSign = eval "((\$element =~ tr/$signOpened//) - (\$element =~ tr/$signClosed//))";
+ my $balancedSign = eval "((\$element =~ tr/$signOpened//) - (\$element =~ tr/$signClosed//))";
if ($balancedSign) { # öffnende/schließende Klammern nicht gleich, dann verlängern
Log3 $hash, 5, "[$name] $element - unbalanced brackets $signOpened$signClosed:$balancedSign";
next E;
@@ -451,18 +452,18 @@ E: while (@$a > 0) {
}
last;
}
-
+
# ein space am Ende wieder abschneiden
$element = substr ($element, 0, length($element)-1);
my @t = split(/\|/, $element);
my $anzahl = @t;
-
+
if ( ($anzahl == 2 || $anzahl == 3) && $t[0] gt "" && $t[1] gt "" ) {
Log3 $hash, 4, "[$name] $element - accepted";
push(@switchingtimes, $element);
} else {
Log3 $hash, 4, "[$name] $element - NOT accepted, must be command or condition";
- unshift @$a, @restoreElements;
+ unshift @$a, @restoreElements;
last;
}
}
@@ -471,8 +472,8 @@ E: while (@$a > 0) {
################################################################################
sub WeekdayTimer_Language {
my ($hash, $a) = @_;
-
- my $name = $hash->{NAME};
+
+ my $name = $hash->{NAME};
# ggf. language optional Parameter
my $langRegExp = "(" . join ("|", keys(%{$hash->{shortDays}})) . ")";
@@ -481,7 +482,7 @@ sub WeekdayTimer_Language {
if ($language =~ m/^$langRegExp$/g) {
} else {
Log3 ($hash, 3, "[$name] language: $language not recognized, use one of $langRegExp") if (length($language) == 2);
- unshift @$a, $language;
+ unshift @$a, $language;
$language = "de";
}
$hash->{LANGUAGE} = $language;
@@ -492,18 +493,18 @@ sub WeekdayTimer_Language {
################################################################################
sub WeekdayTimer_GlobalDaylistSpec {
my ($hash, $a) = @_;
-
+
my $daylist = shift @$a;
- my @tage = @{WeekdayTimer_daylistAsArray($hash, $daylist)};
- my $tage = @tage;
+ my @tage = @{WeekdayTimer_daylistAsArray($hash, $daylist)};
+ my $tage = @tage;
if ($tage > 0) {
;
} else {
- unshift (@$a,$daylist);
+ unshift (@$a,$daylist);
$daylist = "";
}
-
+
$hash->{GlobalDaylistSpec} = $daylist;
}
################################################################################
@@ -514,7 +515,7 @@ sub WeekdayTimer_SetTimerForMidnightUpdate($) {
my $now = time();
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now);
-
+
my $midnightPlus5Seconds = WeekdayTimer_zeitErmitteln ($now, 0, 0, 5, 1);
#Log3 $hash, 3, "midnightPlus5Seconds------------>".FmtDateTime($midnightPlus5Seconds);
@@ -528,120 +529,120 @@ sub WeekdayTimer_SetTimerOfDay($) {
my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash));
-
+
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());
- my $secSinceMidnight = 3600*$hour + 60*$min + $sec;
-
+ my $secSinceMidnight = 3600*$hour + 60*$min + $sec;
+
$hash->{SETTIMERATMIDNIGHT} = $myHash->{SETTIMERATMIDNIGHT};
WeekdayTimer_DeleteTimer($hash);
WeekdayTimer_Profile ($hash);
WeekdayTimer_SetTimer ($hash);
delete $hash->{SETTIMERATMIDNIGHT};
-
+
WeekdayTimer_SetTimerForMidnightUpdate( { HASH => $hash} );
}
################################################################################
sub WeekdayTimer_SetTimer($) {
- my $hash = shift;
+ my $hash = shift;
my $name = $hash->{NAME};
-
- my $now = time();
-
+
+ my $now = time();
+
my $isHeating = WeekdayTimer_isHeizung($hash);
my $swip = AttrVal($name, "switchInThePast", 0);
my $switchInThePast = ($swip || $isHeating);
-
+
Log3 $hash, 4, "[$name] Heating recognized - switch in the past activated" if ($isHeating);
Log3 $hash, 4, "[$name] no switch in the yesterdays because of the devices type($hash->{DEVICE} is not recognized as heating) - use attr switchInThePast" if (!$switchInThePast && !defined $hash->{SETTIMERATMIDNIGHT});
-
+
my @switches = sort keys %{$hash->{profil}};
if ($#switches < 0) {
Log3 $hash, 3, "[$name] no switches to send, due to possible errors.";
- return;
- }
-
+ return;
+ }
+
readingsSingleUpdate ($hash, "state", "inactive", 1) if (!defined $hash->{SETTIMERATMIDNIGHT});
for(my $i=0; $i<=$#switches; $i++) {
-
+
my $idx = $switches[$i];
-
+
my $time = $hash->{profil}{$idx}{TIME};
my $timToSwitch = $hash->{profil}{$idx}{EPOCH};
my $tage = $hash->{profil}{$idx}{TAGE};
my $para = $hash->{profil}{$idx}{PARA};
-
+
my $secondsToSwitch = $timToSwitch - $now;
-
+
my $isActiveTimer = WeekdayTimer_isAnActiveTimer ($hash, $tage, $para);
- readingsSingleUpdate ($hash, "state", "active", 1)
+ readingsSingleUpdate ($hash, "state", "active", 1)
if (!defined $hash->{SETTIMERATMIDNIGHT} && $isActiveTimer);
-
+
if ($secondsToSwitch>-5 || defined $hash->{SETTIMERATMIDNIGHT} ) {
- if($isActiveTimer) {
+ if($isActiveTimer) {
Log3 $hash, 4, "[$name] setTimer - timer seems to be active today: ".join("",@$tage)."|$time|$para";
- } else {
+ } else {
Log3 $hash, 4, "[$name] setTimer - timer seems to be NOT active today: ".join("",@$tage)."|$time|$para ". $hash->{CONDITION};
}
- myRemoveInternalTimer("$idx", $hash);
+ myRemoveInternalTimer("$idx", $hash);
myInternalTimer ("$idx", $timToSwitch, "$hash->{TYPE}_Update", $hash, 0);
}
}
-
+
if (defined $hash->{SETTIMERATMIDNIGHT}) {
return;
}
-
- my ($aktIdx,$aktTime,$aktParameter,$nextTime,$nextParameter) =
+
+ my ($aktIdx,$aktTime,$aktParameter,$nextTime,$nextParameter) =
WeekdayTimer_searchAktNext($hash, time()+5);
- if(!defined $aktTime) {
- Log3 $hash, 3, "[$name] can not compute past switching time";
- }
-
+ if(!defined $aktTime) {
+ Log3 $hash, 3, "[$name] can not compute past switching time";
+ }
+
readingsSingleUpdate ($hash, "nextUpdate", FmtDateTime($nextTime), 1);
- readingsSingleUpdate ($hash, "nextValue", $nextParameter, 1);
- readingsSingleUpdate ($hash, "currValue", $aktParameter, 1); # HB
-
- if ($switchInThePast && defined $aktTime) {
+ readingsSingleUpdate ($hash, "nextValue", $nextParameter, 1);
+ readingsSingleUpdate ($hash, "currValue", $aktParameter, 1); # HB
+
+ if ($switchInThePast && defined $aktTime) {
# Fensterkontakte abfragen - wenn einer im Status closed, dann Schaltung um 60 Sekunden verzögern
if (WeekdayTimer_FensterOffen($hash, $aktParameter, $aktIdx)) {
return;
}
-
- # alle in der Vergangenheit liegenden Schaltungen sammeln und
- # nach 5 Sekunden in der Reihenfolge der Schaltzeiten
+
+ # alle in der Vergangenheit liegenden Schaltungen sammeln und
+ # nach 5 Sekunden in der Reihenfolge der Schaltzeiten
# durch WeekdayTimer_delayedTimerInPast() als Timer einstellen
- # die Parameter merken wir uns kurzzeitig im hash
+ # die Parameter merken wir uns kurzzeitig im hash
# modules{WeekdayTimer}{timerInThePast}
my $device = $hash->{DEVICE};
- Log3 $hash, 4, "[$name] past timer on $hash->{DEVICE} at ". FmtDateTime($aktTime). " with $aktParameter activated";
-
+ Log3 $hash, 4, "[$name] past timer on $hash->{DEVICE} at ". FmtDateTime($aktTime). " with $aktParameter activated";
+
my $parameter = $modules{WeekdayTimer}{timerInThePast}{$device}{$aktTime};
$parameter = [] if (!defined $parameter);
push (@$parameter,["$aktIdx", $aktTime, "$hash->{TYPE}_Update", $hash, 0]);
$modules{WeekdayTimer}{timerInThePast}{$device}{$aktTime} = $parameter;
-
+
my $tipHash = $modules{WeekdayTimer}{timerInThePastHash};
$tipHash = $hash if (!defined $tipHash);
$modules{WeekdayTimer}{timerInThePastHash} = $tipHash;
-
+
myRemoveInternalTimer("delayed", $tipHash);
myInternalTimer ("delayed", time()+5, "WeekdayTimer_delayedTimerInPast", $tipHash, 0);
-
- }
+
+ }
}
################################################################################
sub WeekdayTimer_delayedTimerInPast($) {
my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash));
-
+
my $tim = time();
my $tipIpHash = $modules{WeekdayTimer}{timerInThePast};
foreach my $device ( keys %$tipIpHash ) {
foreach my $time ( sort keys %{$tipIpHash->{$device}} ) {
Log3 $hash, 4, "$device ".FmtDateTime($time)." ".($tim-$time)."s ";
-
+
foreach my $para ( @{$tipIpHash->{$device}{$time}} ) {
myRemoveInternalTimer(@$para[0], @$para[3]);
my $mHash =myInternalTimer (@$para[0],@$para[1],@$para[2],@$para[3],@$para[4]);
@@ -651,55 +652,55 @@ sub WeekdayTimer_delayedTimerInPast($) {
}
delete $modules{WeekdayTimer}{timerInThePast};
delete $modules{WeekdayTimer}{timerInThePastHash}
-}
+}
################################################################################
sub WeekdayTimer_searchAktNext($$) {
my ($hash, $now) = @_;
my $name = $hash->{NAME};
-
+
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now);
#Log3 $hash, 3, "[$name] such--->".FmtDateTime($now);
-
+
my ($oldTag, $oldTime, $oldPara , $oldIdx);
my ($nextTag, $nextTime, $nextPara, $nextIdx);
-
+
my $language = $hash->{LANGUAGE};
my %shortDays = %{$hash->{shortDays}};
-
- my @realativeWdays = ($wday..6,0..$wday-1,$wday..6,0..6);
+
+ my @realativeWdays = ($wday..6,0..$wday-1,$wday..6,0..6);
for (my $i=0;$i<=$#realativeWdays;$i++) {
-
+
my $relativeDay = $i-7;
my $relWday = $realativeWdays[$i];
-
+
foreach my $time (sort keys %{$hash->{helper}{SWITCHINGTIME}{$relWday}}) {
- my ($stunde, $minute, $sekunde) = split (":",$time);
-
+ my ($stunde, $minute, $sekunde) = split (":",$time);
+
$oldTime = $nextTime;
- $oldPara = $nextPara;
+ $oldPara = $nextPara;
$oldIdx = $nextIdx;
$oldTag = $nextTag;
-
+
$nextTime = WeekdayTimer_zeitErmitteln ($now, $stunde, $minute, $sekunde, $relativeDay);
$nextPara = $hash->{helper}{SWITCHINGTIME}{$relWday}{$time};
$nextIdx = $hash->{profile_IDX}{$relWday}{$time};
$nextTag = $relWday;
-
+
#Log3 $hash, 3, $shortDays{$language}[$nextTag]." ".FmtDateTime($nextTime)." ".$nextPara." ".$nextIdx;
-
+
if ($nextTime >= $now) {
#Log3 $hash, 3, "oldIdx------------->$oldIdx";
#Log3 $hash, 3, "oldTime------------>".FmtDateTime($oldTime);
#Log3 $hash, 3, "oldPara------------>$oldPara";
return ($oldIdx, $oldTime, $oldPara, $nextTime, $nextPara);
}
- }
- }
- return (undef,undef,undef,undef);
-}
+ }
+ }
+ return (undef,undef,undef,undef);
+}
################################################################################
sub WeekdayTimer_DeleteTimer($) {
- my $hash = shift;
+ my $hash = shift;
map {myRemoveInternalTimer ($_, $hash)} keys %{$hash->{profil}};
}
################################################################################
@@ -707,13 +708,13 @@ sub WeekdayTimer_Update($) {
my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash));
-
+
my $name = $hash->{NAME};
my $idx = $myHash->{MODIFIER};
my $now = time();
-
+
#my $sollZeit = $myHash->{TIME};
-
+
#my $setModifier = WeekdayTimer_isHeizung($hash);
#my $isHeating = $setModifier gt "";
@@ -722,22 +723,22 @@ sub WeekdayTimer_Update($) {
my $time = $hash->{profil}{$idx}{TIME};
#my $newParam = WeekdayTimer_evalAndcleanupParam($hash,$time,$hash->{profil}{$idx}{PARA}, $isHeating );
my $newParam = $hash->{profil}{$idx}{PARA};
-
+
#Log3 $hash, 3, "[$name] $idx ". $time . " " . $newParam . " " . join("",@$tage);
-
+
# Fenserkontakte abfragen - wenn einer im Status closed, dann Schaltung um 60 Sekunden verzögern
if (WeekdayTimer_FensterOffen($hash, $newParam, $idx)) {
readingsSingleUpdate ($hash, "state", "open window", 1);
return;
}
-
+
my $dieGanzeWoche = [7,8];
my ($activeTimer, $activeTimerState);
if (defined $myHash->{immerSchalten}) {
$activeTimer = WeekdayTimer_isAnActiveTimer ($hash, $dieGanzeWoche, $newParam);
$activeTimerState = WeekdayTimer_isAnActiveTimer ($hash, $tage, $newParam);
Log3 $hash, 4, "[$name] Update - past timer activated";
- } else {
+ } else {
$activeTimer = WeekdayTimer_isAnActiveTimer ($hash, $tage, $newParam);
$activeTimerState = $activeTimer;
Log3 $hash, 4, "[$name] Update - timer seems to be active today: ".join("",@$tage)."|$time|$newParam" if($activeTimer);
@@ -746,13 +747,13 @@ sub WeekdayTimer_Update($) {
#Log3 $hash, 3, "activeTimerState------->$activeTimerState";
my ($aktIdx, $aktTime, $aktParameter, $nextTime, $nextParameter) =
WeekdayTimer_searchAktNext($hash, time()+5);
-
- my $device = $hash->{DEVICE};
+
+ my $device = $hash->{DEVICE};
my $disabled = AttrVal($hash->{NAME}, "disable", 0);
-
+
# ggf. Device schalten
WeekdayTimer_Device_Schalten($hash, $newParam, $tage) if($activeTimer);
-
+
readingsBeginUpdate($hash);
readingsBulkUpdate ($hash, "nextUpdate", FmtDateTime($nextTime));
readingsBulkUpdate ($hash, "nextValue", $nextParameter);
@@ -760,22 +761,22 @@ sub WeekdayTimer_Update($) {
readingsBulkUpdate ($hash, "state", $newParam ) if($activeTimerState);
readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1));
- return 1;
-
+ return 1;
+
}
################################################################################
sub WeekdayTimer_isAnActiveTimer ($$$) {
my ($hash, $tage, $newParam) = @_;
-
+
my $name = $hash->{NAME};
my %specials = ( "%NAME" => $hash->{DEVICE}, "%EVENT" => $newParam);
-
+
my $condition = WeekdayTimer_Condition ($hash, $tage);
my $tageAsHash = WeekdayTimer_tageAsHash($hash, $tage);
my $xPression = "{".$tageAsHash.";;".$condition ."}";
- $xPression = EvalSpecials($xPression, %specials);
+ $xPression = EvalSpecials($xPression, %specials);
Log3 $hash, 5, "[$name] condition: $xPression";
-
+
my $ret = AnalyzeCommandChain(undef, $xPression);
#Log3 $hash, 3, "[$name] condition:>>>$ret<<< $xPression";
Log3 $hash, 5, "[$name] result of condition:$ret";
@@ -787,32 +788,32 @@ sub WeekdayTimer_isHeizung($) {
my ($hash) = @_;
my $name = $hash->{NAME};
-
- my $dHash = $defs{$hash->{DEVICE}};
+
+ my $dHash = $defs{$hash->{DEVICE}};
return "" if (!defined $dHash); # vorzeitiges Ende wenn das device nicht existiert
my $dType = $dHash->{TYPE};
- return "" if (!defined($dType) || $dType eq "dummy" );
-
+ return "" if (!defined($dType) || $dType eq "dummy" );
+
my $dName = $dHash->{NAME};
-
- my @tempSet = ("desired-temp", "desiredTemperature", "desired", "thermostatSetpointSet");
+
+ my @tempSet = ("desired-temp", "desiredTemperature", "desired", "thermostatSetpointSet");
my $allSets = getAllSets($dName);
-
+
foreach my $ts (@tempSet) {
if ($allSets =~ m/$ts/) {
- Log3 $hash, 4, "[$name] device type heating recognized, setModifier:$ts";
- return $ts
+ Log3 $hash, 4, "[$name] device type heating recognized, setModifier:$ts";
+ return $ts
}
- }
-
+ }
+
}
################################################################################
#
sub WeekdayTimer_FensterOffen ($$$) {
my ($hash, $event, $time) = @_;
my $name = $hash->{NAME};
-
+
my %specials = (
'%HEATING_CONTROL' => $hash->{NAME},
'%WEEKDAYTIMER' => $hash->{NAME},
@@ -825,26 +826,26 @@ sub WeekdayTimer_FensterOffen ($$$) {
'$EVENT' => $event,
'$TIME' => $hash->{profil}{$time}{TIME},
);
-
+
my $verzoegerteAusfuehrungCond = AttrVal($hash->{NAME}, "delayedExecutionCond", "0");
#$verzoegerteAusfuehrungCond = 'xxx(%WEEKDAYTIMER,%NAME,%HEATING_CONTROL,$WEEKDAYTIMER,$EVENT,$NAME,$HEATING_CONTROL)';
- my $nextRetry = time()+55+int(rand(10));
+ my $nextRetry = time()+55+int(rand(10));
my $epoch = $hash->{profil}{$time}{EPOCH};
my $delay = int(time()) - $epoch;
my $nextDelay = int($delay/60.+1.5)*60; # round to multiple of 60sec
$nextRetry = $epoch + $nextDelay;
Log3 $hash, 4, "[$name] time=".$hash->{profil}{$time}{TIME}."/$epoch delay=$delay, nextDelay=$nextDelay, nextRetry=$nextRetry";
-
+
map { my $key = $_; $key =~ s/\$/\\\$/g;
- my $val = $specials{$_};
- $verzoegerteAusfuehrungCond =~ s/$key/$val/g
+ my $val = $specials{$_};
+ $verzoegerteAusfuehrungCond =~ s/$key/$val/g
} keys %specials;
Log3 $hash, 4, "[$name] delayedExecutionCond:$verzoegerteAusfuehrungCond";
-
+
my $verzoegerteAusfuehrung = eval($verzoegerteAusfuehrungCond);
Log3 $hash, 4, "[$name] result of delayedExecutionCond:$verzoegerteAusfuehrung";
-
+
if ($verzoegerteAusfuehrung) {
if (!defined($hash->{VERZOEGRUNG})) {
Log3 $hash, 3, "[$name] switch of $hash->{DEVICE} delayed - delayedExecutionCond: '$verzoegerteAusfuehrungCond' is TRUE";
@@ -859,7 +860,7 @@ sub WeekdayTimer_FensterOffen ($$$) {
$hash->{VERZOEGRUNG} = 1;
return 1;
}
-
+
my %contacts = ( "CUL_FHTTK" => { "READING" => "Window", "STATUS" => "(Open)", "MODEL" => "r" },
"CUL_HM" => { "READING" => "state", "STATUS" => "(open|tilted)", "MODEL" => "r" },
"EnOcean" => { "READING" => "state", "STATUS" => "(open)", "MODEL" => "r" },
@@ -868,11 +869,11 @@ sub WeekdayTimer_FensterOffen ($$$) {
"WeekdayTimer" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" },
"Heating_Control" => { "READING" => "delayedExecution","STATUS" => "^1\$", "MODEL" => "a" }
);
-
+
my $fensterKontakte = AttrVal($hash->{NAME}, "windowSensor", "")." ".$hash->{NAME};
$fensterKontakte =~ s/^\s+//;
$fensterKontakte =~ s/\s+$//;
-
+
Log3 $hash, 4, "[$name] list of window sensors found: '$fensterKontakte'";
if ($fensterKontakte ne "" ) {
my @kontakte = split("[ \t]+", $fensterKontakte);
@@ -885,18 +886,18 @@ sub WeekdayTimer_FensterOffen ($$$) {
if (!defined($contacts{$fk_typ})) {
Log3 $hash, 3, "[$name] TYPE '$fk_typ' of $fk not yet supported, $fk ignored - inform maintainer";
} else {
-
+
my $reading = $contacts{$fk_typ}{READING};
my $statusReg = $contacts{$fk_typ}{STATUS};
my $model = $contacts{$fk_typ}{MODEL};
-
+
my $windowStatus;
if ($model eq "r") { ### Reading, sonst Attribut
$windowStatus = ReadingsVal($fk,$reading,"nF");
}else{
- $windowStatus = AttrVal ($fk,$reading,"nF");
+ $windowStatus = AttrVal ($fk,$reading,"nF");
}
-
+
if ($windowStatus eq "nF") {
Log3 $hash, 3, "[$name] Reading/Attribute '$reading' of $fk not found, $fk ignored - inform maintainer" if ($model eq "r");
} else {
@@ -931,19 +932,19 @@ sub WeekdayTimer_FensterOffen ($$$) {
################################################################################
sub WeekdayTimer_evalAndcleanupParam($$$$) {
my ($hash,$time,$param,$isHeating) = @_;
-
+
my $name = $hash->{DEVICE} ;
my $wdName = $hash->{NAME};
-
+
my $newParam = $param;
if ($param =~ m/^{.*}$/) {
-
+
Log3 $hash, 4, "[$wdName] calculating dynamic param before all: ....... $newParam";
-
+
$newParam =~ s/\$NAME/$hash->{DEVICE}/g;
- $newParam =~ s/\$TIME/$time/g;
+ $newParam =~ s/\$TIME/$time/g;
Log3 $hash, 4, "[$wdName] calculating dynamic param after substitutions: $newParam";
-
+
$newParam = eval $newParam;
if ($@ || not defined $newParam) {
Log3 $hash, 1, "[$wdName] problem calculating dynamic param: ........... $param";
@@ -951,7 +952,7 @@ sub WeekdayTimer_evalAndcleanupParam($$$$) {
} else {
Log3 $hash, 4, "[$wdName] calculating dynamic param after eval: ........ $newParam";
}
-
+
}elsif($isHeating && $param =~ m/^\d{1,3}$/){
$newParam = sprintf("%.1f", $param);
}
@@ -963,20 +964,20 @@ sub WeekdayTimer_Device_Schalten($$$) {
my ($command, $condition, $tageAsHash) = "";
my $name = $hash->{NAME}; ###
- my $dummy = "";
-
+ my $dummy = "";
+
my $now = time();
#modifier des Zieldevices auswaehlen
my $setModifier = WeekdayTimer_isHeizung($hash);
-
- $attr{$name}{commandTemplate} =
+
+ $attr{$name}{commandTemplate} =
'set $NAME '. $setModifier .' $EVENT' if (!defined $attr{$name}{commandTemplate});
$command = AttrVal($hash->{NAME}, "commandTemplate", "commandTemplate not found");
$command = $hash->{COMMAND} if ($hash->{COMMAND} gt "");
my $activeTimer = 1;
-
+
my $isHeating = $setModifier gt "";
my $aktParam = ReadingsVal($hash->{DEVICE}, $setModifier, "");
$aktParam = sprintf("%.1f", $aktParam) if ($isHeating && $aktParam =~ m/^[0-9]{1,3}$/i);
@@ -989,93 +990,93 @@ sub WeekdayTimer_Device_Schalten($$$) {
Log3 $hash, 4, "[$name] aktParam:$aktParam newParam:$newParam - is $disabled_txt disabled";
#Kommando ausführen
- if ($command && !$disabled && $activeTimer
- && $aktParam ne $newParam
+ if ($command && !$disabled && $activeTimer
+ && $aktParam ne $newParam
) {
$newParam =~ s/\\:/|/g;
$newParam =~ s/:/ /g;
$newParam =~ s/\|/:/g;
-
+
my %specials = ( "%NAME" => $hash->{DEVICE}, "%EVENT" => $newParam);
$command= EvalSpecials($command, %specials);
-
+
Log3 $hash, 4, "[$name] command: '$command' executed with ".join(",", map { "$_=>$specials{$_}" } keys %specials);
my $ret = AnalyzeCommandChain(undef, $command);
Log3 ($hash, 3, $ret) if($ret);
- }
+ }
}
################################################################################
sub WeekdayTimer_tageAsHash($$) {
- my ($hash, $tage) = @_;
-
+ my ($hash, $tage) = @_;
+
my %days = map {$_ => 1} @$tage;
- map {delete $days{$_}} (7,8);
-
+ map {delete $days{$_}} (7,8);
+
return 'my $days={};map{$days->{$_}=1}'.'('.join (",", sort keys %days).')';
}
################################################################################
-sub WeekdayTimer_Condition($$) {
+sub WeekdayTimer_Condition($$) {
my ($hash, $tage) = @_;
-
- my $name = $hash->{NAME};
+
+ my $name = $hash->{NAME};
Log3 $hash, 4, "[$name] condition:$hash->{CONDITION} - Tage:".join(",",@$tage);
-
+
my $condition = "( ";
- $condition .= ($hash->{CONDITION} gt "") ? $hash->{CONDITION} : 1 ;
+ $condition .= ($hash->{CONDITION} gt "") ? $hash->{CONDITION} : 1 ;
$condition .= " && " . WeekdayTimer_TageAsCondition($tage);
$condition .= ")";
-
+
return $condition;
-
+
}
################################################################################
sub WeekdayTimer_TageAsCondition ($) {
my $tage = shift;
-
+
my %days = map {$_ => 1} @$tage;
-
+
my $we = $days{7}; delete $days{7}; # $we
my $notWe = $days{8}; delete $days{8}; #!$we
-
+
my $tageExp = '(defined $days->{$wday}';
- $tageExp .= ' || $we' if defined $we;
+ $tageExp .= ' || $we' if defined $we;
$tageExp .= ' || !$we' if defined $notWe;
$tageExp .= ')';
-
+
return $tageExp;
-
+
}
################################################################################
sub WeekdayTimer_Attr($$$$) {
my ($cmd, $name, $attrName, $attrVal) = @_;
- $attrVal = 0 if(!defined $attrVal);
-
+ $attrVal = 0 if(!defined $attrVal);
+
my $hash = $defs{$name};
if( $attrName eq "disable" ) {
readingsSingleUpdate ($hash, "disabled", $attrVal, 1);
} elsif ( $attrName eq "enable" ) {
- WeekdayTimer_SetTimerOfDay({ HASH => $hash});
+ WeekdayTimer_SetTimerOfDay({ HASH => $hash});
} elsif ( $attrName eq "switchInThePast" ) {
- $attr{$name}{$attrName} = $attrVal;
- WeekdayTimer_SetTimerOfDay({ HASH => $hash});
+ $attr{$name}{$attrName} = $attrVal;
+ WeekdayTimer_SetTimerOfDay({ HASH => $hash});
}
return undef;
}
########################################################################
sub WeekdayTimer_SetParm($) {
my ($name) = @_;
-
+
my $hash = $modules{WeekdayTimer}{defptr}{$name};
if(defined $hash) {
WeekdayTimer_DeleteTimer($hash);
WeekdayTimer_SetTimer($hash);
- }
+ }
}
################################################################################
sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
- my @wdNamen = sort keys %{$modules{WeekdayTimer}{defptr}};
+ my @wdNamen = sort keys %{$modules{WeekdayTimer}{defptr}};
foreach my $wdName ( @wdNamen ) {
WeekdayTimer_SetParm($wdName);
}
@@ -1087,7 +1088,7 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
=pod
=item device
=item summary sends parameter to devices at defined times
-=item summary_DE sendet Parameter an devices zu einer Liste mit festen Zeiten
+=item summary_DE sendet Parameter an devices zu einer Liste mit festen Zeiten
=begin html
@@ -1129,12 +1130,12 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
profile
Define the weekly profile. All timings are separated by space. A switchingtime is defined
by the following example:
-
+
[<weekdays>|]<time>|<parameter>
-
+
weekdays: optional, if not set every day of the week is used.
Otherwise you can define a day with its number or its shortname.
-
+
- 0,su sunday
- 1,mo monday
- 2,tu tuesday
@@ -1187,24 +1188,24 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
Some definitions without comment:
-
- define wd Weekdaytimer device de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
- define wd Weekdaytimer device de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
- define wd Weekdaytimer device de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
-
- define wd Weekdaytimer device de mo-so, $we|{sunrise_abs_dat($date)}|on mo-so, $we|{sunset_abs_dat($date)}|off
- define wd Weekdaytimer device de mo-so,!$we|{sunrise_abs_dat($date)}|aus mo-so,!$we|{sunset_abs_dat($date)}|aus
-
- define wd Weekdaytimer device de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
- define wd Weekdaytimer device de 22:35|25 23:00|16
+
+ define wd Weekdaytimer device de 7|23:35|25 34|23:30|22 23:30|16 23:15|22 8|23:45|16
+ define wd Weekdaytimer device de fr,$we|23:35|25 34|23:30|22 23:30|16 23:15|22 12|23:45|16
+ define wd Weekdaytimer device de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
+
+ define wd Weekdaytimer device de mo-so, $we|{sunrise_abs_dat($date)}|on mo-so, $we|{sunset_abs_dat($date)}|off
+ define wd Weekdaytimer device de mo-so,!$we|{sunrise_abs_dat($date)}|aus mo-so,!$we|{sunset_abs_dat($date)}|aus
+
+ define wd Weekdaytimer device de {sunrise_abs_dat($date)}|19 {sunset_abs_dat($date)}|21
+ define wd Weekdaytimer device de 22:35|25 23:00|16
The daylist can be given globaly for the whole Weekdaytimer:
- define wd Weekdaytimer device de !$we 09:00|19 (function("Ein"))
- define wd Weekdaytimer device de $we 09:00|19 (function("Ein"))
- define wd Weekdaytimer device de 78 09:00|19 (function("exit"))
- define wd Weekdaytimer device de 57 09:00|19 (function("exit"))
- define wd Weekdaytimer device de fr,$we 09:00|19 (function("exit"))
+ define wd Weekdaytimer device de !$we 09:00|19 (function("Ein"))
+ define wd Weekdaytimer device de $we 09:00|19 (function("Ein"))
+ define wd Weekdaytimer device de 78 09:00|19 (function("exit"))
+ define wd Weekdaytimer device de 57 09:00|19 (function("exit"))
+ define wd Weekdaytimer device de fr,$we 09:00|19 (function("exit"))
@@ -1225,7 +1226,7 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
set wd disable
set wd enable
-
+
Get
@@ -1233,33 +1234,33 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
Attributes
- - delayedExecutionCond
+ - delayedExecutionCond
defines a delay Function. When returning true, the switching of the device is delayed until the function retruns a false value. The behavior is just like a windowsensor in Heating_Control.
-
+
- Example:
+ Example:
- attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT")
+ attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT")
the parameter $WEEKDAYTIMER(timer name) $TIME $NAME(device name) $EVENT are replaced at runtime by the correct value.
-
+
- Example of a function:
+ Example of a function:
sub isDelayed($$$$$) {
my($hc, $wdt, $tim, $nam, $event ) = @_;
-
+
my $theSunIsStillshining = ...
-
- return ($tim eq "16:30" && $theSunIsStillshining) ;
+
+ return ($tim eq "16:30" && $theSunIsStillshining) ;
}
-
+
- - switchInThePast
+ - switchInThePast
defines that the depending device will be switched in the past in definition and startup phase when the device is not recognized as a heating.
Heatings are always switched in the past.
-
-
+
+
- disable
- loglevel
- event-on-update-reading
@@ -1269,4 +1270,4 @@ sub WeekdayTimer_SetAllParms() { # {WeekdayTimer_SetAllParms()}
=end html
-=cut
\ No newline at end of file
+=cut
diff --git a/fhem/FHEM/98_powerMap.pm b/fhem/FHEM/98_powerMap.pm
index 0872d28ae..41539917e 100644
--- a/fhem/FHEM/98_powerMap.pm
+++ b/fhem/FHEM/98_powerMap.pm
@@ -1,5 +1,6 @@
###############################################################################
# $Id$
+# Maintained by igami since 02-2018
#
# TODO
# - document how to include powerMap for other module maintainers
diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt
index 61f6eb954..274363905 100644
--- a/fhem/MAINTAINER.txt
+++ b/fhem/MAINTAINER.txt
@@ -33,7 +33,7 @@ FHEM/00_NetzerI2C.pm klausw Sonstige Systeme
FHEM/00_OWX.pm pahenning 1Wire
FHEM/00_OWX_ASYNC ntruchsess 1Wire
FHEM/00_RPII2C klausw Einplatinencomputer
-FHEM/00_SIGNALduino.pm Sidey Sonstige Systeme
+FHEM/00_SIGNALduino.pm Sidey Sonstige Systeme
FHEM/00_SONOS.pm Reinerlein Multimedia
FHEM/00_TCM.pm klaus-schauer EnOcean
FHEM/00_THZ.pm immiimmi Heizungssteuerung/Raumklima
@@ -272,7 +272,7 @@ FHEM/57_CALVIEW.pm chris1284 Unterstuetzende Dienste/Kalend
FHEM/59_HCS.pm hjr Automatisierung (oder auch PM)
FHEM/59_LuftdatenInfo igami Bastelecke
FHEM/59_OPENWEATHER.pm tupol Unterstuetzende Dienste/Wettermodule (Link als PM an tupol)
-FHEM/59_Twilight.pm dietmar63 Unterstuetzende Dienste/Wettermodule
+FHEM/59_Twilight.pm igami Unterstuetzende Dienste/Wettermodule
FHEM/59_PROPLANTA.pm tupol Unterstuetzende Dienste/Wettermodule (Link als PM an tupol)
FHEM/59_WWO.pm baumrasen Unterstuetzende Dienste/Wettermodule
FHEM/59_Weather.pm neubert Unterstuetzende Dienste/Wettermodule
@@ -414,7 +414,7 @@ FHEM/98_EDIPLUG.pm Wzut Sonstige Systeme
FHEM/98_FReplacer.pm stefanstrobel Sonstiges
FHEM/98_GEOFANCY.pm loredo Unterstuetzende Dienste
FHEM/98_HMinfo.pm martinp876 HomeMatic
-FHEM/98_Heating_Control.pm dietmar63 Unterstuetzende Dienste
+FHEM/98_Heating_Control.pm igami Unterstuetzende Dienste
FHEM/98_HTTPMOD.pm stefanstrobel Sonstiges
FHEM/98_Arducounter.pm stefanstrobel Sonstiges
FHEM/98_Hyperion.pm DeeSPe Beleuchtung
@@ -426,14 +426,14 @@ FHEM/98_ModbusAttr.pm stefanstrobel Sonstiges
FHEM/98_ModbusSET.pm stefanstrobel Sonstiges
FHEM/98_ModbusTrovis5576.pm Reinerlein Heizungssteuerung/Raumklima
FHEM/98_PID20.pm John Automatisierung
-FHEM/98_RandomTimer.pm dietmar63 Unterstuetzende Dienste/Kalendermodule
+FHEM/98_RandomTimer.pm igami Unterstuetzende Dienste/Kalendermodule
FHEM/98_SVG.pm rudolfkoenig Frontends/SVG/Plots/logProxy
FHEM/98_THRESHOLD.pm damian-s Automatisierung
FHEM/98_TRAFFIC.pm jmike Unterstuetzende Dienste
FHEM/98_UbiquitiPM.pm Wzut Sonstige Systeme
FHEM/98_UbiquitiOut.pm Wzut Sonstige Systeme
FHEM/98_Verkehrsinfo.pm martins Unterstuetzende Dienste
-FHEM/98_WeekdayTimer.pm dietmar63 Unterstuetzende Dienste
+FHEM/98_WeekdayTimer.pm igami Unterstuetzende Dienste
FHEM/98_WOL.pm dietmar63 Unterstuetzende Dienste
FHEM/98_XmlList.pm rudolfkoenig Automatisierung
FHEM/96_allowed.pm rudolfkoenig Automatisierung
@@ -464,7 +464,7 @@ FHEM/98_monitoring.pm igami Automatisierung
FHEM/98_notice.pm mfr69bs Sonstiges
FHEM/98_pilight.pm andreas-fey Unterstuetzende Dienste
FHEM/98_ping mattwire Sonstiges
-FHEM/98_powerMap loredo Unterstuetzende Dienste
+FHEM/98_powerMap igami Unterstuetzende Dienste
FHEM/98_QRCode.pm Benni Unterstuetzende Dienste
FHEM/98_rain.pm baumrasen Sonstiges
FHEM/98_restore.pm rudolfkoenig Sonstiges