mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
59_Twilight.pm: bugfix in timer admin
git-svn-id: https://svn.fhem.de/fhem/trunk@23015 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
d1e0ff720f
commit
1602ea563a
@ -41,7 +41,7 @@ use Math::Trig;
|
||||
use Time::Local qw(timelocal_nocheck);
|
||||
use List::Util qw(max min);
|
||||
use GPUtils qw(GP_Import GP_Export);
|
||||
eval { use FHEM::Core::Timer::Helper qw(addTimer removeTimer); 1 };
|
||||
#eval { use FHEM::Core::Timer::Helper qw( addTimer removeTimer optimizeLOT ); 1 };
|
||||
use FHEM::Meta;
|
||||
|
||||
#-- Run before package compilation
|
||||
@ -71,6 +71,7 @@ BEGIN {
|
||||
AttrVal
|
||||
ReadingsVal
|
||||
ReadingsNum
|
||||
ReadingsAge
|
||||
InternalVal
|
||||
IsDisabled
|
||||
Log3
|
||||
@ -81,6 +82,9 @@ BEGIN {
|
||||
FmtTime
|
||||
FmtDateTime
|
||||
strftime
|
||||
perlSyntaxCheck
|
||||
EvalSpecials
|
||||
AnalyzePerlCommand
|
||||
stacktrace
|
||||
)
|
||||
);
|
||||
@ -105,7 +109,6 @@ sub Initialize {
|
||||
return FHEM::Meta::InitMod( __FILE__, $hash );
|
||||
}
|
||||
|
||||
|
||||
################################################################################
|
||||
sub Twilight_Define {
|
||||
my $hash = shift;
|
||||
@ -158,6 +161,8 @@ sub Twilight_Define {
|
||||
|
||||
$attr{$name}{verbose} = 4 if ( $name =~ m/^tst.*$/x );
|
||||
|
||||
#deleteAllRegisteredInternalTimer($hash);
|
||||
|
||||
Log3( $hash, 1, "[$hash->{NAME}] Note: Twilight formerly used weather info from yahoo, but source is offline. Using a guessed Weather type device instead if available!"
|
||||
) if looks_like_number($weather);
|
||||
|
||||
@ -174,23 +179,19 @@ sub Twilight_Define {
|
||||
sub Twilight_Undef {
|
||||
my $hash = shift;
|
||||
my $arg = shift // return;
|
||||
|
||||
deleteAllRegisteredInternalTimer($hash);
|
||||
|
||||
for my $key ( keys %{ $hash->{TW} } ) {
|
||||
Twilight_RemoveInternalTimer( $key, $hash );
|
||||
}
|
||||
Twilight_RemoveInternalTimer( "Midnight", $hash );
|
||||
Twilight_RemoveInternalTimer( "weather", $hash );
|
||||
Twilight_RemoveInternalTimer( "sunpos", $hash );
|
||||
notifyRegexpChanged( $hash, "" );
|
||||
delete $hash->{helper}{extWeather}{regexp};
|
||||
delete $hash->{helper}{extWeather}{dispatch};
|
||||
delete $hash->{helper}{extWeather}{Device};
|
||||
delete $hash->{helper}{extWeather}{Reading};
|
||||
for my $key ( keys %{ $hash->{helper}{extWeather} } ) {
|
||||
delete $hash->{helper}{extWeather}{$key};
|
||||
}
|
||||
delete $hash->{helper}{extWeather};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
################################################################################
|
||||
sub Twilight_Change_DEF {
|
||||
my $hash = shift // return;
|
||||
@ -205,8 +206,8 @@ sub Twilight_Change_DEF {
|
||||
}
|
||||
$newdef = "$hash->{helper}{'.LATITUDE'} $hash->{helper}{'.LONGITUDE'}" if $hash->{helper}{'.LATITUDE'} != AttrVal( 'global', 'latitude', 50.112 ) || $hash->{helper}{'.LONGITUDE'} != AttrVal( 'global', 'longitude', 8.686 );
|
||||
$newdef .= " $hash->{INDOOR_HORIZON} $weather";
|
||||
|
||||
return CommandModify(undef, "$name $newdef");
|
||||
$hash->{DEF} = $newdef;
|
||||
return; # CommandModify(undef, "$name $newdef");
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@ -232,91 +233,169 @@ sub Twilight_Notify {
|
||||
$s = "" if(!defined($s));
|
||||
my $found = ($wname =~ m/^$re$/x || "$wname:$s" =~ m/^$re$/sx);
|
||||
|
||||
if($found) {
|
||||
my $extWeather = ReadingsNum($hash->{helper}{extWeather}{Device}, $hash->{helper}{extWeather}{Reading},-1);
|
||||
my $last = ReadingsNum($name, "cloudCover", -1);
|
||||
|
||||
#here we have to split up for extended forecast handling...
|
||||
|
||||
return if abs ($last - $extWeather) < 6;
|
||||
#my ($cond, $condText) = [-1,"not known"];
|
||||
my $dispatch = defined $hash->{helper}{extWeather} && defined $hash->{helper}{extWeather}{dispatch} ? 1 : 0;
|
||||
|
||||
#$cond = ReadingsNum($hash->{helper}{extWeather}{Device}, $hash->{helper}{extWeather}{dispatch}{cond_code},-2) if $dispatch;
|
||||
#$condText = ReadingsVal($hash->{helper}{extWeather}{Device}, $hash->{helper}{extWeather}{dispatch}{cond_text},"unknown") if $dispatch;
|
||||
|
||||
my $weather_horizon = Twilight_getWeatherHorizon( $hash, $extWeather, 1);
|
||||
#add $sr_weather_horizon and $ss_weather_horizon here, then we will have to do some more Twilight_calc...
|
||||
|
||||
my ($sr, $ss) = Twilight_calc( $hash, $weather_horizon, "7" ); ##these are numbers
|
||||
my $now = time();
|
||||
|
||||
#$hash->{SR_TEST} = $sr;
|
||||
#$hash->{SS_TEST} = $ss;
|
||||
|
||||
#done for today?
|
||||
return if $now > min($ss , $hash->{TW}{ss_weather}{TIME});
|
||||
|
||||
#set potential dates in the past to now
|
||||
$sr = max( $sr, $now - 0.01 );
|
||||
$ss = max( $ss, $now - 0.01 );
|
||||
|
||||
#renew dates and timers?, fire events?
|
||||
my $nextevent = ReadingsVal($name,"nextEvent","none");
|
||||
my $nextEventTime = FmtTime( $sr );
|
||||
|
||||
readingsBeginUpdate( $hash );
|
||||
readingsBulkUpdate( $hash, "cloudCover", $extWeather );
|
||||
#readingsBulkUpdate( $hash, "condition_code", $cond ) if $dispatch;
|
||||
#readingsBulkUpdate( $hash, "condition_txt", $condText ) if $dispatch;
|
||||
|
||||
if ($now < $sr ) {
|
||||
$hash->{TW}{sr_weather}{TIME} = $sr;
|
||||
Twilight_RemoveInternalTimer( "sr_weather", $hash );
|
||||
Twilight_InternalTimer( "sr_weather", $sr, \&Twilight_fireEvent, $hash, 0 );
|
||||
readingsBulkUpdate( $hash, "sr_weather", $nextEventTime );
|
||||
readingsBulkUpdate( $hash, "nextEventTime", $nextEventTime ) if $nextevent eq "sr_weather";
|
||||
}
|
||||
if ($now < $ss ) {
|
||||
$nextEventTime = FmtTime( $ss );
|
||||
$hash->{TW}{ss_weather}{TIME} = $ss;
|
||||
Twilight_RemoveInternalTimer( "ss_weather", $hash );
|
||||
Twilight_InternalTimer( "ss_weather", $ss, \&Twilight_fireEvent, $hash, 0 );
|
||||
readingsBulkUpdate( $hash, "ss_weather", $nextEventTime );
|
||||
readingsBulkUpdate( $hash, "nextEventTime", $nextEventTime ) if $nextevent eq "ss_weather";
|
||||
}
|
||||
|
||||
readingsEndUpdate( $hash, defined( $hash->{LOCAL} ? 0 : 1 ) );
|
||||
#my $swip = $hash->{SWIP};
|
||||
#$hash->{SWIP} = 1 if !$swip;
|
||||
#Twilight_TwilightTimes( $hash, "weather", $extWeather );
|
||||
#$hash->{SWIP} = 0 if !$swip;
|
||||
Twilight_RemoveInternalTimer ("sunpos", $hash);
|
||||
Twilight_InternalTimer ("sunpos", time()+1, \&Twilight_sunpos, $hash, 0);
|
||||
}
|
||||
return Twilight_HandleWeatherData( $hash, 1) if $found;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub Twilight_HandleWeatherData {
|
||||
my $hash = shift // return;
|
||||
my $inNotify = shift // 0;
|
||||
my $wname = $hash->{helper}{extWeather}{Device} // "none";
|
||||
my $name = $hash->{NAME};
|
||||
my ($extWeather, $sr_extWeather, $ss_extWeather);
|
||||
my $dispatch = defined $hash->{helper}{extWeather} && defined $hash->{helper}{extWeather}{dispatch} ? 1 : 0;
|
||||
|
||||
if (!$dispatch
|
||||
|| $dispatch && !defined $hash->{helper}{extWeather}{dispatch}{function} && !defined $hash->{helper}{extWeather}{dispatch}{userfunction} )
|
||||
{
|
||||
$extWeather = ReadingsNum($wname, $hash->{helper}{extWeather}{Reading},-1);
|
||||
} elsif (defined $hash->{helper}{extWeather}{dispatch}{function} ) {
|
||||
#Log3( $hash, 5, "[$hash->{NAME}] before dispatch" );
|
||||
return if ref $hash->{helper}{extWeather}{dispatch}->{function} ne 'CODE';
|
||||
( $extWeather, $sr_extWeather, $ss_extWeather ) = $hash->{helper}{extWeather}{dispatch}->{function}->($hash, $wname);
|
||||
Log3( $hash, 5, "[$hash->{NAME}] after dispatch. results: $extWeather $sr_extWeather $ss_extWeather" );
|
||||
|
||||
} elsif (defined $hash->{helper}{extWeather}{dispatch}{userfunction} ) {
|
||||
#Log3( $hash, 5, "[$hash->{NAME}] before dispatch" );
|
||||
my %specials = (
|
||||
'$WEATHERDEV' => $extWeather,
|
||||
'$WEATHERREADING' => $hash->{helper}{extWeather}{dispatch}{trigger}
|
||||
);
|
||||
my $evalcode = EvalSpecials ($hash->{helper}{extWeather}{dispatch}->{function}, %specials);
|
||||
|
||||
( $extWeather, $sr_extWeather, $ss_extWeather ) =
|
||||
AnalyzePerlCommand( $hash, $evalcode );
|
||||
|
||||
Log3( $hash, 5, "[$hash->{NAME}] external code results: $extWeather $sr_extWeather $ss_extWeather" );
|
||||
|
||||
}
|
||||
|
||||
my $last = ReadingsNum($name, "cloudCover", -1);
|
||||
|
||||
#here we have to split up for extended forecast handling...
|
||||
|
||||
$inNotify ? Log3( $hash, 5, "[$name] NotifyFn called, reading is $extWeather, last is $last" )
|
||||
: Log3( $hash, 5, "[$name] timer based weather update called, reading is $extWeather, last is $last" );
|
||||
|
||||
return if $inNotify && abs ($last - $extWeather) < 6;
|
||||
|
||||
my $weather_horizon = Twilight_getWeatherHorizon( $hash, $extWeather, 1);
|
||||
|
||||
my ($sr, $ss) = Twilight_calc( $hash, $weather_horizon, "7" ); #these are numbers
|
||||
my ($sr_wh,$ss_wh);
|
||||
if (defined $ss_extWeather) {
|
||||
Log3( $hash, 5, "[$name] ss_extWeather exists" );
|
||||
$sr_wh = Twilight_getWeatherHorizon( $hash, $sr_extWeather, 0);
|
||||
$ss_wh = Twilight_getWeatherHorizon( $hash, $ss_extWeather, 0);
|
||||
my ($srt_wh, $sst_wh) = Twilight_calc( $hash, $sr_wh, "7" );
|
||||
$sr = $srt_wh;
|
||||
($srt_wh, $sst_wh) = Twilight_calc( $hash, $ss_wh, "7" );
|
||||
$ss = $sst_wh;
|
||||
}
|
||||
|
||||
my $now = time();
|
||||
Log3( $hash, 5, "[$name] extW-update fn: calc sr_w is ".FmtTime( $sr) .", ss_w is ".FmtTime( $ss) );
|
||||
|
||||
#done for today?
|
||||
return if $inNotify && $now > min($ss , $hash->{TW}{ss_weather}{TIME});
|
||||
Log3( $hash, 5, "[$name] not yet done for today" );
|
||||
|
||||
#set potential dates in the past to now
|
||||
my $sr_passed = 0;
|
||||
my $ss_passed = 0;
|
||||
if ($inNotify) {
|
||||
$sr = max( $sr, $now - 0.01 );
|
||||
$ss = max( $ss, $now - 0.01 );
|
||||
$sr_passed = $hash->{TW}{sr_weather}{TIME} > $sr ? 1 : 0;
|
||||
$ss_passed = $hash->{TW}{ss_weather}{TIME} > $ss ? 1 : 0;
|
||||
}
|
||||
|
||||
#renew dates and timers?, fire events?
|
||||
my $nextevent = ReadingsVal($name,"nextEvent","none");
|
||||
my $nextEventTime = FmtTime( $sr );
|
||||
|
||||
readingsBeginUpdate( $hash );
|
||||
readingsBulkUpdate( $hash, "cloudCover", $extWeather );
|
||||
readingsBulkUpdate( $hash, "cloudCover_sr", $sr_extWeather ) if $sr_wh && $now < $sr;
|
||||
readingsBulkUpdate( $hash, "cloudCover_ss", $ss_extWeather ) if $ss_wh && $now < $ss;
|
||||
|
||||
if ( $now < $sr ) {
|
||||
#deleteSingleRegisteredInternalTimer( "sr_weather", $hash );
|
||||
$hash->{TW}{sr_weather}{TIME} = $sr;
|
||||
resetRegisteredInternalTimer( "sr_weather", $sr, \&Twilight_fireEvent, $hash, 0 );
|
||||
readingsBulkUpdate( $hash, "sr_weather", $nextEventTime ) if $inNotify;
|
||||
readingsBulkUpdate( $hash, "nextEventTime", $nextEventTime ) if $nextevent eq "sr_weather";
|
||||
} elsif ( $sr_passed ) {
|
||||
#deleteSingleRegisteredInternalTimer( "sr_weather", $hash );
|
||||
deleteSingleRegisteredInternalTimer( "sr_weather", $hash, \&Twilight_fireEvent);
|
||||
readingsBulkUpdate( $hash, "sr_weather", $nextEventTime );
|
||||
if ( $nextevent eq "sr_weather" ) {
|
||||
readingsBulkUpdate( $hash, "nextEvent", "ss_weather" ) ;
|
||||
readingsBulkUpdate( $hash, "nextEventTime", FmtTime( $ss ) ) ;
|
||||
readingsBulkUpdate( $hash, "state", "6" );
|
||||
readingsBulkUpdate( $hash, "light", "6" );
|
||||
readingsBulkUpdate( $hash, "aktEvent", "sr_weather" );
|
||||
#deleteSingleRegisteredInternalTimer( "ss_weather", $hash );
|
||||
resetRegisteredInternalTimer( "ss_weather", $ss, \&Twilight_fireEvent, $hash, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $now < $ss ) {
|
||||
$nextEventTime = FmtTime( $ss );
|
||||
#deleteSingleRegisteredInternalTimer( "ss_weather", $hash );
|
||||
$hash->{TW}{ss_weather}{TIME} = $ss;
|
||||
#$hash->{TW}{ss_weather}{SWIP} = 1;
|
||||
resetRegisteredInternalTimer( "ss_weather", $ss, \&Twilight_fireEvent, $hash, 0 );
|
||||
readingsBulkUpdate( $hash, "ss_weather", $nextEventTime ) if $inNotify;
|
||||
readingsBulkUpdate( $hash, "nextEventTime", $nextEventTime ) if $nextevent eq "ss_weather" && !$ss_passed;
|
||||
} elsif ( $ss_passed ) {
|
||||
deleteSingleRegisteredInternalTimer( "ss_weather", $hash, \&Twilight_fireEvent );
|
||||
readingsBulkUpdate( $hash, "ss_weather", $nextEventTime );
|
||||
if ( $nextevent eq "ss_weather" ) {
|
||||
readingsBulkUpdate( $hash, "nextEvent", "ss_indoor" ) ;
|
||||
readingsBulkUpdate( $hash, "nextEventTime", FmtTime( $hash->{TW}{ss_indoor}{TIME} ) ) ;
|
||||
readingsBulkUpdate( $hash, "aktEvent", "ss_weather" );
|
||||
readingsBulkUpdate( $hash, "state", "8" );
|
||||
readingsBulkUpdate( $hash, "light", "4" );
|
||||
}
|
||||
}
|
||||
|
||||
readingsEndUpdate( $hash, defined( $hash->{LOCAL} ? 0 : 1 ) );
|
||||
#my $swip = $hash->{SWIP};
|
||||
#$hash->{SWIP} = 1 if !$swip;
|
||||
#Twilight_TwilightTimes( $hash, "weather", $extWeather );
|
||||
#$hash->{SWIP} = 0 if !$swip;
|
||||
#deleteSingleRegisteredInternalTimer ("sunpos", $hash);
|
||||
return resetRegisteredInternalTimer("sunpos", time()+1, \&Twilight_sunpos, $hash, 0);
|
||||
}
|
||||
|
||||
sub Twilight_Firstrun {
|
||||
my $hash = shift // return;
|
||||
my $name = $hash->{NAME};
|
||||
$hash->{SWIP} = 0;
|
||||
#$hash->{SWIP} = 0;
|
||||
|
||||
my $attrVal = AttrVal( $name,'useExtWeather', $hash->{DEFINE});
|
||||
$attrVal = "$hash->{helper}{extWeather}{Device}:$hash->{helper}{extWeather}{Reading}" if !$attrVal && defined $hash->{helper} && defined $hash->{helper}{extWeather}{Device} && defined $hash->{helper}{extWeather}{Reading};
|
||||
$attrVal = "$hash->{helper}{extWeather}{Device}:$hash->{helper}{extWeather}{trigger}" if !$attrVal && defined $hash->{helper} && defined $hash->{helper}{extWeather}{Device} && defined $hash->{helper}{extWeather}{trigger};
|
||||
|
||||
my $extWeatherVal = 0;
|
||||
|
||||
if ($attrVal) {
|
||||
Twilight_init_ExtWeather_usage( $hash, $attrVal );
|
||||
my $extWeatherVal = ReadingsVal($hash->{helper}{extWeather}{Device}, $hash->{helper}{extWeather}{Reading},"-1");
|
||||
readingsSingleUpdate ($hash, "cloudCover", $extWeatherVal, 0);
|
||||
Twilight_getWeatherHorizon( $hash, $extWeatherVal );
|
||||
Twilight_TwilightTimes( $hash, "weather", $extWeatherVal );
|
||||
$extWeatherVal = ReadingsNum( $name, "cloudCover", ReadingsNum( $hash->{helper}{extWeather}{Device}, $hash->{helper}{extWeather}{Reading}, 0 ) );
|
||||
readingsSingleUpdate ( $hash, "cloudCover", $extWeatherVal, 0 ) if $extWeatherVal;
|
||||
}
|
||||
|
||||
my $mHash = { HASH => $hash };
|
||||
Twilight_sunpos($mHash);
|
||||
Twilight_Midnight($mHash);
|
||||
Twilight_getWeatherHorizon( $hash, $extWeatherVal );
|
||||
|
||||
#next 3: Materials only
|
||||
#Twilight_TwilightTimes( $hash, "mid") if !defined $hash->{helper}{extWeather}{Device};
|
||||
#Twilight_TwilightTimes( $hash, "weather");
|
||||
#return Twilight_HandleWeatherData( $hash, 0);
|
||||
|
||||
my $fnHash = { HASH => $hash };
|
||||
Twilight_sunpos($fnHash) if !$attrVal;
|
||||
Twilight_Midnight($fnHash, 1);
|
||||
delete $hash->{DEFINE};
|
||||
|
||||
return;
|
||||
@ -334,9 +413,9 @@ sub Twilight_Attr {
|
||||
return Twilight_init_ExtWeather_usage($hash, $attrVal);
|
||||
} elsif ($cmd eq "del") {
|
||||
notifyRegexpChanged( $hash, "" );
|
||||
delete $hash->{helper}{extWeather}{regexp};
|
||||
delete $hash->{helper}{extWeather}{Device};
|
||||
delete $hash->{helper}{extWeather}{Reading};
|
||||
for my $key ( keys %{ $hash->{helper}{extWeather} } ) {
|
||||
delete $hash->{helper}{extWeather}{$key};
|
||||
}
|
||||
delete $hash->{helper}{extWeather};
|
||||
}
|
||||
}
|
||||
@ -346,16 +425,28 @@ sub Twilight_init_ExtWeather_usage {
|
||||
my $hash = shift // return;
|
||||
my $devreading = shift // 1000;
|
||||
my $useTimer = shift // 0;
|
||||
my ($extWeather, $extWReading, $err) ;
|
||||
my ($extWeather, $extWReading, $err);
|
||||
my @parts;
|
||||
if (!looks_like_number($devreading)) {
|
||||
($extWeather, $extWReading) = split( ":", $devreading );
|
||||
@parts = split( " ", $devreading, 2 );
|
||||
($extWeather, $extWReading) = split( ":", $parts[0] );
|
||||
return "External weather device seems not to exist" if (!defined $defs{$extWeather} && $init_done);
|
||||
|
||||
### This is the place to allow external dispatch functions...
|
||||
if ($parts[1] && 0) { #&& 0 to disable this part atm...
|
||||
my %specials = (
|
||||
'$WEATHERDEV' => $extWeather,
|
||||
'$WEATHERREADING' => $extWReading
|
||||
);
|
||||
my $err = perlSyntaxCheck( $parts[1], %specials );
|
||||
return $err if ( $err );
|
||||
}
|
||||
} else {
|
||||
#conversion code, try to guess the ext. weather device to replace yahoo
|
||||
my @devices=devspec2array("TYPE=Weather");
|
||||
return "No Weather-Type device found if !$devices[0]";
|
||||
$extWeather = $devices[0];
|
||||
$extWReading = "cloudCover";
|
||||
#$extWReading = "cloudCover";
|
||||
}
|
||||
|
||||
($err, $extWReading) = Twilight_disp_ExtWeather($hash, $extWeather) if !$extWReading;
|
||||
@ -364,7 +455,9 @@ sub Twilight_init_ExtWeather_usage {
|
||||
notifyRegexpChanged($hash, $extWregex);
|
||||
$hash->{helper}{extWeather}{regexp} = $extWregex;
|
||||
$hash->{helper}{extWeather}{Device} = $extWeather;
|
||||
$hash->{helper}{extWeather}{Reading} = $extWReading;
|
||||
$hash->{helper}{extWeather}{Reading} = $extWReading if !$parts[1] && !exists $hash->{helper}{extWeather}{dispatch};
|
||||
$hash->{helper}{extWeather}{trigger} = $extWReading if $parts[1];
|
||||
$hash->{helper}{extWeather}{userfunction} = $parts[1] if $parts[1];
|
||||
return InternalTimer( time(), \&Twilight_Firstrun,$hash,0) if $init_done && $useTimer;
|
||||
return;
|
||||
}
|
||||
@ -375,9 +468,21 @@ sub Twilight_disp_ExtWeather {
|
||||
my ( $err, $extWReading );
|
||||
my $wtype = InternalVal( $extWeather, 'TYPE', undef );
|
||||
return ("No type info about extWeather available!", "none") if !$wtype;
|
||||
for my $key ( keys %{ $hash->{helper}{extWeather} } ) {
|
||||
delete $hash->{helper}{extWeather}{$key};
|
||||
}
|
||||
delete $hash->{helper}{extWeather}{dispatch};
|
||||
|
||||
|
||||
my $dispatch = {
|
||||
"Weather" => {"cloudCover" => "cloudCover", "cond_code" => "code", "cond_text" => "condition"},
|
||||
"Weather" => {
|
||||
"cloudCover" => "cloudCover",
|
||||
"function" => \&getwTYPE_Weather
|
||||
},
|
||||
"PROPLANTA" => {
|
||||
"cloudCover" => "fc0_cloud06",
|
||||
"function" => \&getwTYPE_PROPLANTA
|
||||
}
|
||||
};
|
||||
if (ref $dispatch->{$wtype} eq 'HASH') {
|
||||
$extWReading = $dispatch->{$wtype}{cloudCover};
|
||||
@ -407,61 +512,66 @@ sub Twilight_Get {
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_InternalTimer {
|
||||
my ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone ) = @_;
|
||||
|
||||
my $timerName = "$hash->{NAME}_$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) );
|
||||
addTimer($timerName,$tim, $callback, $mHash, $waitIfInitNotDone );
|
||||
#InternalTimer( $tim, $callback, $mHash, $waitIfInitNotDone );
|
||||
return $mHash;
|
||||
sub resetRegisteredInternalTimer {
|
||||
my ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone, $oldTime ) = @_;
|
||||
deleteSingleRegisteredInternalTimer( $modifier, $hash, $callback );
|
||||
setRegisteredInternalTimer ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone );
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_RemoveInternalTimer {
|
||||
my $modifier = shift;
|
||||
my $hash = shift // return;
|
||||
sub setRegisteredInternalTimer {
|
||||
my ( $modifier, $tim, $callback, $hash, $waitIfInitNotDone ) = @_;
|
||||
|
||||
my $timerName = "$hash->{NAME}_$modifier";
|
||||
my $myHash = $hash->{TIMER}{$timerName};
|
||||
if ( defined($myHash) ) {
|
||||
delete $hash->{TIMER}{$timerName};
|
||||
my $fnHash = {
|
||||
HASH => $hash,
|
||||
NAME => $timerName,
|
||||
MODIFIER => $modifier
|
||||
};
|
||||
if ( defined( $hash->{TIMER}{$timerName} ) ) {
|
||||
Log3( $hash, 1, "[$hash->{NAME}] possible overwriting of timer $timerName - please delete it first" );
|
||||
stacktrace();
|
||||
}
|
||||
else {
|
||||
$hash->{TIMER}{$timerName} = $fnHash;
|
||||
}
|
||||
|
||||
Log3( $hash, 5, "[$hash->{NAME}] setting Timer: $timerName " . FmtDateTime($tim) );
|
||||
InternalTimer( $tim, $callback, $fnHash, $waitIfInitNotDone );
|
||||
return $fnHash;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub deleteSingleRegisteredInternalTimer {
|
||||
my $modifier = shift;
|
||||
my $hash = shift // return;
|
||||
my $callback = shift;
|
||||
|
||||
my $timerName = "$hash->{NAME}_$modifier";
|
||||
my $fnHash = $hash->{TIMER}{$timerName};
|
||||
if ( defined($fnHash) ) {
|
||||
Log3( $hash, 5, "[$hash->{NAME}] removing Timer: $timerName" );
|
||||
removeTimer($timerName);
|
||||
#RemoveInternalTimer($myHash);
|
||||
RemoveInternalTimer($fnHash);
|
||||
delete $hash->{TIMER}{$timerName};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_GetHashIndirekt {
|
||||
my $myHash = shift;
|
||||
my $function = shift // return;
|
||||
|
||||
if ( !defined( $myHash->{HASH} ) ) {
|
||||
|
||||
#Log3 ($hash, 5, "[$function] myHash not valid");
|
||||
return;
|
||||
sub deleteAllRegisteredInternalTimer {
|
||||
my $hash = shift // return;
|
||||
|
||||
for my $key ( keys %{ $hash->{TIMER} } ) {
|
||||
deleteSingleRegisteredInternalTimer( $hash->{TIMER}{$key}{MODIFIER}, $hash );
|
||||
}
|
||||
return $myHash->{HASH};
|
||||
return;
|
||||
}
|
||||
################################################################################
|
||||
|
||||
sub Twilight_midnight_seconds {
|
||||
my $now = shift // return;
|
||||
|
||||
################################################################################
|
||||
sub secondsSinceMidnight {
|
||||
my $now = shift // time();
|
||||
my @time = localtime($now);
|
||||
my $secs = ( $time[2] * 3600 ) + ( $time[1] * 60 ) + $time[0];
|
||||
return $secs;
|
||||
@ -474,11 +584,10 @@ sub Twilight_calc {
|
||||
my $idx = shift // return;
|
||||
|
||||
my $now = time();
|
||||
my $midnight = $now - Twilight_midnight_seconds( $now );
|
||||
my $midnight = $now - secondsSinceMidnight( $now );
|
||||
my $lat = $hash->{helper}{'.LATITUDE'};
|
||||
my $long = $hash->{helper}{'.LONGITUDE'};
|
||||
|
||||
#my $sr = sunrise_abs("Horizon=$deg");
|
||||
my $sr =
|
||||
sr_alt( $now, 1, 0, 0, 0, "Horizon=$deg", undef, undef, undef, $lat,
|
||||
$long );
|
||||
@ -501,13 +610,13 @@ sub Twilight_calc {
|
||||
|
||||
################################################################################
|
||||
sub Twilight_TwilightTimes {
|
||||
my ( $hash, $whitchTimes, $xml ) = @_;
|
||||
my $hash = shift;
|
||||
my $whitchTimes = shift // return;
|
||||
my $firstrun = shift // 0;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
#my $horizon = $hash->{HORIZON};
|
||||
#my $horizon = ReadingsNum($name,"horizon",0);
|
||||
my $swip = $hash->{SWIP};
|
||||
my $swip = !$firstrun;
|
||||
|
||||
my $lat = $hash->{helper}{'.LATITUDE'};
|
||||
my $long = $hash->{helper}{'.LONGITUDE'};
|
||||
@ -535,8 +644,8 @@ sub Twilight_TwilightTimes {
|
||||
$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}{SWIP} = $swip;
|
||||
#$hash->{TW}{$ss}{SWIP} = $swip;
|
||||
|
||||
( $hash->{TW}{$sr}{TIME}, $hash->{TW}{$ss}{TIME} ) =
|
||||
Twilight_calc( $hash, $deg, $idx );
|
||||
@ -570,25 +679,20 @@ sub Twilight_TwilightTimes {
|
||||
0 .. $#ereignisse - 1;
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
my $myHash;
|
||||
my $now = time();
|
||||
my $secSinceMidnight = Twilight_midnight_seconds($now);
|
||||
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";
|
||||
#my @keyListe = qw "DEG LIGHT STATE SWIP TIME NAMENEXT";
|
||||
my @keyListe = qw "DEG LIGHT STATE TIME NAMENEXT";
|
||||
for my $ereignis ( sort keys %{ $hash->{TW} } ) {
|
||||
next if ( $whitchTimes eq "weather" && !( $ereignis =~ m/weather/ ) );
|
||||
|
||||
Twilight_RemoveInternalTimer( $ereignis, $hash ); # if(!$jetztIstMitternacht);
|
||||
if ( defined $hash->{TW}{$ereignis}{TIME} && $hash->{TW}{$ereignis}{TIME} > 0 ) {
|
||||
$myHash = Twilight_InternalTimer( $ereignis, $hash->{TW}{$ereignis}{TIME},
|
||||
deleteSingleRegisteredInternalTimer( $ereignis, $hash, \&Twilight_fireEvent );
|
||||
|
||||
if ( defined $hash->{TW}{$ereignis}{TIME} && $hash->{TW}{$ereignis}{TIME} > $now ) { # had been > 0
|
||||
#my $fnHash =
|
||||
setRegisteredInternalTimer( $ereignis, $hash->{TW}{$ereignis}{TIME},
|
||||
\&Twilight_fireEvent, $hash, 0 );
|
||||
map { $myHash->{$_} = $hash->{TW}{$ereignis}{$_} } @keyListe;
|
||||
#map { $fnHash->{$_} = $hash->{TW}{$ereignis}{$_} } @keyListe;
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,18 +701,23 @@ sub Twilight_TwilightTimes {
|
||||
}
|
||||
################################################################################
|
||||
sub Twilight_fireEvent {
|
||||
my $myHash = shift // return;
|
||||
my $fnHash = shift // return;
|
||||
|
||||
my ($hash, $modifier) = ($fnHash->{HASH}, $fnHash->{MODIFIER});
|
||||
|
||||
my $hash = Twilight_GetHashIndirekt( $myHash, ( caller(0) )[3] );
|
||||
#my $hash = Twilight_GetHashIndirekt( $fnHash, ( caller(0) )[3] );
|
||||
return if ( !defined($hash) );
|
||||
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $event = $myHash->{MODIFIER};
|
||||
#my $modifier = $fnHash->{MODIFIER};
|
||||
my $event = $modifier;
|
||||
my $myHash =$hash->{TW}{$modifier};
|
||||
my $deg = $myHash->{DEG};
|
||||
my $light = $myHash->{LIGHT};
|
||||
my $state = $myHash->{STATE};
|
||||
my $swip = $myHash->{SWIP};
|
||||
#my $swip = $myHash->{SWIP};
|
||||
|
||||
my $eventTime = $myHash->{TIME};
|
||||
my $nextEvent = $myHash->{NAMENEXT};
|
||||
@ -622,7 +731,8 @@ sub Twilight_fireEvent {
|
||||
: "undefined";
|
||||
|
||||
my $doTrigger = !( defined( $hash->{LOCAL} ) )
|
||||
&& ( abs($delta) < 6 || $swip && $state gt $oldState );
|
||||
#&& ( abs($delta) < 6 || $swip && $state gt $oldState );
|
||||
&& ( abs($delta) < 6 || $state gt $oldState );
|
||||
|
||||
Log3(
|
||||
$hash, 4,
|
||||
@ -646,93 +756,34 @@ sub Twilight_fireEvent {
|
||||
|
||||
################################################################################
|
||||
sub Twilight_Midnight {
|
||||
my $myHash = shift // return;
|
||||
my $fnHash = shift // return;
|
||||
my $firstrun = shift // 0;
|
||||
|
||||
my $hash = Twilight_GetHashIndirekt( $myHash, ( caller(0) )[3] );
|
||||
return if ( !defined($hash) );
|
||||
|
||||
return Twilight_HandleWeatherData( $hash, "Mid", $firstrun, ReadingsNum($hash->{NAME},"cloudCover",0) );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_WeatherTimerUpdate {
|
||||
my $myHash = shift // return;
|
||||
my $swip = shift // 1;
|
||||
my ($hash, $modifier) = ($fnHash->{HASH}, $fnHash->{MODIFIER});
|
||||
|
||||
my $hash = Twilight_GetHashIndirekt( $myHash, ( caller(0) )[3] );
|
||||
#my $hash = Twilight_GetHashIndirekt( $fnHash, ( caller(0) )[3] );
|
||||
return if ( !defined($hash) );
|
||||
|
||||
return Twilight_HandleWeatherData( $hash, "weather", $swip );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
sub Twilight_HandleWeatherData {
|
||||
my $hash = shift;
|
||||
my $mode = shift;
|
||||
my $swip = shift // return;
|
||||
my $cloudCover = shift // ReadingsNum($hash->{NAME},"cloudCover",0);
|
||||
|
||||
$hash->{SWIP} = $swip;
|
||||
|
||||
Twilight_getWeatherHorizon( $hash, $cloudCover );
|
||||
Twilight_TwilightTimes( $hash, $mode, $cloudCover );
|
||||
return Twilight_StandardTimerSet( $hash );
|
||||
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_RepeatTimerSet {
|
||||
my $hash = shift;
|
||||
my $mode = shift // return;
|
||||
|
||||
my $midnight = time() + 60;
|
||||
|
||||
Twilight_RemoveInternalTimer( "Midnight", $hash );
|
||||
return Twilight_InternalTimer( "Midnight", $midnight, \&Twilight_Midnight, $hash,
|
||||
0 )
|
||||
if $mode eq "Mid";
|
||||
|
||||
return Twilight_InternalTimer( "Midnight", $midnight,
|
||||
\&Twilight_WeatherTimerUpdate, $hash, 0 );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_StandardTimerSet {
|
||||
my $hash = shift // return;
|
||||
my $midnight = time() - Twilight_midnight_seconds( time() ) + 24 * 3600 + 1;
|
||||
|
||||
Twilight_RemoveInternalTimer( "Midnight", $hash );
|
||||
Twilight_InternalTimer( "Midnight", $midnight, \&Twilight_Midnight, $hash, 0 );
|
||||
return Twilight_WeatherTimerSet($hash);
|
||||
}
|
||||
|
||||
################################################################################
|
||||
sub Twilight_WeatherTimerSet {
|
||||
my $hash = shift // return;
|
||||
my $now = time();
|
||||
|
||||
Twilight_RemoveInternalTimer( "weather", $hash );
|
||||
for my $key ( "sr_weather", "ss_weather" ) {
|
||||
my $tim = $hash->{TW}{$key}{TIME};
|
||||
if ( $tim - 60 * 60 > $now + 60 ) {
|
||||
Twilight_InternalTimer( "weather", $tim - 60 * 60,
|
||||
\&Twilight_WeatherTimerUpdate, $hash, 0 );
|
||||
last;
|
||||
}
|
||||
|
||||
if (!defined $hash->{helper}{extWeather}{Device} || $firstrun) {
|
||||
Twilight_TwilightTimes( $hash, "mid", $firstrun);
|
||||
Twilight_sunposTimerSet($hash);
|
||||
} else {
|
||||
Twilight_HandleWeatherData( $hash, 0);
|
||||
Twilight_TwilightTimes( $hash, "mid", $firstrun);
|
||||
}
|
||||
|
||||
return;
|
||||
my $now = time();
|
||||
my $midnight = $now - secondsSinceMidnight( $now ) + DAYSECONDS + 1;
|
||||
return resetRegisteredInternalTimer( "Midnight", $midnight, \&Twilight_Midnight, $hash, 0 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
sub Twilight_sunposTimerSet {
|
||||
my $hash = shift // return;
|
||||
|
||||
Twilight_RemoveInternalTimer( "sunpos", $hash );
|
||||
return Twilight_InternalTimer( "sunpos", time() + $hash->{SUNPOS_OFFSET},
|
||||
\&Twilight_sunpos, $hash, 0 );
|
||||
return resetRegisteredInternalTimer( "sunpos", time() + $hash->{SUNPOS_OFFSET}, \&Twilight_sunpos, $hash, 0 );
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@ -756,9 +807,11 @@ sub Twilight_getWeatherHorizon {
|
||||
|
||||
################################################################################
|
||||
sub Twilight_sunpos {
|
||||
my $myHash = shift // return;
|
||||
|
||||
my $hash = Twilight_GetHashIndirekt( $myHash, ( caller(0) )[3] );
|
||||
my $fnHash = shift // return;
|
||||
|
||||
my ($hash, $modifier) = ($fnHash->{HASH}, $fnHash->{MODIFIER});
|
||||
|
||||
#my $hash = Twilight_GetHashIndirekt( $fnHash, ( caller(0) )[3] );
|
||||
return if ( !defined($hash) );
|
||||
|
||||
my $hashName = $hash->{NAME};
|
||||
@ -870,20 +923,16 @@ sub Twilight_sunpos {
|
||||
$twilight_weather =
|
||||
int( ( $dElevation - $hash->{WEATHER_HORIZON} + 12.0 ) / 18.0 * 1000 )
|
||||
/ 10;
|
||||
Log3( $hash, 5, "[$hash->{NAME}] Original weather readings" );
|
||||
Log3( $hash, 5, "[$hashName] Original weather readings" );
|
||||
} else {
|
||||
my $extDev = $hash->{helper}{extWeather}{Device};
|
||||
my $extReading = $hash->{helper}{extWeather}{Reading};
|
||||
#my $extDev = $hash->{helper}{extWeather}{Device};
|
||||
#my $extReading = $hash->{helper}{extWeather}{Reading} ;
|
||||
#my ( $extDev, $extReading ) = split( ":", $ExtWeather );
|
||||
my $extWeatherHorizont = ReadingsNum($extDev ,$extReading , -1 );
|
||||
my $extWeatherHorizont = ReadingsNum($hashName,'cloudCover' , -1 );
|
||||
if ( $extWeatherHorizont >= 0 ) {
|
||||
$extWeatherHorizont = min (100, $extWeatherHorizont);
|
||||
Log3( $hash, 5,
|
||||
"[$hash->{NAME}] "
|
||||
. "New weather readings from: "
|
||||
. $extDev . ":"
|
||||
. $extReading . ":"
|
||||
. $extWeatherHorizont );
|
||||
"[$hashName] Using cloudCover value $extWeatherHorizont" );
|
||||
$twilight_weather = $twilight -
|
||||
int( 0.007 * ( $extWeatherHorizont**2 ) )
|
||||
; ## SCM: 100% clouds => 30% light (rough estimation)
|
||||
@ -893,11 +942,7 @@ sub Twilight_sunpos {
|
||||
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" );
|
||||
"[$hashName] No useable cloudCover value available: ${$extWeatherHorizont}, taking existant weather horizon." );
|
||||
}
|
||||
}
|
||||
|
||||
@ -957,6 +1002,60 @@ sub twilight {
|
||||
return h2hms_fmt($t);
|
||||
}
|
||||
|
||||
###########
|
||||
# Dispatch functions
|
||||
|
||||
sub getTwilightHours {
|
||||
my $hash = shift // return;
|
||||
my $hour = ( localtime )[2];
|
||||
my $sr_hour = ( localtime( $hash->{TW}{sr_weather}{TIME}))[2];
|
||||
my $ss_hour = ( localtime( $hash->{TW}{ss_weather}{TIME}))[2];
|
||||
return $hour, $sr_hour, $ss_hour;
|
||||
}
|
||||
|
||||
sub getwTYPE_Weather {
|
||||
my $hash = shift // return;
|
||||
|
||||
my @ret;
|
||||
my $extDev = $hash->{helper}{extWeather}{Device};
|
||||
my ($hour, $sr_hour, $ss_hour) = getTwilightHours($hash);
|
||||
|
||||
my $rAge = int(ReadingsAge("extDev","cloudCover",0)/3600);
|
||||
|
||||
$ret[0] = $rAge < 24 ? ReadingsNum($extDev,"cloudCover",0) : 50;
|
||||
Log3( $hash, 5, "[$hash->{NAME}] function is called, cc is $ret[0], hours sr: $sr_hour, ss: $ss_hour" );
|
||||
|
||||
my $hfc_sr = max( 0 , $sr_hour - $hour ) + $rAge; #remark: needs some additionals logic for midnight updates! (ReadingsAge()?)
|
||||
my $hfc_ss = max( 0 , $ss_hour - $hour ) + $rAge;
|
||||
|
||||
$ret[1] = $hfc_sr && $rAge < 24 ? ReadingsNum($extDev,"hfc${hfc_sr}_cloudCover",0) : $ret[0];
|
||||
$ret[2] = $hfc_ss && $rAge < 24 ? ReadingsNum($extDev,"hfc${hfc_ss}_cloudCover",0) : $ret[0];
|
||||
|
||||
return @ret;
|
||||
}
|
||||
|
||||
|
||||
sub getwTYPE_PROPLANTA {
|
||||
my $hash = shift // return;
|
||||
|
||||
|
||||
my $extDev = $hash->{helper}{extWeather}{Device};
|
||||
my @hour = getTwilightHours($hash);
|
||||
|
||||
my $fc_day0 = secondsSinceMidnight( time() ) > 60 ? 0 : 1;
|
||||
my $fc_day1 = $fc_day0 + 1;
|
||||
|
||||
my @ret;
|
||||
for (my $i = 0; $i < 3 ; $i++) {
|
||||
$hour[$i] <= 4 ? $ret[$i] = ReadingsNum($extDev,"fc${fc_day0}_cloud03",0) :
|
||||
$hour[$i] <= 7 ? $ret[$i] = ReadingsNum($extDev,"fc${fc_day0}_cloud06",0) :
|
||||
$hour[$i] <= 10 ? $ret[$i] = ReadingsNum($extDev,"fc${fc_day0}_cloud09",0) :
|
||||
$hour[$i] <= 19 ? $ret[$i] = ReadingsNum($extDev,"fc${fc_day0}_cloud18",0) :
|
||||
$hour[$i] <= 22 ? $ret[$i] = ReadingsNum($extDev,"fc${fc_day0}_cloud21",0) :
|
||||
$ret[$i] = ReadingsNum($extDev,"fc${fc_day1}_cloud03",0);
|
||||
}
|
||||
return @ret;;
|
||||
}
|
||||
1;
|
||||
|
||||
__END__
|
||||
@ -1292,8 +1391,7 @@ Anwendungsbeispiel:
|
||||
"Math::Trig" : "0",
|
||||
"Time::Local" : "0",
|
||||
"strict" : "0",
|
||||
"warnings" : "0",
|
||||
"FHEM::Core::Timer::Helper" : "0"
|
||||
"warnings" : "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user