2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-13 05:06:35 +00:00

MAINTAINER: Maintainer changes

git-svn-id: https://svn.fhem.de/fhem/trunk@16005 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
igami 2018-01-27 06:05:51 +00:00
parent acd4e7eee3
commit 7a07a71b0f
6 changed files with 523 additions and 519 deletions

View File

@ -4,6 +4,7 @@
# 59_Twilight.pm # 59_Twilight.pm
# Copyright by Sebastian Stuecker # Copyright by Sebastian Stuecker
# erweitert von Dietmar Ortmann # erweitert von Dietmar Ortmann
# Maintained by igami since 02-2018
# #
# used algorithm see: http://lexikon.astronomie.info/zeitgleichung/ # used algorithm see: http://lexikon.astronomie.info/zeitgleichung/
# #
@ -37,7 +38,7 @@ use warnings;
use POSIX; use POSIX;
use HttpUtils; use HttpUtils;
use Math::Trig; use Math::Trig;
use Time::Local 'timelocal_nocheck'; use Time::Local 'timelocal_nocheck';
sub Twilight_calc($$); sub Twilight_calc($$);
sub Twilight_my_gmt_offset(); 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] !~ /^[\. ]*$/ ) { if(int(@a)>4) { if ($a[4] =~ /^[\+-]*[0-9]*\.*[0-9]*$/ && $a[4] !~ /^[\. ]*$/ ) {
$indoor_horizon = $a[4]; $indoor_horizon = $a[4];
if($indoor_horizon > 20) { $indoor_horizon=20;} 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;} if($indoor_horizon < -6) { $indoor_horizon= -6;}
}else{ }else{
return "Argument Indoor_Horizon is not a valid number";} return "Argument Indoor_Horizon is not a valid number";}
} }
$hash->{WEATHER_HORIZON} = 0; $hash->{WEATHER_HORIZON} = 0;
$hash->{INDOOR_HORIZON} = $indoor_horizon; $hash->{INDOOR_HORIZON} = $indoor_horizon;
$hash->{LATITUDE} = $latitude; $hash->{LATITUDE} = $latitude;
$hash->{LONGITUDE} = $longitude; $hash->{LONGITUDE} = $longitude;
$hash->{WEATHER} = $weather; $hash->{WEATHER} = $weather;
$hash->{VERSUCHE} = 0; $hash->{VERSUCHE} = 0;
$hash->{DEFINE} = 1; $hash->{DEFINE} = 1;
$hash->{CONDITION} = 50; $hash->{CONDITION} = 50;
$hash->{SUNPOS_OFFSET} = 5*60; $hash->{SUNPOS_OFFSET} = 5*60;
$attr{$name}{verbose} = 4 if ($name =~ /^tst.*$/ ); $attr{$name}{verbose} = 4 if ($name =~ /^tst.*$/ );
my $mHash = { HASH=>$hash }; my $mHash = { HASH=>$hash };
Twilight_sunpos($mHash); Twilight_sunpos($mHash);
Twilight_Midnight($mHash); Twilight_Midnight($mHash);
delete $hash->{DEFINE}; delete $hash->{DEFINE};
return undef; return undef;
} }
################################################################################ ################################################################################
@ -152,14 +153,14 @@ sub myInternalTimer($$$$$) {
my ($modifier, $tim, $callback, $hash, $waitIfInitNotDone) = @_; my ($modifier, $tim, $callback, $hash, $waitIfInitNotDone) = @_;
my $timerName = "$hash->{NAME}_$modifier"; 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})) { if (defined($hash->{TIMER}{$timerName})) {
Log3 $hash, 1, "[$hash->{NAME}] possible overwriting of timer $timerName - please delete first"; Log3 $hash, 1, "[$hash->{NAME}] possible overwriting of timer $timerName - please delete first";
stacktrace(); stacktrace();
} else { } else {
$hash->{TIMER}{$timerName} = $mHash; $hash->{TIMER}{$timerName} = $mHash;
} }
Log3 $hash, 5, "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim); Log3 $hash, 5, "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim);
InternalTimer($tim, $callback, $mHash, $waitIfInitNotDone); InternalTimer($tim, $callback, $mHash, $waitIfInitNotDone);
return $mHash; return $mHash;
@ -191,12 +192,12 @@ sub myRemoveInternalTimer($$) {
################################################################################ ################################################################################
sub myGetHashIndirekt ($$) { sub myGetHashIndirekt ($$) {
my ($myHash, $function) = @_; my ($myHash, $function) = @_;
if (!defined($myHash->{HASH})) { if (!defined($myHash->{HASH})) {
Log 3, "[$function] myHash not valid"; Log 3, "[$function] myHash not valid";
return undef; return undef;
}; };
return $myHash->{HASH}; return $myHash->{HASH};
} }
################################################################################ ################################################################################
sub Twilight_midnight_seconds($) { sub Twilight_midnight_seconds($) {
@ -207,12 +208,12 @@ sub Twilight_midnight_seconds($) {
} }
################################################################################ ################################################################################
#sub Twilight_ssTimeAsEpoch($) { #sub Twilight_ssTimeAsEpoch($) {
# my ($zeit) = @_; # my ($zeit) = @_;
# my ($hour, $min, $sec) = split(":",$zeit); # my ($hour, $min, $sec) = split(":",$zeit);
# #
# my $days=0; # my $days=0;
# if ($hour>=24) {$days = 1; $hour -=24}; # if ($hour>=24) {$days = 1; $hour -=24};
# #
# my @jetzt_arr = localtime(time()); # my @jetzt_arr = localtime(time());
# #Stunden Minuten Sekunden # #Stunden Minuten Sekunden
# $jetzt_arr[2] = $hour; $jetzt_arr[1] = $min; $jetzt_arr[0] = $sec; # $jetzt_arr[2] = $hour; $jetzt_arr[1] = $min; $jetzt_arr[0] = $sec;
@ -224,21 +225,21 @@ sub Twilight_midnight_seconds($) {
################################################################################ ################################################################################
sub Twilight_calc($$) { sub Twilight_calc($$) {
my ($deg, $idx) = @_; my ($deg, $idx) = @_;
my $midnight = time() - Twilight_midnight_seconds(time()); my $midnight = time() - Twilight_midnight_seconds(time());
my $sr = sunrise_abs("Horizon=$deg"); my $sr = sunrise_abs("Horizon=$deg");
my $ss = sunset_abs ("Horizon=$deg"); my $ss = sunset_abs ("Horizon=$deg");
my ($srhour, $srmin, $srsec) = split(":",$sr); $srhour -= 24 if($srhour>=24); 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 $sr1 = $midnight + 3600*$srhour+60*$srmin+$srsec;
my $ss1 = $midnight + 3600*$sshour+60*$ssmin+$sssec; 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, #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); return ($sr1 + 0.01*$idx), ($ss1 - 0.01*$idx);
} }
################################################################################ ################################################################################
@ -258,32 +259,32 @@ sub Twilight_TwilightTimes(@) {
foreach my $horizon (@horizons) { foreach my $horizon (@horizons) {
$idx++; next if ($whitchTimes eq "weather" && !($horizon =~ m/weather/) ); $idx++; next if ($whitchTimes eq "weather" && !($horizon =~ m/weather/) );
my ($name, $deg) = split(":", $horizon); my ($name, $deg) = split(":", $horizon);
my $sr = "sr$name"; my $ss = "ss$name"; my $sr = "sr$name"; my $ss = "ss$name";
$hash->{TW}{$sr}{NAME} = $sr; $hash->{TW}{$ss}{NAME} = $ss; $hash->{TW}{$sr}{NAME} = $sr; $hash->{TW}{$ss}{NAME} = $ss;
$hash->{TW}{$sr}{DEG} = $deg; $hash->{TW}{$ss}{DEG} = $deg; $hash->{TW}{$sr}{DEG} = $deg; $hash->{TW}{$ss}{DEG} = $deg;
$hash->{TW}{$sr}{LIGHT} = $idx+1;$hash->{TW}{$ss}{LIGHT} = $idx; $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}{STATE} = $idx+1;$hash->{TW}{$ss}{STATE} = 12 - $idx;
$hash->{TW}{$sr}{SWIP} = $swip; $hash->{TW}{$ss}{SWIP} = $swip; $hash->{TW}{$sr}{SWIP} = $swip; $hash->{TW}{$ss}{SWIP} = $swip;
($hash->{TW}{$sr}{TIME}, $hash->{TW}{$ss}{TIME}) = Twilight_calc ($deg, $idx); ($hash->{TW}{$sr}{TIME}, $hash->{TW}{$ss}{TIME}) = Twilight_calc ($deg, $idx);
if ($hash->{TW}{$sr}{TIME} == 0) { if ($hash->{TW}{$sr}{TIME} == 0) {
Log3 $hash, 4, "[$Name] hint: $hash->{TW}{$sr}{NAME}, $hash->{TW}{$ss}{NAME} are not defined(HORIZON=$deg)"; Log3 $hash, 4, "[$Name] hint: $hash->{TW}{$sr}{NAME}, $hash->{TW}{$ss}{NAME} are not defined(HORIZON=$deg)";
} }
} }
$attr{global}{latitude} = $lat; $attr{global}{latitude} = $lat;
$attr{global}{longitude} = $long; $attr{global}{longitude} = $long;
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
readingsBeginUpdate ($hash); readingsBeginUpdate ($hash);
foreach my $ereignis (keys %{$hash->{TW}}) { foreach my $ereignis (keys %{$hash->{TW}}) {
next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) ); next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) );
readingsBulkUpdate($hash, $ereignis, $hash->{TW}{$ereignis}{TIME} == 0 ? "undefined" : FmtTime($hash->{TW}{$ereignis}{TIME})); readingsBulkUpdate($hash, $ereignis, $hash->{TW}{$ereignis}{TIME} == 0 ? "undefined" : FmtTime($hash->{TW}{$ereignis}{TIME}));
} }
if ($hash->{CONDITION} != 50 ) { if ($hash->{CONDITION} != 50 ) {
readingsBulkUpdate ($hash,"condition", $hash->{CONDITION}); readingsBulkUpdate ($hash,"condition", $hash->{CONDITION});
readingsBulkUpdate ($hash,"condition_txt",$hash->{CONDITION_TXT}); readingsBulkUpdate ($hash,"condition_txt",$hash->{CONDITION_TXT});
} }
readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1)); readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1));
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
my @horizonsOhneDeg = map {my($e, $deg)=split(":",$_); "$e"} @horizons; my @horizonsOhneDeg = map {my($e, $deg)=split(":",$_); "$e"} @horizons;
@ -296,18 +297,18 @@ sub Twilight_TwilightTimes(@) {
my $lastMitternacht = $now-$secSinceMidnight; my $lastMitternacht = $now-$secSinceMidnight;
my $nextMitternacht = ($secSinceMidnight > 12*3600) ? $lastMitternacht+24*3600 : $lastMitternacht; my $nextMitternacht = ($secSinceMidnight > 12*3600) ? $lastMitternacht+24*3600 : $lastMitternacht;
my $jetztIstMitternacht = abs($now+5-$nextMitternacht)<=10; my $jetztIstMitternacht = abs($now+5-$nextMitternacht)<=10;
my @keyListe = qw "DEG LIGHT STATE SWIP TIME NAMENEXT"; my @keyListe = qw "DEG LIGHT STATE SWIP TIME NAMENEXT";
foreach my $ereignis (sort keys %{$hash->{TW}}) { foreach my $ereignis (sort keys %{$hash->{TW}}) {
next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) ); next if ($whitchTimes eq "weather" && !($ereignis =~ m/weather/) );
myRemoveInternalTimer($ereignis, $hash); # if(!$jetztIstMitternacht); myRemoveInternalTimer($ereignis, $hash); # if(!$jetztIstMitternacht);
if($hash->{TW}{$ereignis}{TIME} > 0) { if($hash->{TW}{$ereignis}{TIME} > 0) {
$myHash = myInternalTimer($ereignis, $hash->{TW}{$ereignis}{TIME}, "Twilight_fireEvent", $hash, 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; return 1;
} }
################################################################################ ################################################################################
@ -318,7 +319,7 @@ sub Twilight_fireEvent($) {
return if (!defined($hash)); return if (!defined($hash));
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $event = $myHash->{MODIFIER}; my $event = $myHash->{MODIFIER};
my $deg = $myHash->{DEG}; my $deg = $myHash->{DEG};
my $light = $myHash->{LIGHT}; my $light = $myHash->{LIGHT};
@ -330,18 +331,18 @@ sub Twilight_fireEvent($) {
my $delta = int($eventTime - time()); my $delta = int($eventTime - time());
my $oldState = ReadingsVal($name,"state","0"); my $oldState = ReadingsVal($name,"state","0");
my $nextEventTime = ($hash->{TW}{$nextEvent}{TIME} > 0) ? FmtTime($hash->{TW}{$nextEvent}{TIME}) : "undefined"; 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); 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, 3, "[$hash->{NAME}] swip-delta-oldState-doTrigger===>$swip/$delta/$oldState/$doTrigger";
Log3 $hash, 4, Log3 $hash, 4,
sprintf ("[$hash->{NAME}] %-10s %-19s ", $event, FmtDateTime($eventTime)). 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); sprintf ("===> %-10s %-19s ", $nextEvent, $nextEventTime);
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate ($hash, "state", $state); readingsBulkUpdate ($hash, "state", $state);
readingsBulkUpdate ($hash, "light", $light); readingsBulkUpdate ($hash, "light", $light);
@ -355,11 +356,11 @@ sub Twilight_fireEvent($) {
} }
################################################################################ ################################################################################
sub Twilight_Midnight($) { sub Twilight_Midnight($) {
my ($myHash) = @_; my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]); my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash)); return if (!defined($hash));
$hash->{SWIP} = 0; $hash->{SWIP} = 0;
my $param = Twilight_CreateHttpParameterAndGetData($myHash, "Mid"); my $param = Twilight_CreateHttpParameterAndGetData($myHash, "Mid");
} }
################################################################################ ################################################################################
@ -367,24 +368,24 @@ sub Twilight_Midnight($) {
sub Twilight_WeatherTimerUpdate($) { sub Twilight_WeatherTimerUpdate($) {
my ($myHash) = @_; my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]); 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"); my $param = Twilight_CreateHttpParameterAndGetData($myHash, "weather");
} }
################################################################################ ################################################################################
sub Twilight_CreateHttpParameterAndGetData($$) { sub Twilight_CreateHttpParameterAndGetData($$) {
my ($myHash, $mode) = @_; my ($myHash, $mode) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]); my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash)); return if (!defined($hash));
my $location = $hash->{WEATHER}; my $location = $hash->{WEATHER};
my $verbose = AttrVal($hash->{NAME}, "verbose", 3 ); 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 = "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"); my $url = sprintf($URL, $location, "json");
Log3 $hash, 4, "[$hash->{NAME}] url=$url"; Log3 $hash, 4, "[$hash->{NAME}] url=$url";
my $param = { my $param = {
url => $url, url => $url,
timeout => defined($hash->{DEFINE}) ? 10 :10, timeout => defined($hash->{DEFINE}) ? 10 :10,
@ -394,23 +395,23 @@ sub Twilight_CreateHttpParameterAndGetData($$) {
header => "User-Agent: Mozilla/5.0\r\nAccept: application/xml", header => "User-Agent: Mozilla/5.0\r\nAccept: application/xml",
callback => \&Twilight_WeatherCallback, callback => \&Twilight_WeatherCallback,
mode => $mode }; mode => $mode };
if (defined($hash->{DEFINE})) { if (defined($hash->{DEFINE})) {
delete $param->{callback}; delete $param->{callback};
my ($err, $result) = HttpUtils_BlockingGet($param); my ($err, $result) = HttpUtils_BlockingGet($param);
Twilight_WeatherCallback($param, $err, $result); Twilight_WeatherCallback($param, $err, $result);
} else { } else {
HttpUtils_NonblockingGet($param); HttpUtils_NonblockingGet($param);
} }
} }
################################################################################ ################################################################################
sub Twilight_WeatherCallback(@) { sub Twilight_WeatherCallback(@) {
my ($param, $err, $result) = @_; my ($param, $err, $result) = @_;
my $hash = $param->{hash}; my $hash = $param->{hash};
return if (!defined($hash)); return if (!defined($hash));
if ($err) { if ($err) {
Log3 $hash, 3, "[$hash->{NAME}] got no weather info from yahoo. Error code: $err"; Log3 $hash, 3, "[$hash->{NAME}] got no weather info from yahoo. Error code: $err";
$result = undef; $result = undef;
@ -418,22 +419,22 @@ sub Twilight_WeatherCallback(@) {
Log3 $hash, 4, "[$hash->{NAME}] got weather info from yahoo for $hash->{WEATHER}"; Log3 $hash, 4, "[$hash->{NAME}] got weather info from yahoo for $hash->{WEATHER}";
Log3 $hash, 5, "[$hash->{NAME}] answer=$result" if defined $result; Log3 $hash, 5, "[$hash->{NAME}] answer=$result" if defined $result;
} }
Twilight_getWeatherHorizon($hash, $result); Twilight_getWeatherHorizon($hash, $result);
#$hash->{CONDITION} = 50; #$hash->{CONDITION} = 50;
if ($hash->{CONDITION} == 50 && $hash->{VERSUCHE} <= 10) { if ($hash->{CONDITION} == 50 && $hash->{VERSUCHE} <= 10) {
$hash->{VERSUCHE} += 1; $hash->{VERSUCHE} += 1;
Twilight_RepeatTimerSet($hash, $param->{mode}); Twilight_RepeatTimerSet($hash, $param->{mode});
return; return;
} }
Twilight_TwilightTimes ($hash, $param->{mode}, $result); 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 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); 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); Twilight_StandardTimerSet ($hash);
} }
################################################################################ ################################################################################
@ -446,8 +447,8 @@ sub Twilight_RepeatTimerSet($$) {
myInternalTimer ("Midnight", $midnight, "Twilight_Midnight", $hash, 0); myInternalTimer ("Midnight", $midnight, "Twilight_Midnight", $hash, 0);
} else { } else {
myInternalTimer ("Midnight", $midnight, "Twilight_WeatherTimerUpdate", $hash, 0); myInternalTimer ("Midnight", $midnight, "Twilight_WeatherTimerUpdate", $hash, 0);
} }
} }
################################################################################ ################################################################################
sub Twilight_StandardTimerSet($) { sub Twilight_StandardTimerSet($) {
@ -484,13 +485,13 @@ sub Twilight_sunposTimerSet($) {
sub Twilight_getWeatherHorizon(@) sub Twilight_getWeatherHorizon(@)
{ {
my ($hash, $result) = @_; my ($hash, $result) = @_;
my $location=$hash->{WEATHER}; my $location=$hash->{WEATHER};
if ($location == 0) { if ($location == 0) {
$hash->{WEATHER_HORIZON}="0"; $hash->{WEATHER_HORIZON}="0";
$hash->{CONDITION}="0"; $hash->{CONDITION}="0";
return 1; return 1;
} }
my $mod = "[".$hash->{NAME} ."] "; my $mod = "[".$hash->{NAME} ."] ";
my @faktor_cond_code = (10,10,10,10, 9, 7, 7, 7, 7, 7, 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); my ($cond_code, $cond_txt, $temperatur, $aktTemp);
if (defined($result)) { if (defined($result)) {
# ersetze in result(json) ": durch "=> # ersetze in result(json) ": durch "=>
# dadurch entsteht ein Perlausdruck, der direkt geparst werden kann # dadurch entsteht ein Perlausdruck, der direkt geparst werden kann
my $perlAusdruck = $result; my $perlAusdruck = $result;
#$perlAusdruck = "<h1>could"; #$perlAusdruck = "<h1>could";
$perlAusdruck =~ s/("[\w ]+")(\s*)(:)/$1=>/g; $perlAusdruck =~ s/("[\w ]+")(\s*)(:)/$1=>/g;
$perlAusdruck =~ s/null/undef/g; $perlAusdruck =~ s/null/undef/g;
$perlAusdruck =~ s/true/1/g; $perlAusdruck =~ s/true/1/g;
$perlAusdruck =~ s/false/0/g; $perlAusdruck =~ s/false/0/g;
$perlAusdruck = 'return ' .$perlAusdruck; $perlAusdruck = 'return ' .$perlAusdruck;
my $anonymSub = eval "sub {$perlAusdruck}"; my $anonymSub = eval "sub {$perlAusdruck}";
Log3 $hash, 3, "[$hash->{NAME}] error $@ parsing $result" if($@); Log3 $hash, 3, "[$hash->{NAME}] error $@ parsing $result" if($@);
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, "[$hash->{NAME}] error $@ parsing $result" if($@);
#Log3 $hash, 3, "jsonAsPerl". Dumper $resHash->{query}{results}{channel}{item}{condition}; #Log3 $hash, 3, "jsonAsPerl". Dumper $resHash->{query}{results}{channel}{item}{condition};
if (!$@) { if (!$@) {
$cond_code = $resHash->{query}{results}{channel}{item}{condition}{code}; $cond_code = $resHash->{query}{results}{channel}{item}{condition}{code};
$cond_txt = $resHash->{query}{results}{channel}{item}{condition}{text}; $cond_txt = $resHash->{query}{results}{channel}{item}{condition}{text};
$temperatur = $resHash->{query}{results}{channel}{item}{condition}{temp}; $temperatur = $resHash->{query}{results}{channel}{item}{condition}{temp};
} }
} }
} }
# wenn kein Code ermittelt werden kann, wird ein Pseudocode gesetzt # wenn kein Code ermittelt werden kann, wird ein Pseudocode gesetzt
if (!defined($cond_code) ) { if (!defined($cond_code) ) {
$cond_code = "50"; # eigener neutraler Code $cond_code = "50"; # eigener neutraler Code
$cond_txt = "undefined"; $cond_txt = "undefined";
$temperatur = "undefined"; $temperatur = "undefined";
} else { } else {
$hash->{WEATHER_CORRECTION} = $faktor_cond_code[$cond_code] / 25 * 20; $hash->{WEATHER_CORRECTION} = $faktor_cond_code[$cond_code] / 25 * 20;
$hash->{WEATHER_HORIZON} = $hash->{WEATHER_CORRECTION} + $hash->{INDOOR_HORIZON}; $hash->{WEATHER_HORIZON} = $hash->{WEATHER_CORRECTION} + $hash->{INDOOR_HORIZON};
$hash->{CONDITION} = $cond_code; $hash->{CONDITION} = $cond_code;
@ -544,15 +545,15 @@ sub Twilight_getWeatherHorizon(@)
$hash->{TEMPERATUR} = $temperatur; $hash->{TEMPERATUR} = $temperatur;
Log3 $hash, 4, "[$hash->{NAME}] $cond_code=$cond_txt $temperatur, correction: $hash->{WEATHER_CORRECTION}°"; 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)); my $declination = 0.4095*sin(0.016906*($doy-80.086));
if($hash->{WEATHER_HORIZON} > (89-$hash->{LATITUDE}+$declination) ){ if($hash->{WEATHER_HORIZON} > (89-$hash->{LATITUDE}+$declination) ){
$hash->{WEATHER_HORIZON} = 89-$hash->{LATITUDE}+$declination; $hash->{WEATHER_HORIZON} = 89-$hash->{LATITUDE}+$declination;
} }
return 1; return 1;
} }
################################################################################ ################################################################################
sub Twilight_sunpos($) sub Twilight_sunpos($)
@ -640,7 +641,7 @@ sub Twilight_sunpos($)
my $twilight = int(($dElevation+12.0)/18.0 * 1000)/10; my $twilight = int(($dElevation+12.0)/18.0 * 1000)/10;
$twilight = 100 if ($twilight>100); $twilight = 100 if ($twilight>100);
$twilight = 0 if ($twilight< 0); $twilight = 0 if ($twilight< 0);
my $twilight_weather ; my $twilight_weather ;
if( (my $ExtWeather = AttrVal($hashName, "useExtWeather", "")) eq "") { if( (my $ExtWeather = AttrVal($hashName, "useExtWeather", "")) eq "") {
@ -648,17 +649,17 @@ sub Twilight_sunpos($)
Log3 $hash, 5, "[$hash->{NAME}] " . "Original weather readings"; Log3 $hash, 5, "[$hash->{NAME}] " . "Original weather readings";
} else { } else {
my($extDev,$extReading) = split(":",$ExtWeather); my($extDev,$extReading) = split(":",$ExtWeather);
my $extWeatherHorizont = ReadingsVal($extDev,$extReading,-1); my $extWeatherHorizont = ReadingsVal($extDev,$extReading,-1);
if ($extWeatherHorizont >= 0){ if ($extWeatherHorizont >= 0){
$extWeatherHorizont = 100 if ($extWeatherHorizont > 100); $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) $twilight_weather = $twilight - int(0.007 * ($extWeatherHorizont ** 2)); ## SCM: 100% clouds => 30% light (rough estimation)
} else { } else {
$twilight_weather = int(($dElevation-$hash->{WEATHER_HORIZON}+12.0)/18.0 * 1000)/10; $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 = 100 if ($twilight_weather>100);
$twilight_weather = 0 if ($twilight_weather< 0); $twilight_weather = 0 if ($twilight_weather< 0);
@ -759,7 +760,7 @@ sub twilight($$$$) {
<br><br> <br><br>
<b>indoor_horizon</b> <b>indoor_horizon</b>
<br> <br>
The parameter <b>indoor_horizon</b> 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 <b>indoor_horizon</b> 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. indoor_horizon 0 means indoor values are the same as real values. indoor_horizon > 0 means earlier indoor sunset resp. later indoor sunrise.
<br><br> <br><br>
<b>Weather_Position</b> <b>Weather_Position</b>
@ -899,8 +900,8 @@ Example:
<br><br> <br><br>
<b>indoor_horizon</b> <b>indoor_horizon</b>
<br> <br>
Der Parameter <b>indoor_horizon</b> bestimmt einen virtuellen Horizont, der f&uuml;r die Berechnung der D&auml;mmerung innerhalb von R&auml;men genutzt werden kann. Minimalwert ist -6 (ergibt gleichen Wert wie Zivile D&auml;mmerung). Bei 0 fallen Der Parameter <b>indoor_horizon</b> bestimmt einen virtuellen Horizont, der f&uuml;r die Berechnung der D&auml;mmerung innerhalb von R&auml;men genutzt werden kann. Minimalwert ist -6 (ergibt gleichen Wert wie Zivile D&auml;mmerung). Bei 0 fallen
indoor- und realer D&aumlmmerungswert zusammen. Werte gr&oumlsser 0 ergeben fr&uumlhere Werte für den Abend bzw. sp&aumltere f&uumlr den Morgen. indoor- und realer D&aumlmmerungswert zusammen. Werte gr&oumlsser 0 ergeben fr&uumlhere Werte für den Abend bzw. sp&aumltere f&uumlr den Morgen.
<br><br> <br><br>
<b>Weather_Position</b> <b>Weather_Position</b>
<br> <br>
@ -925,7 +926,7 @@ Example:
<b>Azimut, Elevation, Twilight (Seitenwinkel, Höhenwinkel, D&auml;mmerung)</b> <b>Azimut, Elevation, Twilight (Seitenwinkel, Höhenwinkel, D&auml;mmerung)</b>
<br> <br>
Das Modul berechnet zus&auml;tzlich Azimuth und Elevation der Sonne. Diese Werte k&ouml;nnen zur Rolladensteuerung verwendet werden.<br><br> Das Modul berechnet zus&auml;tzlich Azimuth und Elevation der Sonne. Diese Werte k&ouml;nnen zur Rolladensteuerung verwendet werden.<br><br>
Das Reading <b>Twilight</b> wird als neuer "(twi)light" Wert hinzugef&uuml;gt. Er wird aus der Elevation der Sonne mit folgender Formel abgeleitet: (Elevation+12)/18 * 100). Das erlaubt eine detailliertere Kontrolle der Lampen w&auml;hrend Sonnenauf - und untergang. Dieser Wert ist zwischen 0% und 100% wenn die Elevation zwischen -12&deg; und 6&deg; Das Reading <b>Twilight</b> wird als neuer "(twi)light" Wert hinzugef&uuml;gt. Er wird aus der Elevation der Sonne mit folgender Formel abgeleitet: (Elevation+12)/18 * 100). Das erlaubt eine detailliertere Kontrolle der Lampen w&auml;hrend Sonnenauf - und untergang. Dieser Wert ist zwischen 0% und 100% wenn die Elevation zwischen -12&deg; und 6&deg;
<br><br> <br><br>
@ -990,7 +991,7 @@ Wissenswert dazu ist, dass die Sonne, abh&auml;gnig vom Breitengrad, bestimmte E
<li><b>useExtWeather &lt;device&gt;:&lt;reading&gt;</b></li> <li><b>useExtWeather &lt;device&gt;:&lt;reading&gt;</b></li>
Nutzt Daten von einem anderen Device um <b>twilight_weather</b> zu berechnen.<br/> Nutzt Daten von einem anderen Device um <b>twilight_weather</b> zu berechnen.<br/>
Das Reading sollte sich im Intervall zwischen 0 und 100 bewegen, z.B. das Reading <b>c_clouds</b> in einem<b><a href="#openweathermap">openweathermap</a></b> device, bei dem 0 heiteren und 100 bedeckten Himmel bedeuten. Das Reading sollte sich im Intervall zwischen 0 und 100 bewegen, z.B. das Reading <b>c_clouds</b> in einem<b><a href="#openweathermap">openweathermap</a></b> device, bei dem 0 heiteren und 100 bedeckten Himmel bedeuten.
Wird diese Attribut genutzt , werden Wettereffekte wie Starkregen oder Gewitter fuer die Berechnung von <b>twilight_weather</b> nicht mehr herangezogen. Wird diese Attribut genutzt , werden Wettereffekte wie Starkregen oder Gewitter fuer die Berechnung von <b>twilight_weather</b> nicht mehr herangezogen.
</ul> </ul>
<br> <br>

View File

@ -3,6 +3,7 @@
# #
# 98_Heating_Control.pm # 98_Heating_Control.pm
# written by Dietmar Ortmann # written by Dietmar Ortmann
# Maintained by igami since 02-2018
# #
# This file is part of fhem. # This file is part of fhem.
# #
@ -36,7 +37,7 @@ sub Heating_Control_Initialize($)
# Consumer # Consumer
$hash->{SetFn} = "Heating_Control_Set"; $hash->{SetFn} = "Heating_Control_Set";
$hash->{AttrFn} = "Heating_Control_Attr"; $hash->{AttrFn} = "Heating_Control_Attr";
$hash->{DefFn} = "Heating_Control_Define"; $hash->{DefFn} = "Heating_Control_Define";
$hash->{UndefFn} = "Heating_Control_Undef"; $hash->{UndefFn} = "Heating_Control_Undef";
$hash->{GetFn} = "Heating_Control_Get"; $hash->{GetFn} = "Heating_Control_Get";
@ -47,21 +48,21 @@ sub Heating_Control_Initialize($)
################################################################################ ################################################################################
sub Heating_Control_Set($@) { sub Heating_Control_Set($@) {
my ($hash, @a) = @_; my ($hash, @a) = @_;
return "no set value specified" if(int(@a) < 2); return "no set value specified" if(int(@a) < 2);
return "Unknown argument $a[1], choose one of enable disable " if($a[1] eq "?"); return "Unknown argument $a[1], choose one of enable disable " if($a[1] eq "?");
my $name = shift @a; my $name = shift @a;
my $v = join(" ", @a); my $v = join(" ", @a);
Log3 $hash, 3, "[$name] set $name $v"; Log3 $hash, 3, "[$name] set $name $v";
if ($v eq "enable") { if ($v eq "enable") {
fhem("attr $name disable 0"); fhem("attr $name disable 0");
} elsif ($v eq "disable") { } elsif ($v eq "disable") {
fhem("attr $name disable 1"); fhem("attr $name disable 1");
} }
return undef; return undef;
} }
######################################################################## ########################################################################
sub Heating_Control_Get($@) { sub Heating_Control_Get($@) {
@ -92,8 +93,8 @@ sub Heating_Control_SetTimerOfDay($) {
######################################################################## ########################################################################
sub Heating_Control_Attr($$$$) { sub Heating_Control_Attr($$$$) {
my ($cmd, $name, $attrName, $attrVal) = @_; my ($cmd, $name, $attrName, $attrVal) = @_;
WeekdayTimer_Attr($cmd, $name, $attrName, $attrVal); WeekdayTimer_Attr($cmd, $name, $attrName, $attrVal);
return undef; return undef;
} }
######################################################################## ########################################################################
@ -101,15 +102,15 @@ sub Heating_Control_SetTimer($) {
my ($hash) = @_; my ($hash) = @_;
WeekdayTimer_DeleteTimer($hash); WeekdayTimer_DeleteTimer($hash);
WeekdayTimer_SetTimer($hash); WeekdayTimer_SetTimer($hash);
} }
######################################################################## ########################################################################
sub Heating_Control_SetTemp($) { sub Heating_Control_SetTemp($) {
my ($name) = @_; my ($name) = @_;
my $hash = $modules{Heating_Control}{defptr}{$name}; my $hash = $modules{Heating_Control}{defptr}{$name};
if(defined $hash) { if(defined $hash) {
Heating_Control_SetTimer($hash); Heating_Control_SetTimer($hash);
} }
} }
######################################################################## ########################################################################
sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()} sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
@ -170,12 +171,12 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<ul><b>profile</b><br> <ul><b>profile</b><br>
Define the weekly profile. All timings are separated by space. A switchingtime is defined Define the weekly profile. All timings are separated by space. A switchingtime is defined
by the following example: <br><br> by the following example: <br><br>
<ul><b>[&lt;weekdays&gt;|]&lt;time&gt;|&lt;parameter&gt;</b></ul><br> <ul><b>[&lt;weekdays&gt;|]&lt;time&gt;|&lt;parameter&gt;</b></ul><br>
<u>weekdays:</u> optional, if not set every day of the week is used.<br> <u>weekdays:</u> optional, if not set every day of the week is used.<br>
Otherwise you can define a day with its number or its shortname.<br> Otherwise you can define a day with its number or its shortname.<br>
<ul> <ul>
<li>0,su sunday</li> <li>0,su sunday</li>
<li>1,mo monday</li> <li>1,mo monday</li>
<li>2,tu tuesday</li> <li>2,tu tuesday</li>
@ -236,26 +237,26 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<code>define HeizStatus2 notify Heating:. * {Heating_Control_SetAllTemps()}</code> <code>define HeizStatus2 notify Heating:. * {Heating_Control_SetAllTemps()}</code>
<br><p> <br><p>
Some definitions without comment: Some definitions without comment:
<code><pre>
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
</code></pre>
the list of days can be set globaly for the whole Heating_Control:<p>
<code><pre> <code><pre>
define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$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 HeizungWohnen_an_we Heating_Control HeizungWohnen de $we 09:00|19 (heizungAnAus("Ein")) 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 HeizungWohnen_an_we Heating_Control HeizungWohnen de 78 09:00|19 (heizungAnAus("Ein")) define hc Heating_Control HeizungKueche de 20:35|25 34|14:30|22 21:30|16 21:15|22 12|23:00|16
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 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
</code></pre>
the list of days can be set globaly for the whole Heating_Control:<p>
<code><pre>
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"))
</code></pre> </code></pre>
An example to be able to temporarily boost the temperature for one hour: 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 define HeatingBath_Boost dummy
attr HeatingBath_Boost setList state:0,23,24,25 attr HeatingBath_Boost setList state:0,23,24,25
attr HeatingBath_Boost webCmd state attr HeatingBath_Boost webCmd state
define di_ResetBoostBath DOIF ([HeatingBath_Boost] > 0) define di_ResetBoostBath DOIF ([HeatingBath_Boost] > 0)
({Heating_Control_SetAllTemps()}, defmod di_ResetBoostBath_Reset at +01:00:00 set HeatingBath_Boost 0) ({Heating_Control_SetAllTemps()}, defmod di_ResetBoostBath_Reset at +01:00:00 set HeatingBath_Boost 0)
DOELSE DOELSE
({Heating_Control_SetAllTemps()}) ({Heating_Control_SetAllTemps()})
attr di_ResetBoostBath do always attr di_ResetBoostBath do always
</code></pre> </code></pre>
@ -288,7 +289,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
</code></pre> </code></pre>
Now you can set "HeatingBath_Boost" in the web interface for a one-hour boost of 3 degrees in the bath. 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). (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 <code>VacationTemp</code>.<br> Easy to extend this with a vacation timer using another dummy variable, here <code>VacationTemp</code>.<br>
Then you can use the command Then you can use the command
<code>defmod defVacationEnd at 2016-12-30T00:00:00 set VacationTemp off, {Heating_Control_SetAllTemps()}</code> <code>defmod defVacationEnd at 2016-12-30T00:00:00 set VacationTemp off, {Heating_Control_SetAllTemps()}</code>
@ -308,7 +309,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
} }
</code></pre> </code></pre>
Pray that the device does not restart during your vacation, as the <code>define defVacationEnd ... at </code> is volatile and will be lost at restart! Pray that the device does not restart during your vacation, as the <code>define defVacationEnd ... at </code> is volatile and will be lost at restart!
</ul> </ul>
</ul> </ul>
@ -321,32 +322,32 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<a name="Heating_ControlLogattr"></a> <a name="Heating_ControlLogattr"></a>
<b>Attributes</b> <b>Attributes</b>
<ul> <ul>
<li>delayedExecutionCond <br> <li>delayedExecutionCond <br>
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. 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.
<br><br> <br><br>
<b>Example:</b> <b>Example:</b>
<pre> <pre>
attr hc delayedExecutionCond isDelayed("%HEATING_CONTROL","%WEEKDAYTIMER","%TIME","%NAME","%EVENT") attr hc delayedExecutionCond isDelayed("%HEATING_CONTROL","%WEEKDAYTIMER","%TIME","%NAME","%EVENT")
</pre> </pre>
the parameters %HEATING_CONTROL(timer name) %TIME %NAME(device name) %EVENT are replaced at runtime by the correct value. the parameters %HEATING_CONTROL(timer name) %TIME %NAME(device name) %EVENT are replaced at runtime by the correct value.
<br><br> <br><br>
<b>Example of a function:</b> <b>Example of a function:</b>
<pre> <pre>
sub isDelayed($$$$$) { sub isDelayed($$$$$) {
my($hc, $wdt, $tim, $nam, $event ) = @_; my($hc, $wdt, $tim, $nam, $event ) = @_;
my $theSunIsStillshining = ... my $theSunIsStillshining = ...
return ($tim eq "16:30" && $theSunIsStillshining) ; return ($tim eq "16:30" && $theSunIsStillshining) ;
} }
</pre> </pre>
</li> </li>
<li>switchInThePast<br> <li>switchInThePast<br>
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. 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. Heatings are always switched in the past.
</li> </li>
<li><a href="#disable">disable</a></li> <li><a href="#disable">disable</a></li>
<li><a href="#event-on-update-reading">event-on-update-reading</a></li> <li><a href="#event-on-update-reading">event-on-update-reading</a></li>
@ -404,19 +405,19 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<u>Wochentage:</u> optionale Angabe, falls nicht gesetzt wird der Schaltpunkt jeden Tag ausgef&uumlhrt. <u>Wochentage:</u> optionale Angabe, falls nicht gesetzt wird der Schaltpunkt jeden Tag ausgef&uumlhrt.
F&uumlr die Tage an denen dieser Schaltpunkt aktiv sein soll, ist jeder Tag mit seiner F&uumlr 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.<br><br> Tagesnummer (Mo=1, ..., So=0) oder Name des Tages (Mo, Di, ..., So) einzusetzen.<br><br>
<ul> <ul>
<li>0,so Sonntag</li> <li>0,so Sonntag</li>
<li>1,mo Montag</li> <li>1,mo Montag</li>
<li>2,di Dienstag</li> <li>2,di Dienstag</li>
<li>3,mi Mittwoch</li> <li>3,mi Mittwoch</li>
<li>4 ...</li> <li>4 ...</li>
<li>7,$we Wochenende ($we)</li> <li>7,$we Wochenende ($we)</li>
<li>8,!$we Wochentag (!$we)</li> <li>8,!$we Wochentag (!$we)</li>
</ul><br> </ul><br>
Es ist m&oumlglich $we or !$we in der Tagesliste zu definieren. Es ist m&oumlglich $we or !$we in der Tagesliste zu definieren.
So ist es auf einfache Art m&oumlglich die Schaltzeitpunkte f&uumlr das Wochenende oder Wochetage zu definieren. So ist es auf einfache Art m&oumlglich die Schaltzeitpunkte f&uumlr das Wochenende oder Wochetage zu definieren.
$we und!$we werden als 7 bzw. 8 spezifiziert, wenn die numerische Variante der Tagesliste gew&aumlhlt wird.<br><br> $we und!$we werden als 7 bzw. 8 spezifiziert, wenn die numerische Variante der Tagesliste gew&aumlhlt wird.<br><br>
<u>Uhrzeit:</u>Angabe der Uhrzeit zu der geschaltet werden soll, Format: HH:MM:[SS](HH im 24 Stunden Format) oder eine Perlfunction wie {sunrise_abs()}. <u>Uhrzeit:</u>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)}<br><br> In {} kannst du die Variable $date(epoch) nutzen, um die Schaltzeiten der Woche zu berechnen. Beispiel: {sunrise_abs_dat($date)}<br><br>
<u>Parameter:</u>Angabe der zu setzenden Temperatur als Zahl mit Format 99.9 oder als symbolische Konstante <b>eco</b> <u>Parameter:</u>Angabe der zu setzenden Temperatur als Zahl mit Format 99.9 oder als symbolische Konstante <b>eco</b>
@ -468,24 +469,24 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<code>define HeizStatus2 notify Heizung:.* {Heating_Control_SetAllTemps()}</code> <code>define HeizStatus2 notify Heizung:.* {Heating_Control_SetAllTemps()}</code>
<br><p> <br><p>
Einige Definitionen ohne weitere Erkl&aumlrung: Einige Definitionen ohne weitere Erkl&aumlrung:
<code><pre> <code><pre>
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 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 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 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 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 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 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 hx Heating_Control HeizungKueche de 22:35|25 23:00|16
</code></pre> </code></pre>
Die Tagesliste kann global f&uumlr das ganze Heating_Control angegeben werden:<p> Die Tagesliste kann global f&uumlr das ganze Heating_Control angegeben werden:<p>
<code><pre> <code><pre>
define HeizungWohnen_an_wt Heating_Control HeizungWohnen de !$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 $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 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 57 09:00|19 (heizungAnAus("Ein"))
define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein")) define HeizungWohnen_an_we Heating_Control HeizungWohnen de fr,$we 09:00|19 (heizungAnAus("Ein"))
</code></pre> </code></pre>
es ist möglich den Parameter als Perlcode zu spezifizieren:<p> es ist möglich den Parameter als Perlcode zu spezifizieren:<p>
@ -493,12 +494,12 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
... 7|23:35|{getParameter(13,"this")} 7|23:36|{getParameter(14,"that")} ... 7|23:35|{getParameter(13,"this")} 7|23:36|{getParameter(14,"that")}
</code></pre> </code></pre>
ein detailiertes Beispiel ist in Heating_Control(EN) beschrieben<p> ein detailiertes Beispiel ist in Heating_Control(EN) beschrieben<p>
</ul> </ul>
</ul> </ul>
<a name="Heating_Controlset"></a> <a name="Heating_Controlset"></a>
<b>Set</b> <b>Set</b>
<code><b><font size="+1">set &lt;name&gt; &lt;value&gt;</font></b></code> <code><b><font size="+1">set &lt;name&gt; &lt;value&gt;</font></b></code>
<br><br> <br><br>
@ -513,7 +514,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<code>set hc disable</code><br> <code>set hc disable</code><br>
<code>set hc enable</code><br> <code>set hc enable</code><br>
</ul> </ul>
</ul> </ul>
<a name="Heating_Controlget"></a> <a name="Heating_Controlget"></a>
<b>Get</b> <ul>N/A</ul><br> <b>Get</b> <ul>N/A</ul><br>
@ -522,33 +523,33 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
<b>Attributes</b> <b>Attributes</b>
<ul> <ul>
<li>delayedExecutionCond <br> <li>delayedExecutionCond <br>
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.
<br><br> <br><br>
<b>Beispiel:</b> <b>Beispiel:</b>
<pre> <pre>
attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT") attr wd delayedExecutionCond isDelayed("$HEATING_CONTROL","$WEEKDAYTIMER","$TIME","$NAME","$EVENT")
</pre> </pre>
Die Parameter $HEATING_CONTROL(timer Name) $TIME $NAME(device Name) $EVENT werden zur Laufzeit durch die echten Werte ersetzt. Die Parameter $HEATING_CONTROL(timer Name) $TIME $NAME(device Name) $EVENT werden zur Laufzeit durch die echten Werte ersetzt.
<br><br> <br><br>
<b>Beispielfunktion:</b> <b>Beispielfunktion:</b>
<pre> <pre>
sub isDelayed($$$$$) { sub isDelayed($$$$$) {
my($hc, $wdt, $tim, $nam, $event ) = @_; my($hc, $wdt, $tim, $nam, $event ) = @_;
my $theSunIsStillshining = ... my $theSunIsStillshining = ...
return ($tim eq "16:30" && $theSunIsStillshining) ; return ($tim eq "16:30" && $theSunIsStillshining) ;
} }
</pre> </pre>
</li> </li>
<li>switchInThePast<br> <li>switchInThePast<br>
Definiert, dass ein abh&aumlngiges Ger&aumlt in der Start- oder Definitionsphase mit einem Wert aus der Vergangheit geschaltet wird auch wenn das Ger&aumlt nicht als Heizung erkannt wurde. Definiert, dass ein abh&aumlngiges Ger&aumlt in der Start- oder Definitionsphase mit einem Wert aus der Vergangheit geschaltet wird auch wenn das Ger&aumlt nicht als Heizung erkannt wurde.
Heizungen werden immer mit einem Wert aus der Vergangenheit geschaltet. Heizungen werden immer mit einem Wert aus der Vergangenheit geschaltet.
</li> </li>
<li><a href="#disable">disable</a></li> <li><a href="#disable">disable</a></li>
<li><a href="#event-on-update-reading">event-on-update-reading</a></li> <li><a href="#event-on-update-reading">event-on-update-reading</a></li>
<li><a href="#event-on-change-reading">event-on-change-reading</a></li> <li><a href="#event-on-change-reading">event-on-change-reading</a></li>
@ -558,4 +559,3 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()}
=end html_DE =end html_DE
=cut =cut

View File

@ -3,6 +3,7 @@
# #
# 98_RandomTimer_Initialize.pm # 98_RandomTimer_Initialize.pm
# written by Dietmar Ortmann # written by Dietmar Ortmann
# Maintained by igami since 02-2018
# #
# This file is part of fhem. # This file is part of fhem.
# #
@ -96,7 +97,7 @@ sub RandomTimer_Define($$)
if(!($timeToSwitch =~ m/^[0-9]{2,4}$/i)); if(!($timeToSwitch =~ m/^[0-9]{2,4}$/i));
RandomTimer_setSwitchmode ($hash, "800/200") if (!defined $hash->{helper}{SWITCHMODE}); RandomTimer_setSwitchmode ($hash, "800/200") if (!defined $hash->{helper}{SWITCHMODE});
$hash->{NAME} = $name; $hash->{NAME} = $name;
$hash->{DEVICE} = $device; $hash->{DEVICE} = $device;
$hash->{helper}{TIMESPEC_START} = $timespec_start; $hash->{helper}{TIMESPEC_START} = $timespec_start;
@ -107,11 +108,11 @@ sub RandomTimer_Define($$)
$hash->{helper}{S_REP} = $srep; $hash->{helper}{S_REP} = $srep;
$hash->{helper}{S_REL} = $srel; $hash->{helper}{S_REL} = $srel;
$hash->{COMMAND} = Value($hash->{DEVICE}); $hash->{COMMAND} = Value($hash->{DEVICE});
#$attr{$name}{verbose} = 4; #$attr{$name}{verbose} = 4;
readingsSingleUpdate ($hash, "TimeToSwitch", $hash->{helper}{TIMETOSWITCH}, 1); readingsSingleUpdate ($hash, "TimeToSwitch", $hash->{helper}{TIMETOSWITCH}, 1);
myRemoveInternalTimer("SetTimer", $hash); myRemoveInternalTimer("SetTimer", $hash);
myInternalTimer ("SetTimer", time(), "RandomTimer_SetTimer", $hash, 0); myInternalTimer ("SetTimer", time(), "RandomTimer_SetTimer", $hash, 0);
@ -125,50 +126,50 @@ sub RandomTimer_SetTimer($) {
my $now = time(); 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);
RandomTimer_setActive($hash, 0); RandomTimer_setActive($hash, 0);
RandomTimer_schaltZeitenErmitteln($hash, $now); RandomTimer_schaltZeitenErmitteln($hash, $now);
RandomTimer_setState($hash); RandomTimer_setState($hash);
Log3 $hash, 4, "[".$hash->{NAME}."]" . " timings RandomTimer on $hash->{DEVICE}: " 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}{startTime})) . " - "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); . strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime}));
my $secToMidnight = 24*3600 -(3600*$hour + 60*$min + $sec); my $secToMidnight = 24*3600 -(3600*$hour + 60*$min + $sec);
my $setExecTime = max($now, $hash->{helper}{startTime}); my $setExecTime = max($now, $hash->{helper}{startTime});
myRemoveInternalTimer("Exec", $hash); myRemoveInternalTimer("Exec", $hash);
myInternalTimer ("Exec", $setExecTime, "RandomTimer_Exec", $hash, 0); myInternalTimer ("Exec", $setExecTime, "RandomTimer_Exec", $hash, 0);
if ($hash->{helper}{REP} gt "") { if ($hash->{helper}{REP} gt "") {
my $setTimerTime = max($now+$secToMidnight + 15, my $setTimerTime = max($now+$secToMidnight + 15,
$hash->{helper}{stopTime}) + $hash->{helper}{TIMETOSWITCH}+15; $hash->{helper}{stopTime}) + $hash->{helper}{TIMETOSWITCH}+15;
myRemoveInternalTimer("SetTimer", $hash); myRemoveInternalTimer("SetTimer", $hash);
myInternalTimer ("SetTimer", $setTimerTime, "RandomTimer_SetTimer", $hash, 0); myInternalTimer ("SetTimer", $setTimerTime, "RandomTimer_SetTimer", $hash, 0);
} }
} }
######################################################################## ########################################################################
# define Test RandomTimer +00:00:05 Brunnen +00:05:00 60 ; # define Test RandomTimer +00:00:05 Brunnen +00:05:00 60 ;
# attr Test room RandomTimerX ; # attr Test room RandomTimerX ;
# attr Test verbose 5 ; # attr Test verbose 5 ;
# define ds at +00:00:30 attr Test disable 1 ; # 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 # 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 # delete RT_Test
sub RandomTimer_Exec($) { sub RandomTimer_Exec($) {
my ($myHash) = @_; my ($myHash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]); my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if (!defined($hash)); return if (!defined($hash));
my $now = time(); my $now = time();
# Wenn aktiv aber disabled, dann timer abschalten, Meldung ausgeben. # Wenn aktiv aber disabled, dann timer abschalten, Meldung ausgeben.
my $active = RandomTimer_isAktive($hash); my $active = RandomTimer_isAktive($hash);
my $disabled = RandomTimer_isDisabled($hash); my $disabled = RandomTimer_isDisabled($hash);
my $stopTimeReached = RandomTimer_stopTimeReached($hash); my $stopTimeReached = RandomTimer_stopTimeReached($hash);
if ($active) { if ($active) {
# wenn temporär ausgeschaltet # wenn temporär ausgeschaltet
if ($disabled) { if ($disabled) {
@ -207,16 +208,16 @@ sub RandomTimer_Exec($) {
RandomTimer_setActive($hash,0); RandomTimer_setActive($hash,0);
return; return;
} }
if (!$disabled) { if (!$disabled) {
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) { if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." starting RandomTimer on $hash->{DEVICE}: " 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}{startTime})) . " - "
. strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime})); . strftime("%H:%M:%S(%d)",localtime($hash->{helper}{stopTime}));
RandomTimer_setActive($hash,1); RandomTimer_setActive($hash,1);
} }
} }
} }
RandomTimer_setState($hash); RandomTimer_setState($hash);
if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) { if ($now>$hash->{helper}{startTime} && $now<$hash->{helper}{stopTime}) {
RandomTimer_device_toggle($hash) if (!$disabled); RandomTimer_device_toggle($hash) if (!$disabled);
@ -254,7 +255,7 @@ sub RandomTimer_down($) {
######################################################################## ########################################################################
sub RandomTimer_setState($) { sub RandomTimer_setState($) {
my ($hash) = @_; my ($hash) = @_;
if (RandomTimer_isDisabled($hash)) { if (RandomTimer_isDisabled($hash)) {
#$hash->{STATE} = "disabled"; #$hash->{STATE} = "disabled";
readingsSingleUpdate ($hash, "state", "disabled", 0); readingsSingleUpdate ($hash, "state", "disabled", 0);
@ -262,20 +263,20 @@ sub RandomTimer_setState($) {
my $state = $hash->{helper}{active} ? "on" : "off"; my $state = $hash->{helper}{active} ? "on" : "off";
readingsSingleUpdate ($hash, "state", $state, 1); readingsSingleUpdate ($hash, "state", $state, 1);
} }
} }
######################################################################## ########################################################################
sub RandomTimer_Attr($$$) { sub RandomTimer_Attr($$$) {
my ($cmd, $name, $attrName, $attrVal) = @_; my ($cmd, $name, $attrName, $attrVal) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
if( $attrName ~~ ["switchmode"] ) { if( $attrName ~~ ["switchmode"] ) {
RandomTimer_setSwitchmode($hash, $attrVal); RandomTimer_setSwitchmode($hash, $attrVal);
} }
if( $attrName ~~ ["disable","disableCond"] ) { if( $attrName ~~ ["disable","disableCond"] ) {
# Schaltung vorziehen, damit bei einem disable abgeschaltet wird. # Schaltung vorziehen, damit bei einem disable abgeschaltet wird.
myRemoveInternalTimer("Exec", $hash); myRemoveInternalTimer("Exec", $hash);
myInternalTimer ("Exec", time()+1, "RandomTimer_Exec", $hash, 0); myInternalTimer ("Exec", time()+1, "RandomTimer_Exec", $hash, 0);
@ -288,7 +289,7 @@ sub RandomTimer_setSwitchmode ($$) {
my ($hash, $attrVal) = @_; my ($hash, $attrVal) = @_;
my $mod = "[".$hash->{NAME} ."] "; my $mod = "[".$hash->{NAME} ."] ";
if(!($attrVal =~ m/^([0-9]{1,3})\/([0-9]{1,3})$/i)) { if(!($attrVal =~ m/^([0-9]{1,3})\/([0-9]{1,3})$/i)) {
Log3 undef, 3, $mod . "invalid switchMode <$attrVal>, use 999/999"; Log3 undef, 3, $mod . "invalid switchMode <$attrVal>, use 999/999";
} else { } else {
@ -317,7 +318,7 @@ sub RandomTimer_schaltZeitenErmitteln ($$) {
RandomTimer_startZeitErmitteln($hash, $now); RandomTimer_startZeitErmitteln($hash, $now);
RandomTimer_stopZeitErmitteln ($hash, $now); RandomTimer_stopZeitErmitteln ($hash, $now);
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate ($hash, "Startzeit", FmtDateTime($hash->{helper}{startTime})); readingsBulkUpdate ($hash, "Startzeit", FmtDateTime($hash->{helper}{startTime}));
readingsBulkUpdate ($hash, "Stoppzeit", FmtDateTime($hash->{helper}{stopTime})); readingsBulkUpdate ($hash, "Stoppzeit", FmtDateTime($hash->{helper}{stopTime}));
@ -385,7 +386,7 @@ sub RandomTimer_stopZeitErmitteln ($$) {
} else { } else {
$stopTime = RandomTimer_zeitBerechnen($now, $hour, $min, $sec); $stopTime = RandomTimer_zeitBerechnen($now, $hour, $min, $sec);
} }
if (!AttrVal($hash->{NAME}, "forceStoptimeSameDay", 0)) { if (!AttrVal($hash->{NAME}, "forceStoptimeSameDay", 0)) {
if ($hash->{helper}{startTime} > $stopTime) { if ($hash->{helper}{startTime} > $stopTime) {
$stopTime = RandomTimer_addDays($stopTime, 1); $stopTime = RandomTimer_addDays($stopTime, 1);
@ -403,9 +404,9 @@ sub RandomTimer_device_toggle ($) {
if ($status ne "on" && $status ne "off" ) { if ($status ne "on" && $status ne "off" ) {
Log3 $hash, 3, "[".$hash->{NAME}."]"." result of function Value($hash->{DEVICE}) must be 'on' or 'off'"; Log3 $hash, 3, "[".$hash->{NAME}."]"." result of function Value($hash->{DEVICE}) must be 'on' or 'off'";
} }
my $sigma = ($status eq "on") my $sigma = ($status eq "on")
? $hash->{helper}{SIGMAWHENON} ? $hash->{helper}{SIGMAWHENON}
: $hash->{helper}{SIGMAWHENOFF}; : $hash->{helper}{SIGMAWHENOFF};
my $zufall = int(rand(1000)); my $zufall = int(rand(1000));
@ -413,13 +414,13 @@ sub RandomTimer_device_toggle ($) {
if ($zufall < $sigma ) { if ($zufall < $sigma ) {
$hash->{COMMAND} = ($status eq "on") ? "off" : "on"; $hash->{COMMAND} = ($status eq "on") ? "off" : "on";
RandomTimer_device_switch($hash); RandomTimer_device_switch($hash);
} }
} }
######################################################################## ########################################################################
sub RandomTimer_device_switch ($) { sub RandomTimer_device_switch ($) {
my ($hash) = @_; my ($hash) = @_;
my $command = "set @ $hash->{COMMAND}"; my $command = "set @ $hash->{COMMAND}";
if ($hash->{COMMAND} eq "on") { if ($hash->{COMMAND} eq "on") {
$command = AttrVal($hash->{NAME}, "onCmd", $command); $command = AttrVal($hash->{NAME}, "onCmd", $command);
@ -438,17 +439,17 @@ sub RandomTimer_device_switch ($) {
######################################################################## ########################################################################
sub RandomTimer_isDisabled($) { sub RandomTimer_isDisabled($) {
my ($hash) = @_; my ($hash) = @_;
my $disable = AttrVal($hash->{NAME}, "disable", 0 ); my $disable = AttrVal($hash->{NAME}, "disable", 0 );
return $disable if($disable); return $disable if($disable);
my $disableCond = AttrVal($hash->{NAME}, "disableCond", "nf" ); my $disableCond = AttrVal($hash->{NAME}, "disableCond", "nf" );
if ($disableCond eq "nf") { if ($disableCond eq "nf") {
return 0; return 0;
} else { } else {
$disable = eval ($disableCond); $disable = eval ($disableCond);
if ($@) { if ($@) {
$@ =~ s/\n/ /g; $@ =~ s/\n/ /g;
Log3 ($hash, 3, "[$hash->{NAME}] ERROR: " . $@ . " EVALUATING " . $disableCond); Log3 ($hash, 3, "[$hash->{NAME}] ERROR: " . $@ . " EVALUATING " . $disableCond);
} }
return $disable; return $disable;
@ -459,7 +460,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
foreach my $hc ( sort keys %{$modules{RandomTimer}{defptr}} ) { foreach my $hc ( sort keys %{$modules{RandomTimer}{defptr}} ) {
my $hash = $modules{RandomTimer}{defptr}{$hc}; my $hash = $modules{RandomTimer}{defptr}{$hc};
my $myHash->{HASH}=$hash; my $myHash->{HASH}=$hash;
RandomTimer_SetTimer($myHash); RandomTimer_SetTimer($myHash);
Log3 undef, 3, "RandomTimer_Wakeup() for $hash->{NAME} done!"; Log3 undef, 3, "RandomTimer_Wakeup() for $hash->{NAME} done!";
@ -470,7 +471,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
1; 1;
=pod =pod
=item device =item device
=item summary imitates the random switch functionality of a timer clock (FS20 ZSU) =item summary imitates the random switch functionality of a timer clock (FS20 ZSU)
=item summary_DE bildet die Zufallsfunktion einer Zeitschaltuhr nach =item summary_DE bildet die Zufallsfunktion einer Zeitschaltuhr nach
=begin html =begin html
@ -562,7 +563,7 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
<b>Examples</b> <b>Examples</b>
<pre> <pre>
attr ZufallsTimerZ disableCond (!isVerreist()) attr ZufallsTimerZ disableCond (!isVerreist())
attr ZufallsTimerZ disableCond (Value("presenceDummy") ne "present") attr ZufallsTimerZ disableCond (Value("presenceDummy") ne "present")
</pre> </pre>
</li> </li>
@ -589,8 +590,8 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
</pre> </pre>
</li> </li>
the decision to switch on or off depends on the state of the device and is evaluated by the funktion Value(<device>). Value() must the decision to switch on or off depends on the state of the device and is evaluated by the funktion Value(<device>). 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: 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:
<pre> <pre>
attr stateFormat EDIPlug_01 {(ReadingsVal("EDIPlug_01","state","nF") =~ m/(ON|on)/i) ? "on" : "off" } attr stateFormat EDIPlug_01 {(ReadingsVal("EDIPlug_01","state","nF") =~ m/(ON|on)/i) ? "on" : "off" }
</pre> </pre>
@ -598,8 +599,8 @@ sub RandomTimer_Wakeup() { # {RandomTimer_Wakeup()}
<pre> <pre>
[EDIPlug] result of function Value(EDIPlug_01) must be 'on' or 'off' [EDIPlug] result of function Value(EDIPlug_01) must be 'on' or 'off'
</pre> </pre>
<li><a name="switchmode">switchmode</a><br> <li><a name="switchmode">switchmode</a><br>
Setting the switchmode you can influence the behavior of switching on/off. 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". 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 attr ZufallsTimerZ switchmode 400/400
</pre> </pre>
</li> </li>
</ul> </ul>
=end html =end html
=cut =cut

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
############################################################################### ###############################################################################
# $Id$ # $Id$
# Maintained by igami since 02-2018
# #
# TODO # TODO
# - document how to include powerMap for other module maintainers # - document how to include powerMap for other module maintainers

View File

@ -33,7 +33,7 @@ FHEM/00_NetzerI2C.pm klausw Sonstige Systeme
FHEM/00_OWX.pm pahenning 1Wire FHEM/00_OWX.pm pahenning 1Wire
FHEM/00_OWX_ASYNC ntruchsess 1Wire FHEM/00_OWX_ASYNC ntruchsess 1Wire
FHEM/00_RPII2C klausw Einplatinencomputer 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_SONOS.pm Reinerlein Multimedia
FHEM/00_TCM.pm klaus-schauer EnOcean FHEM/00_TCM.pm klaus-schauer EnOcean
FHEM/00_THZ.pm immiimmi Heizungssteuerung/Raumklima 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_HCS.pm hjr Automatisierung (oder auch PM)
FHEM/59_LuftdatenInfo igami Bastelecke FHEM/59_LuftdatenInfo igami Bastelecke
FHEM/59_OPENWEATHER.pm tupol Unterstuetzende Dienste/Wettermodule (Link als PM an tupol) 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_PROPLANTA.pm tupol Unterstuetzende Dienste/Wettermodule (Link als PM an tupol)
FHEM/59_WWO.pm baumrasen Unterstuetzende Dienste/Wettermodule FHEM/59_WWO.pm baumrasen Unterstuetzende Dienste/Wettermodule
FHEM/59_Weather.pm neubert 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_FReplacer.pm stefanstrobel Sonstiges
FHEM/98_GEOFANCY.pm loredo Unterstuetzende Dienste FHEM/98_GEOFANCY.pm loredo Unterstuetzende Dienste
FHEM/98_HMinfo.pm martinp876 HomeMatic 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_HTTPMOD.pm stefanstrobel Sonstiges
FHEM/98_Arducounter.pm stefanstrobel Sonstiges FHEM/98_Arducounter.pm stefanstrobel Sonstiges
FHEM/98_Hyperion.pm DeeSPe Beleuchtung FHEM/98_Hyperion.pm DeeSPe Beleuchtung
@ -426,14 +426,14 @@ FHEM/98_ModbusAttr.pm stefanstrobel Sonstiges
FHEM/98_ModbusSET.pm stefanstrobel Sonstiges FHEM/98_ModbusSET.pm stefanstrobel Sonstiges
FHEM/98_ModbusTrovis5576.pm Reinerlein Heizungssteuerung/Raumklima FHEM/98_ModbusTrovis5576.pm Reinerlein Heizungssteuerung/Raumklima
FHEM/98_PID20.pm John Automatisierung 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_SVG.pm rudolfkoenig Frontends/SVG/Plots/logProxy
FHEM/98_THRESHOLD.pm damian-s Automatisierung FHEM/98_THRESHOLD.pm damian-s Automatisierung
FHEM/98_TRAFFIC.pm jmike Unterstuetzende Dienste FHEM/98_TRAFFIC.pm jmike Unterstuetzende Dienste
FHEM/98_UbiquitiPM.pm Wzut Sonstige Systeme FHEM/98_UbiquitiPM.pm Wzut Sonstige Systeme
FHEM/98_UbiquitiOut.pm Wzut Sonstige Systeme FHEM/98_UbiquitiOut.pm Wzut Sonstige Systeme
FHEM/98_Verkehrsinfo.pm martins Unterstuetzende Dienste 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_WOL.pm dietmar63 Unterstuetzende Dienste
FHEM/98_XmlList.pm rudolfkoenig Automatisierung FHEM/98_XmlList.pm rudolfkoenig Automatisierung
FHEM/96_allowed.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_notice.pm mfr69bs Sonstiges
FHEM/98_pilight.pm andreas-fey Unterstuetzende Dienste FHEM/98_pilight.pm andreas-fey Unterstuetzende Dienste
FHEM/98_ping mattwire Sonstiges 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_QRCode.pm Benni Unterstuetzende Dienste
FHEM/98_rain.pm baumrasen Sonstiges FHEM/98_rain.pm baumrasen Sonstiges
FHEM/98_restore.pm rudolfkoenig Sonstiges FHEM/98_restore.pm rudolfkoenig Sonstiges