change OpenWeatherMapAPI Code and extend 59_Weather.pm Modul
This commit is contained in:
		
							
								
								
									
										500
									
								
								59_Weather.pm
									
									
									
									
									
								
							
							
						
						
									
										500
									
								
								59_Weather.pm
									
									
									
									
									
								
							@@ -32,10 +32,13 @@ package main;
 | 
				
			|||||||
use strict;
 | 
					use strict;
 | 
				
			||||||
use warnings;
 | 
					use warnings;
 | 
				
			||||||
use Time::HiRes qw(gettimeofday);
 | 
					use Time::HiRes qw(gettimeofday);
 | 
				
			||||||
#use HttpUtils;
 | 
					use experimental qw /switch/;
 | 
				
			||||||
 | 
					use Readonly;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use FHEM::Meta;
 | 
					use FHEM::Meta;
 | 
				
			||||||
use vars qw($FW_ss);
 | 
					use vars qw($FW_ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# use Data::Dumper;    # for Debug only
 | 
					# use Data::Dumper;    # for Debug only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my %pressure_trend_txt_en = ( 0 => "steady", 1 => "rising", 2 => "falling" );
 | 
					my %pressure_trend_txt_en = ( 0 => "steady", 1 => "rising", 2 => "falling" );
 | 
				
			||||||
@@ -205,50 +208,60 @@ my @iconlist = (
 | 
				
			|||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_LanguageInitialize($) {
 | 
					sub Weather_LanguageInitialize {
 | 
				
			||||||
    my ($lang) = @_;
 | 
					    my $lang = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( $lang eq "de" ) {
 | 
					    given ($lang) {
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_de;
 | 
					        when ('de') {
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_de;
 | 
					            %wdays_txt_i18n          = %wdays_txt_de;
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_de;
 | 
					            @directions_txt_i18n     = @directions_txt_de;
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_de;
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_de;
 | 
				
			||||||
    }
 | 
					            %status_items_txt_i18n   = %status_items_txt_de;
 | 
				
			||||||
    elsif ( $lang eq "nl" ) {
 | 
					        }
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_nl;
 | 
					
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_nl;
 | 
					        when ('nl') {
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_nl;
 | 
					            %wdays_txt_i18n          = %wdays_txt_nl;
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_nl;
 | 
					            @directions_txt_i18n     = @directions_txt_nl;
 | 
				
			||||||
    }
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_nl;
 | 
				
			||||||
    elsif ( $lang eq "fr" ) {
 | 
					            %status_items_txt_i18n   = %status_items_txt_nl;
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_fr;
 | 
					        }
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_fr;
 | 
					
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_fr;
 | 
					        when ('fr') {
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_fr;
 | 
					            %wdays_txt_i18n          = %wdays_txt_fr;
 | 
				
			||||||
    }
 | 
					            @directions_txt_i18n     = @directions_txt_fr;
 | 
				
			||||||
    elsif ( $lang eq "pl" ) {
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_fr;
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_pl;
 | 
					            %status_items_txt_i18n   = %status_items_txt_fr;
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_pl;
 | 
					        }
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_pl;
 | 
					
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_pl;
 | 
					        when ('pl') {
 | 
				
			||||||
    }
 | 
					            %wdays_txt_i18n          = %wdays_txt_pl;
 | 
				
			||||||
    elsif ( $lang eq "it" ) {
 | 
					            @directions_txt_i18n     = @directions_txt_pl;
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_it;
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_pl;
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_it;
 | 
					            %status_items_txt_i18n   = %status_items_txt_pl;
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_it;
 | 
					        }
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_it;
 | 
					
 | 
				
			||||||
    }
 | 
					        when ('it') {
 | 
				
			||||||
    else {
 | 
					            %wdays_txt_i18n          = %wdays_txt_it;
 | 
				
			||||||
        %wdays_txt_i18n          = %wdays_txt_en;
 | 
					            @directions_txt_i18n     = @directions_txt_it;
 | 
				
			||||||
        @directions_txt_i18n     = @directions_txt_en;
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_it;
 | 
				
			||||||
        %pressure_trend_txt_i18n = %pressure_trend_txt_en;
 | 
					            %status_items_txt_i18n   = %status_items_txt_it;
 | 
				
			||||||
        %status_items_txt_i18n   = %status_items_txt_en;
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default {
 | 
				
			||||||
 | 
					            %wdays_txt_i18n          = %wdays_txt_en;
 | 
				
			||||||
 | 
					            @directions_txt_i18n     = @directions_txt_en;
 | 
				
			||||||
 | 
					            %pressure_trend_txt_i18n = %pressure_trend_txt_en;
 | 
				
			||||||
 | 
					            %status_items_txt_i18n   = %status_items_txt_en;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_DebugCodes($) {
 | 
					sub Weather_DebugCodes {
 | 
				
			||||||
    my ($lang) = @_;
 | 
					    my $lang = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my @YahooCodes_i18n = YahooWeatherAPI_getYahooCodes($lang);
 | 
					    my @YahooCodes_i18n = YahooWeatherAPI_getYahooCodes($lang);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Debug "Weather Code List, see http://developer.yahoo.com/weather/#codes";
 | 
					    Debug "Weather Code List, see http://developer.yahoo.com/weather/#codes";
 | 
				
			||||||
@@ -257,37 +270,44 @@ sub Weather_DebugCodes($) {
 | 
				
			|||||||
          sprintf( "%2d %30s %30s", $c, $iconlist[$c], $YahooCodes_i18n[$c] );
 | 
					          sprintf( "%2d %30s %30s", $c, $iconlist[$c], $YahooCodes_i18n[$c] );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
sub Weather_Initialize($) {
 | 
					sub Weather_Initialize {
 | 
				
			||||||
    my ($hash) = @_;
 | 
					    my $hash = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $hash->{DefFn}   = 'Weather_Define';
 | 
					    $hash->{DefFn}        = \&Weather_Define;
 | 
				
			||||||
    $hash->{UndefFn} = 'Weather_Undef';
 | 
					    $hash->{UndefFn}      = \&Weather_Undef;
 | 
				
			||||||
    $hash->{GetFn}   = 'Weather_Get';
 | 
					    $hash->{GetFn}        = \&Weather_Get;
 | 
				
			||||||
    $hash->{SetFn}   = 'Weather_Set';
 | 
					    $hash->{SetFn}        = \&Weather_Set;
 | 
				
			||||||
    $hash->{AttrList} =
 | 
					    $hash->{AttrFn}       = \&Weather_Attr;
 | 
				
			||||||
 | 
					    $hash->{AttrList}     =
 | 
				
			||||||
        'disable:0,1 '
 | 
					        'disable:0,1 '
 | 
				
			||||||
      . 'forecast:multiple-strict,hourly,daily '
 | 
					      . 'forecast:multiple-strict,hourly,daily '
 | 
				
			||||||
      . 'forecastLimit '
 | 
					      . 'forecastLimit '
 | 
				
			||||||
      . 'alerts:0,1 '
 | 
					      . 'alerts:0,1 '
 | 
				
			||||||
      . $readingFnAttributes;
 | 
					      . $readingFnAttributes;
 | 
				
			||||||
    $hash->{NotifyFn} = 'Weather_Notify';
 | 
					    $hash->{NotifyFn}     = \&Weather_Notify;
 | 
				
			||||||
 | 
					    $hash->{parseParams}  = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FHEM::Meta::InitMod( __FILE__, $hash );
 | 
					    return FHEM::Meta::InitMod( __FILE__, $hash );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub degrees_to_direction($@) {
 | 
					sub degrees_to_direction {
 | 
				
			||||||
    my ( $degrees, @directions_txt_i18n ) = @_;
 | 
					    my $degrees             = shift;
 | 
				
			||||||
 | 
					    my $directions_txt_i18n = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $mod = int( ( ( $degrees + 11.25 ) % 360 ) / 22.5 );
 | 
					    my $mod = int( ( ( $degrees + 11.25 ) % 360 ) / 22.5 );
 | 
				
			||||||
    return $directions_txt_i18n[$mod];
 | 
					    return $directions_txt_i18n->[$mod];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Weather_ReturnWithError($$) {
 | 
					sub Weather_ReturnWithError {
 | 
				
			||||||
    my ( $hash, $responseRef ) = @_;
 | 
					    my $hash        = shift;
 | 
				
			||||||
 | 
					    my $responseRef = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name = $hash->{NAME};
 | 
					    my $name = $hash->{NAME};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    readingsBeginUpdate($hash);
 | 
					    readingsBeginUpdate($hash);
 | 
				
			||||||
@@ -310,10 +330,10 @@ sub Weather_ReturnWithError($$) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Weather_RetrieveCallbackFn($) {
 | 
					sub Weather_RetrieveCallbackFn {
 | 
				
			||||||
    my $name        = shift;
 | 
					    my $name = shift;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return undef
 | 
					    return
 | 
				
			||||||
      unless ( IsDevice($name) );
 | 
					      unless ( IsDevice($name) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $hash        = $defs{$name};
 | 
					    my $hash        = $defs{$name};
 | 
				
			||||||
@@ -325,10 +345,14 @@ sub Weather_RetrieveCallbackFn($) {
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
        Weather_ReturnWithError( $hash, $responseRef );
 | 
					        Weather_ReturnWithError( $hash, $responseRef );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Weather_WriteReadings($$) {
 | 
					sub Weather_WriteReadings {
 | 
				
			||||||
    my ( $hash, $dataRef ) = @_;
 | 
					    my $hash    = shift; 
 | 
				
			||||||
 | 
					    my $dataRef = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name    = $hash->{NAME};
 | 
					    my $name    = $hash->{NAME};
 | 
				
			||||||
    my $hourly  = ( AttrVal( $name, 'forecast', '' ) =~ m{hourly}xms ? 1: 0 );
 | 
					    my $hourly  = ( AttrVal( $name, 'forecast', '' ) =~ m{hourly}xms ? 1: 0 );
 | 
				
			||||||
    my $daily   = ( AttrVal( $name, 'forecast', '' ) =~ m{daily}xms ? 1 : 0 );
 | 
					    my $daily   = ( AttrVal( $name, 'forecast', '' ) =~ m{daily}xms ? 1 : 0 );
 | 
				
			||||||
@@ -353,31 +377,31 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
    readingsBulkUpdate( $hash, 'lastError', '' );
 | 
					    readingsBulkUpdate( $hash, 'lastError', '' );
 | 
				
			||||||
    foreach my $r ( keys %{$dataRef} ) {
 | 
					    foreach my $r ( keys %{$dataRef} ) {
 | 
				
			||||||
        readingsBulkUpdate( $hash, $r, $dataRef->{$r} )
 | 
					        readingsBulkUpdate( $hash, $r, $dataRef->{$r} )
 | 
				
			||||||
          if (  ref( $dataRef->{$r} ) ne 'HASH'
 | 
					          if ( ref( $dataRef->{$r} ) ne 'HASH'
 | 
				
			||||||
            and ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
					            && ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
				
			||||||
        readingsBulkUpdate( $hash, '.license', $dataRef->{license}->{text} );
 | 
					        readingsBulkUpdate( $hash, '.license', $dataRef->{license}->{text} );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ### current
 | 
					    ### current
 | 
				
			||||||
    if ( defined( $dataRef->{current} )
 | 
					    if ( defined( $dataRef->{current} )
 | 
				
			||||||
        and ref( $dataRef->{current} ) eq 'HASH' )
 | 
					        && ref( $dataRef->{current} ) eq 'HASH' )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        while ( my ( $r, $v ) = each %{ $dataRef->{current} } ) {
 | 
					        while ( my ( $r, $v ) = each %{ $dataRef->{current} } ) {
 | 
				
			||||||
            readingsBulkUpdate( $hash, $r, $v )
 | 
					            readingsBulkUpdate( $hash, $r, $v )
 | 
				
			||||||
              if (  ref( $dataRef->{$r} ) ne 'HASH'
 | 
					              if ( ref( $dataRef->{$r} ) ne 'HASH'
 | 
				
			||||||
                and ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
					                && ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        readingsBulkUpdate( $hash, 'icon',
 | 
					        readingsBulkUpdate( $hash, 'icon',
 | 
				
			||||||
            $iconlist[ $dataRef->{current}->{code} ] );
 | 
					            $iconlist[ $dataRef->{current}->{code} ] );
 | 
				
			||||||
        if (    defined( $dataRef->{current}->{wind_direction} )
 | 
					        if (   defined( $dataRef->{current}->{wind_direction} )
 | 
				
			||||||
            and $dataRef->{current}->{wind_direction}
 | 
					            && $dataRef->{current}->{wind_direction}
 | 
				
			||||||
            and defined( $dataRef->{current}->{wind_speed} )
 | 
					            && defined( $dataRef->{current}->{wind_speed} )
 | 
				
			||||||
            and $dataRef->{current}->{wind_speed} )
 | 
					            && $dataRef->{current}->{wind_speed} )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            my $wdir =
 | 
					            my $wdir =
 | 
				
			||||||
              degrees_to_direction( $dataRef->{current}->{wind_direction},
 | 
					              degrees_to_direction( $dataRef->{current}->{wind_direction},
 | 
				
			||||||
                @directions_txt_i18n );
 | 
					                \@directions_txt_i18n );
 | 
				
			||||||
            readingsBulkUpdate( $hash, 'wind_condition',
 | 
					            readingsBulkUpdate( $hash, 'wind_condition',
 | 
				
			||||||
                    'Wind: '
 | 
					                    'Wind: '
 | 
				
			||||||
                  . $wdir . ' '
 | 
					                  . $wdir . ' '
 | 
				
			||||||
@@ -387,15 +411,15 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ### forecast
 | 
					    ### forecast
 | 
				
			||||||
    if (  ref( $dataRef->{forecast} ) eq 'HASH'
 | 
					    if ( ref( $dataRef->{forecast} ) eq 'HASH'
 | 
				
			||||||
      and ($hourly or $daily) )
 | 
					      && ($hourly || $daily) )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ## hourly
 | 
					        ## hourly
 | 
				
			||||||
        if (
 | 
					        if (
 | 
				
			||||||
                defined( $dataRef->{forecast}->{hourly} )
 | 
					               defined( $dataRef->{forecast}->{hourly} )
 | 
				
			||||||
            and ref( $dataRef->{forecast}->{hourly} ) eq 'ARRAY'
 | 
					            && ref( $dataRef->{forecast}->{hourly} ) eq 'ARRAY'
 | 
				
			||||||
            and scalar( @{ $dataRef->{forecast}->{hourly} } ) > 0
 | 
					            && scalar( @{ $dataRef->{forecast}->{hourly} } ) > 0
 | 
				
			||||||
            and $hourly
 | 
					            && $hourly
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            my $i = 0;
 | 
					            my $i = 0;
 | 
				
			||||||
@@ -406,8 +430,8 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                while ( my ( $r, $v ) = each %{$fc} ) {
 | 
					                while ( my ( $r, $v ) = each %{$fc} ) {
 | 
				
			||||||
                    readingsBulkUpdate( $hash, $f . $r, $v )
 | 
					                    readingsBulkUpdate( $hash, $f . $r, $v )
 | 
				
			||||||
                      if (  ref( $dataRef->{$r} ) ne 'HASH'
 | 
					                      if ( ref( $dataRef->{$r} ) ne 'HASH'
 | 
				
			||||||
                        and ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
					                        && ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                readingsBulkUpdate(
 | 
					                readingsBulkUpdate(
 | 
				
			||||||
                    $hash,
 | 
					                    $hash,
 | 
				
			||||||
@@ -417,19 +441,19 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (
 | 
					                if (
 | 
				
			||||||
                    defined(
 | 
					                    defined(
 | 
				
			||||||
                        $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_direction}
 | 
					                       $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_direction}
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    and $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_direction}
 | 
					                    && $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_direction}
 | 
				
			||||||
                    and defined(
 | 
					                    && defined(
 | 
				
			||||||
                        $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_speed}
 | 
					                        $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_speed}
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    and $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_speed}
 | 
					                    && $dataRef->{forecast}->{hourly}[ $i - 1 ]{wind_speed}
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    my $wdir = degrees_to_direction(
 | 
					                    my $wdir = degrees_to_direction(
 | 
				
			||||||
                        $dataRef->{forecast}
 | 
					                        $dataRef->{forecast}
 | 
				
			||||||
                          ->{hourly}[ $i - 1 ]{wind_direction},
 | 
					                          ->{hourly}[ $i - 1 ]{wind_direction},
 | 
				
			||||||
                        @directions_txt_i18n
 | 
					                        \@directions_txt_i18n
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    readingsBulkUpdate(
 | 
					                    readingsBulkUpdate(
 | 
				
			||||||
                        $hash,
 | 
					                        $hash,
 | 
				
			||||||
@@ -441,16 +465,16 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                last if ( $i == $limit and $limit > 0 );
 | 
					                last if ( $i == $limit && $limit > 0 );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ## daily
 | 
					        ## daily
 | 
				
			||||||
        if (
 | 
					        if (
 | 
				
			||||||
                defined( $dataRef->{forecast}->{daily} )
 | 
					               defined( $dataRef->{forecast}->{daily} )
 | 
				
			||||||
            and ref( $dataRef->{forecast}->{daily} ) eq 'ARRAY'
 | 
					            && ref( $dataRef->{forecast}->{daily} ) eq 'ARRAY'
 | 
				
			||||||
            and scalar( @{ $dataRef->{forecast}->{daily} } ) > 0
 | 
					            && scalar( @{ $dataRef->{forecast}->{daily} } ) > 0
 | 
				
			||||||
            and $daily
 | 
					            && $daily
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            my $i = 0;
 | 
					            my $i = 0;
 | 
				
			||||||
@@ -461,8 +485,8 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                while ( my ( $r, $v ) = each %{$fc} ) {
 | 
					                while ( my ( $r, $v ) = each %{$fc} ) {
 | 
				
			||||||
                    readingsBulkUpdate( $hash, $f . $r, $v )
 | 
					                    readingsBulkUpdate( $hash, $f . $r, $v )
 | 
				
			||||||
                      if (  ref( $dataRef->{$r} ) ne 'HASH'
 | 
					                      if ( ref( $dataRef->{$r} ) ne 'HASH'
 | 
				
			||||||
                        and ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
					                        && ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                readingsBulkUpdate(
 | 
					                readingsBulkUpdate(
 | 
				
			||||||
                    $hash,
 | 
					                    $hash,
 | 
				
			||||||
@@ -472,18 +496,18 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (
 | 
					                if (
 | 
				
			||||||
                    defined(
 | 
					                    defined(
 | 
				
			||||||
                        $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction}
 | 
					                       $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction}
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    and $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction}
 | 
					                    && $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction}
 | 
				
			||||||
                    and defined(
 | 
					                    && defined(
 | 
				
			||||||
                        $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_speed}
 | 
					                        $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_speed}
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    and $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_speed}
 | 
					                    && $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_speed}
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    my $wdir = degrees_to_direction(
 | 
					                    my $wdir = degrees_to_direction(
 | 
				
			||||||
                        $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction},
 | 
					                        $dataRef->{forecast}->{daily}[ $i - 1 ]{wind_direction},
 | 
				
			||||||
                        @directions_txt_i18n
 | 
					                        \@directions_txt_i18n
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    readingsBulkUpdate(
 | 
					                    readingsBulkUpdate(
 | 
				
			||||||
                        $hash,
 | 
					                        $hash,
 | 
				
			||||||
@@ -495,18 +519,18 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                last if ( $i == $limit and $limit > 0 );
 | 
					                last if ( $i == $limit && $limit > 0 );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (  ref( $dataRef->{alerts} ) eq 'HASH'
 | 
					    if ( ref( $dataRef->{alerts} ) eq 'HASH'
 | 
				
			||||||
      and $alerts )
 | 
					      && $alerts )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      while ( my ( $r, $v ) = each %{ $dataRef->{alerts} } ) {
 | 
					      while ( my ( $r, $v ) = each %{ $dataRef->{alerts} } ) {
 | 
				
			||||||
            readingsBulkUpdate( $hash, $r, $v )
 | 
					            readingsBulkUpdate( $hash, $r, $v )
 | 
				
			||||||
              if (  ref( $dataRef->{$r} ) ne 'HASH'
 | 
					              if ( ref( $dataRef->{$r} ) ne 'HASH'
 | 
				
			||||||
                and ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
					                && ref( $dataRef->{$r} ) ne 'ARRAY' );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -524,13 +548,15 @@ sub Weather_WriteReadings($$) {
 | 
				
			|||||||
    readingsEndUpdate( $hash, 1 );
 | 
					    readingsEndUpdate( $hash, 1 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} );
 | 
					    Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_GetUpdate($) {
 | 
					sub Weather_GetUpdate {
 | 
				
			||||||
    my ($hash) = @_;
 | 
					    my $hash = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name = $hash->{NAME};
 | 
					    my $name = $hash->{NAME};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( $attr{$name} && $attr{$name}->{disable} ) {
 | 
					    if ( $attr{$name} && $attr{$name}->{disable} ) {
 | 
				
			||||||
@@ -543,34 +569,19 @@ sub Weather_GetUpdate($) {
 | 
				
			|||||||
        Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} );
 | 
					        Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        $hash->{fhem}->{api}->{exclude} = Weather_parseForcastAttr($hash);
 | 
					 | 
				
			||||||
        $hash->{fhem}->{api}->setRetrieveData;
 | 
					        $hash->{fhem}->{api}->setRetrieveData;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 1;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_parseForcastAttr {
 | 
					sub Weather_Get {
 | 
				
			||||||
    my $hash      = shift;
 | 
					    my $hash = shift // return;
 | 
				
			||||||
    my $name      = $hash->{NAME};
 | 
					    my $aRef = shift // return;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    my @exclude   = qw 'alerts minutely hourly daily';
 | 
					 | 
				
			||||||
    my @forecast  = split(',',AttrVal($name,'forcast','') . (AttrVal($name,'alerts',0) ? ',alerts' : ''));
 | 
					 | 
				
			||||||
    my %exclude =();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @exclude{@exclude} = @exclude;
 | 
					    my $name = shift @$aRef // return;
 | 
				
			||||||
    delete @exclude{@forecast};
 | 
					    my $reading = shift @$aRef // return;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return join(',',keys %exclude);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
sub Weather_Get($@) {
 | 
					 | 
				
			||||||
    my ( $hash, @a ) = @_;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return "argument is missing" if ( int(@a) != 2 );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    my $reading = $a[1];
 | 
					 | 
				
			||||||
    my $value;
 | 
					    my $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( defined( $hash->{READINGS}->{$reading} ) ) {
 | 
					    if ( defined( $hash->{READINGS}->{$reading} ) ) {
 | 
				
			||||||
@@ -585,42 +596,50 @@ sub Weather_Get($@) {
 | 
				
			|||||||
        return "Unknown reading $reading, choose one of " . $rt;
 | 
					        return "Unknown reading $reading, choose one of " . $rt;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return "$a[0] $reading => $value";
 | 
					    return "$name $reading => $value";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_Set($@) {
 | 
					sub Weather_Set {
 | 
				
			||||||
    my ( $hash, @a ) = @_;
 | 
					    my $hash = shift // return;
 | 
				
			||||||
 | 
					    my $aRef = shift // return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $cmd = $a[1];
 | 
					    my $name = shift @$aRef // return;
 | 
				
			||||||
 | 
					    my $cmd  = shift @$aRef
 | 
				
			||||||
 | 
					      // return qq{"set $name" needs at least one argument};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # usage check
 | 
					    # usage check
 | 
				
			||||||
    if ( ( @a == 2 ) && ( $a[1] eq "update" ) ) {
 | 
					    if ( scalar(@{$aRef}) == 0
 | 
				
			||||||
 | 
					      && $cmd eq 'update' )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        Weather_DisarmTimer($hash);
 | 
					        Weather_DisarmTimer($hash);
 | 
				
			||||||
        Weather_GetUpdate($hash);
 | 
					        Weather_GetUpdate($hash);
 | 
				
			||||||
        return undef;
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( ( @a >= 2 ) && ( $a[1] eq "newLocation" ) ) {
 | 
					    elsif ( scalar(@{$aRef}) == 1
 | 
				
			||||||
 | 
					        &&  $cmd eq "newLocation" )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        if (   $hash->{API} eq 'DarkSkyAPI'
 | 
					        if (   $hash->{API} eq 'DarkSkyAPI'
 | 
				
			||||||
            or $hash->{API} eq 'OpenWeatherMapAPI'
 | 
					            || $hash->{API} eq 'OpenWeatherMapAPI'
 | 
				
			||||||
            or $hash->{API} eq 'wundergroundAPI'
 | 
					            || $hash->{API} eq 'wundergroundAPI'
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            my ($lat,$long);
 | 
					            my ($lat,$long);
 | 
				
			||||||
            ($lat,$long) = split(',',$a[2])
 | 
					            ($lat,$long) = split(',',$aRef->[0])
 | 
				
			||||||
              if ( defined($a[2]) and $a[2] );
 | 
					              if ( defined($aRef->[0]) && $aRef->[0] );
 | 
				
			||||||
            ($lat,$long) = split(',',$hash->{fhem}->{LOCATION})
 | 
					            ($lat,$long) = split(',',$hash->{fhem}->{LOCATION})
 | 
				
			||||||
              unless ( defined($lat)
 | 
					              unless ( defined($lat)
 | 
				
			||||||
                and defined($long)
 | 
					                && defined($long)
 | 
				
			||||||
                and $lat =~ /(-?\d+(\.\d+)?)/
 | 
					                && $lat =~ m{(-?\d+(\.\d+)?)}xms
 | 
				
			||||||
                and $long =~ /(-?\d+(\.\d+)?)/ );
 | 
					                && $long =~ m{(-?\d+(\.\d+)?)}xms );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $hash->{fhem}->{api}->setLocation($lat,$long);
 | 
					            $hash->{fhem}->{api}->setLocation($lat,$long);
 | 
				
			||||||
            Weather_DisarmTimer($hash);
 | 
					            Weather_DisarmTimer($hash);
 | 
				
			||||||
            Weather_GetUpdate($hash);
 | 
					            Weather_GetUpdate($hash);
 | 
				
			||||||
            return undef;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else { return 'this API is not ' . $a[1] .' supported' }
 | 
					        else { return 'this API is not ' . $aRef->[0] .' supported' }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        return "Unknown argument $cmd, choose one of update:noArg newLocation";
 | 
					        return "Unknown argument $cmd, choose one of update:noArg newLocation";
 | 
				
			||||||
@@ -628,27 +647,33 @@ sub Weather_Set($@) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###################################
 | 
					###################################
 | 
				
			||||||
sub Weather_RearmTimer($$) {
 | 
					sub Weather_RearmTimer {
 | 
				
			||||||
    my ( $hash, $t ) = @_;
 | 
					    my $hash  = shift;
 | 
				
			||||||
 | 
					    my $t     = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Log3( $hash, 4, "Weather $hash->{NAME}: Rearm new Timer" );
 | 
					    Log3( $hash, 4, "Weather $hash->{NAME}: Rearm new Timer" );
 | 
				
			||||||
    InternalTimer( $t, "Weather_GetUpdate", $hash, 0 );
 | 
					    InternalTimer( $t, "Weather_GetUpdate", $hash, 0 );
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Weather_DisarmTimer($) {
 | 
					sub Weather_DisarmTimer {
 | 
				
			||||||
    my ($hash) = @_;
 | 
					    my $hash = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RemoveInternalTimer($hash);
 | 
					    RemoveInternalTimer($hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Weather_Notify($$) {
 | 
					sub Weather_Notify {
 | 
				
			||||||
    my ( $hash, $dev ) = @_;
 | 
					    my $hash  = shift;
 | 
				
			||||||
    my $name = $hash->{NAME};
 | 
					    my $dev   = shift;
 | 
				
			||||||
    my $type = $hash->{TYPE};
 | 
					    
 | 
				
			||||||
 | 
					    my $name  = $hash->{NAME};
 | 
				
			||||||
 | 
					    my $type  = $hash->{TYPE};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if ( $dev->{NAME} ne "global" );
 | 
					    return if ( $dev->{NAME} ne "global" );
 | 
				
			||||||
    return if ( !grep( m/^INITIALIZED|REREADCFG$/, @{ $dev->{CHANGED} } ) );
 | 
					    return if ( !grep { /^INITIALIZED|REREADCFG$/ } @{ $dev->{CHANGED} } );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # return if($attr{$name} && $attr{$name}->{disable});
 | 
					    # return if($attr{$name} && $attr{$name}->{disable});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -665,14 +690,17 @@ sub Weather_Notify($$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ### quick run GetUpdate then Demo
 | 
					    ### quick run GetUpdate then Demo
 | 
				
			||||||
    Weather_GetUpdate($hash)
 | 
					    Weather_GetUpdate($hash)
 | 
				
			||||||
      if ( defined( $hash->{APIKEY} ) and lc( $hash->{APIKEY} ) eq 'demo' );
 | 
					      if ( defined( $hash->{APIKEY} ) && lc( $hash->{APIKEY} ) eq 'demo' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return undef;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
sub Weather_Define($$) {
 | 
					sub Weather_Define {
 | 
				
			||||||
    my ( $hash, $def ) = @_;
 | 
					    my $hash  = shift // return;
 | 
				
			||||||
 | 
					    my $aRef  = shift // return;
 | 
				
			||||||
 | 
					    my $hRef  = shift // undef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return $@ unless ( FHEM::Meta::SetInternals($hash) );
 | 
					    return $@ unless ( FHEM::Meta::SetInternals($hash) );
 | 
				
			||||||
    use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
 | 
					    use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
 | 
				
			||||||
@@ -680,42 +708,33 @@ sub Weather_Define($$) {
 | 
				
			|||||||
    my $usage =
 | 
					    my $usage =
 | 
				
			||||||
"syntax: define <name> Weather [API=<API>] [apikey=<apikey>] [location=<location>] [interval=<interval>] [lang=<lang>]";
 | 
					"syntax: define <name> Weather [API=<API>] [apikey=<apikey>] [location=<location>] [interval=<interval>] [lang=<lang>]";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # defaults
 | 
					 | 
				
			||||||
    my $API      = "DarkSkyAPI,cachemaxage:600";
 | 
					 | 
				
			||||||
    my $interval = 3600;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # parse parameters
 | 
					 | 
				
			||||||
    my ( $arrayref, $hashref ) = parseParams($def);
 | 
					 | 
				
			||||||
    my @a = @{$arrayref};
 | 
					 | 
				
			||||||
    my %h = %{$hashref};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # check minimum syntax
 | 
					    # check minimum syntax
 | 
				
			||||||
    return $usage unless ( scalar @a == 2 );
 | 
					    return $usage unless ( scalar @{$aRef} == 2 );
 | 
				
			||||||
    my $name = $a[0];
 | 
					    my $name = $aRef->[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $location = $h{location} if exists $h{location};
 | 
					    my $location  = $hRef->{location} // undef;
 | 
				
			||||||
    my $apikey   = $h{apikey}   if exists $h{apikey};
 | 
					    my $apikey    = $hRef->{apikey} // undef;
 | 
				
			||||||
    my $lang     = $h{lang}     if exists $h{lang};
 | 
					    my $lang      = $hRef->{lang} // undef;
 | 
				
			||||||
    $interval = $h{interval} if exists $h{interval};
 | 
					    my $interval  = $hRef->{interval} // 3600;
 | 
				
			||||||
    $API      = $h{API}      if exists $h{API};
 | 
					    my $API       = $hRef->{API} // "DarkSkyAPI,cachemaxage:600";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # evaluate API options
 | 
					    # evaluate API options
 | 
				
			||||||
    my ( $api, $apioptions ) = split( ',', $API, 2 );
 | 
					    my ( $api, $apioptions ) = split( ',', $API, 2 );
 | 
				
			||||||
    $apioptions = "" unless ( defined($apioptions) );
 | 
					    $apioptions = "" unless ( defined($apioptions) );
 | 
				
			||||||
    eval { require "$api.pm"; };
 | 
					    eval { require $api . '.pm'; };
 | 
				
			||||||
    return "$name: cannot load API $api: $@" if ($@);
 | 
					    return "$name: cannot load API $api: $@" if ($@);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $hash->{NOTIFYDEV}          = "global";
 | 
					    $hash->{NOTIFYDEV}          = "global";
 | 
				
			||||||
    $hash->{fhem}->{interfaces} = "temperature;humidity;wind";
 | 
					    $hash->{fhem}->{interfaces} = "temperature;humidity;wind";
 | 
				
			||||||
    $hash->{fhem}->{LOCATION}   = (
 | 
					    $hash->{fhem}->{LOCATION}   = (
 | 
				
			||||||
        ( defined($location) and $location )
 | 
					        ( defined($location) && $location )
 | 
				
			||||||
        ? $location
 | 
					        ? $location
 | 
				
			||||||
        : AttrVal( 'global', 'latitude', 'error' ) . ','
 | 
					        : AttrVal( 'global', 'latitude', 'error' ) . ','
 | 
				
			||||||
          . AttrVal( 'global', 'longitude', 'error' )
 | 
					          . AttrVal( 'global', 'longitude', 'error' )
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    $hash->{INTERVAL} = $interval;
 | 
					    $hash->{INTERVAL} = $interval;
 | 
				
			||||||
    $hash->{LANG}     = (
 | 
					    $hash->{LANG}     = (
 | 
				
			||||||
        ( defined($lang) and $lang )
 | 
					        ( defined($lang) && $lang )
 | 
				
			||||||
        ? $lang
 | 
					        ? $lang
 | 
				
			||||||
        : lc( AttrVal( 'global', 'language', 'de' ) )
 | 
					        : lc( AttrVal( 'global', 'language', 'de' ) )
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@@ -739,58 +758,89 @@ sub Weather_Define($$) {
 | 
				
			|||||||
            apikey     => $hash->{APIKEY},
 | 
					            apikey     => $hash->{APIKEY},
 | 
				
			||||||
            location   => $hash->{fhem}->{LOCATION},
 | 
					            location   => $hash->{fhem}->{LOCATION},
 | 
				
			||||||
            apioptions => $hash->{APIOPTIONS},
 | 
					            apioptions => $hash->{APIOPTIONS},
 | 
				
			||||||
            language   => $hash->{LANG}
 | 
					            language   => $hash->{LANG},
 | 
				
			||||||
            exclude    => Weather_parseForcastAttr($hash),
 | 
					            forecast   => AttrVal($name,'forecast',''),
 | 
				
			||||||
 | 
					            alerts     => AttrVal($name,'alerts',0)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Weather_GetUpdate($hash) if ($init_done);
 | 
					    Weather_GetUpdate($hash)
 | 
				
			||||||
 | 
					      if ($init_done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return undef;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
sub Weather_Undef($$) {
 | 
					sub Weather_Undef {
 | 
				
			||||||
    my ( $hash, $arg ) = @_;
 | 
					    my $hash  = shift;
 | 
				
			||||||
 | 
					    my $arg   = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RemoveInternalTimer($hash);
 | 
					    RemoveInternalTimer($hash);
 | 
				
			||||||
    return undef;
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub Weather_Attr {
 | 
				
			||||||
 | 
					    my ( $cmd, $name, $attrName, $attrVal ) = @_;
 | 
				
			||||||
 | 
					    my $hash = $defs{$name};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    given ($attrName) {
 | 
				
			||||||
 | 
					        when ('forecast') {
 | 
				
			||||||
 | 
					            if ( $cmd eq 'set' ) {
 | 
				
			||||||
 | 
					                $hash->{fhem}->{api}->setForecast($attrVal)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $hash->{fhem}->{api}->setForecast();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        when ('alerts') {
 | 
				
			||||||
 | 
					            if ( $cmd eq 'set' ) {
 | 
				
			||||||
 | 
					                $hash->{fhem}->{api}->setAlerts($attrVal);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $hash->{fhem}->{api}->setAlerts();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Icon Parameter
 | 
					# Icon Parameter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use constant ICONHIGHT => 120;
 | 
					Readonly my $ICONWIDTH => 175;
 | 
				
			||||||
use constant ICONWIDTH => 175;
 | 
					Readonly my $ICONSCALE => 0.5;
 | 
				
			||||||
use constant ICONSCALE => 0.5;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherIconIMGTag($) {
 | 
					sub WeatherIconIMGTag {
 | 
				
			||||||
    my $width  = int( ICONSCALE * ICONWIDTH );
 | 
					    my $icon    = shift;
 | 
				
			||||||
    my ($icon) = @_;
 | 
					
 | 
				
			||||||
    my $url    = FW_IconURL("weather/$icon");
 | 
					    my $width   = int( $ICONSCALE * $ICONWIDTH );
 | 
				
			||||||
    my $style  = " width=$width";
 | 
					    my $url     = FW_IconURL("weather/$icon");
 | 
				
			||||||
 | 
					    my $style   = " width=$width";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return "<img src=\"$url\"$style alt=\"$icon\">";
 | 
					    return "<img src=\"$url\"$style alt=\"$icon\">";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#####################################
 | 
					#####################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherAsHtmlV($;$$) {
 | 
					sub WeatherAsHtmlV {
 | 
				
			||||||
    my ( $d, $op1, $op2 ) = @_;
 | 
					    my $d   = shift;
 | 
				
			||||||
 | 
					    my $op1 = shift;
 | 
				
			||||||
 | 
					    my $op2 = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
					    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $h     = $defs{$d};
 | 
					    my $h     = $defs{$d};
 | 
				
			||||||
    my $width = int( ICONSCALE * ICONWIDTH );
 | 
					    my $width = int( $ICONSCALE * $ICONWIDTH );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $ret = '<table class="weather">';
 | 
					    my $ret = '<table class="weather">';
 | 
				
			||||||
    my $fc;
 | 
					    my $fc;
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
        defined($f)
 | 
					        defined($f)
 | 
				
			||||||
        and (  $f eq 'h'
 | 
					        && ( $f eq 'h'
 | 
				
			||||||
            or $f eq 'd' )
 | 
					          || $f eq 'd' )
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $fc = ( $f eq 'd' ? 'fc' : 'hfc' );
 | 
					        $fc = ( $f eq 'd' ? 'fc' : 'hfc' );
 | 
				
			||||||
@@ -799,7 +849,7 @@ sub WeatherAsHtmlV($;$$) {
 | 
				
			|||||||
        $fc = (
 | 
					        $fc = (
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                defined( $h->{READINGS}->{fc1_day_of_week} )
 | 
					                defined( $h->{READINGS}->{fc1_day_of_week} )
 | 
				
			||||||
                  and $h->{READINGS}->{fc1_day_of_week}
 | 
					                  && $h->{READINGS}->{fc1_day_of_week}
 | 
				
			||||||
            ) ? 'fc' : 'hfc'
 | 
					            ) ? 'fc' : 'hfc'
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -816,7 +866,7 @@ sub WeatherAsHtmlV($;$$) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
					    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
				
			||||||
        if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
					        if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
				
			||||||
            and $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
					            && $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $ret .= sprintf(
 | 
					            $ret .= sprintf(
 | 
				
			||||||
'<tr><td class="weatherIcon" width=%d>%s</td><td class="weatherValue"><span class="weatherDay">%s: %s</span><br><span class="weatherMin">min %s°C</span> <span class="weatherMax">max %s°C</span><br>%s</td></tr>',
 | 
					'<tr><td class="weatherIcon" width=%d>%s</td><td class="weatherValue"><span class="weatherDay">%s: %s</span><br><span class="weatherMin">min %s°C</span> <span class="weatherMax">max %s°C</span><br>%s</td></tr>',
 | 
				
			||||||
@@ -846,21 +896,25 @@ sub WeatherAsHtmlV($;$$) {
 | 
				
			|||||||
    return $ret;
 | 
					    return $ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherAsHtml($;$$) {
 | 
					sub WeatherAsHtml {
 | 
				
			||||||
    my ( $d, $op1, $op2 ) = @_;
 | 
					    my $d   = shift;
 | 
				
			||||||
 | 
					    my $op1 = shift;
 | 
				
			||||||
 | 
					    my $op2 = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
					    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WeatherAsHtmlV( $d, $f, $items );
 | 
					    return WeatherAsHtmlV( $d, $f, $items );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherAsHtmlH($;$$) {
 | 
					sub WeatherAsHtmlH {
 | 
				
			||||||
    my ( $d, $op1, $op2 ) = @_;
 | 
					    my $d   = shift;
 | 
				
			||||||
 | 
					    my $op1 = shift;
 | 
				
			||||||
 | 
					    my $op2 = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
					    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $h     = $defs{$d};
 | 
					    my $h     = $defs{$d};
 | 
				
			||||||
    my $width = int( ICONSCALE * ICONWIDTH );
 | 
					    my $width = int( $ICONSCALE * $ICONWIDTH );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $format =
 | 
					    my $format =
 | 
				
			||||||
'<td><table border=1><tr><td class="weatherIcon" width=%d>%s</td></tr><tr><td class="weatherValue">%s</td></tr><tr><td class="weatherValue">%s°C %s%%</td></tr><tr><td class="weatherValue">%s</td></tr></table></td>';
 | 
					'<td><table border=1><tr><td class="weatherIcon" width=%d>%s</td></tr><tr><td class="weatherValue">%s</td></tr><tr><td class="weatherValue">%s°C %s%%</td></tr><tr><td class="weatherValue">%s</td></tr></table></td>';
 | 
				
			||||||
@@ -869,8 +923,8 @@ sub WeatherAsHtmlH($;$$) {
 | 
				
			|||||||
    my $fc;
 | 
					    my $fc;
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
        defined($f)
 | 
					        defined($f)
 | 
				
			||||||
        and (  $f eq 'h'
 | 
					        && ( $f eq 'h'
 | 
				
			||||||
            or $f eq 'd' )
 | 
					          || $f eq 'd' )
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $fc = ( $f eq 'd' ? 'fc' : 'hfc' );
 | 
					        $fc = ( $f eq 'd' ? 'fc' : 'hfc' );
 | 
				
			||||||
@@ -879,7 +933,7 @@ sub WeatherAsHtmlH($;$$) {
 | 
				
			|||||||
        $fc = (
 | 
					        $fc = (
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                defined( $h->{READINGS}->{fc1_day_of_week} )
 | 
					                defined( $h->{READINGS}->{fc1_day_of_week} )
 | 
				
			||||||
                  and $h->{READINGS}->{fc1_day_of_week}
 | 
					                  && $h->{READINGS}->{fc1_day_of_week}
 | 
				
			||||||
            ) ? 'fc' : 'hfc'
 | 
					            ) ? 'fc' : 'hfc'
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -914,7 +968,7 @@ sub WeatherAsHtmlH($;$$) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
					    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
				
			||||||
        if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
					        if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
				
			||||||
            and $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
					            && $h->{READINGS}->{"${fc}${i}_low_c"} )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $ret .= sprintf( '<td class="weatherMin">min %s°C</td>',
 | 
					            $ret .= sprintf( '<td class="weatherMin">min %s°C</td>',
 | 
				
			||||||
                ReadingsVal( $d, "${fc}${i}_low_c", " - " ) );
 | 
					                ReadingsVal( $d, "${fc}${i}_low_c", " - " ) );
 | 
				
			||||||
@@ -932,7 +986,7 @@ sub WeatherAsHtmlH($;$$) {
 | 
				
			|||||||
        ReadingsVal( $d, "wind_condition", "" ) );
 | 
					        ReadingsVal( $d, "wind_condition", "" ) );
 | 
				
			||||||
    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
					    for ( my $i = 1 ; $i < $items ; $i++ ) {
 | 
				
			||||||
        if ( defined( $h->{READINGS}->{"${fc}${i}_high_c"} )
 | 
					        if ( defined( $h->{READINGS}->{"${fc}${i}_high_c"} )
 | 
				
			||||||
            and $h->{READINGS}->{"${fc}${i}_high_c"} )
 | 
					            && $h->{READINGS}->{"${fc}${i}_high_c"} )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $ret .= sprintf( '<td class="weatherMax">max %s°C</td>',
 | 
					            $ret .= sprintf( '<td class="weatherMax">max %s°C</td>',
 | 
				
			||||||
                ReadingsVal( $d, "${fc}${i}_high_c", " - " ) );
 | 
					                ReadingsVal( $d, "${fc}${i}_high_c", " - " ) );
 | 
				
			||||||
@@ -944,8 +998,10 @@ sub WeatherAsHtmlH($;$$) {
 | 
				
			|||||||
    return $ret;
 | 
					    return $ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherAsHtmlD($;$$) {
 | 
					sub WeatherAsHtmlD {
 | 
				
			||||||
    my ( $d, $op1, $op2 ) = @_;
 | 
					    my $d   = shift;
 | 
				
			||||||
 | 
					    my $op1 = shift;
 | 
				
			||||||
 | 
					    my $op2 = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
					    my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -955,19 +1011,23 @@ sub WeatherAsHtmlD($;$$) {
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
        WeatherAsHtmlH( $d, $f, $items );
 | 
					        WeatherAsHtmlH( $d, $f, $items );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WeatherCheckOptions($@) {
 | 
					sub WeatherCheckOptions {
 | 
				
			||||||
    my ( $d, $op1, $op2 ) = @_;
 | 
					    my $d   = shift;
 | 
				
			||||||
 | 
					    my $op1 = shift;
 | 
				
			||||||
 | 
					    my $op2 = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $items = $op2;
 | 
					    my $items = $op2;
 | 
				
			||||||
    my $f     = $op1;
 | 
					    my $f     = $op1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( defined($op1) and $op1 and $op1 =~ /[0-9]/g ) { $items = $op1; }
 | 
					    if ( defined($op1) && $op1 && $op1 =~ m{[0-9]}xms ) { $items = $op1; }
 | 
				
			||||||
    if ( defined($op2) and $op2 and $op2 =~ /[dh]/g )  { $f     = $op2; }
 | 
					    if ( defined($op2) && $op2 && $op2 =~ m{[dh]}xms )  { $f     = $op2; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $f =~ tr/dh/./cd if ( defined $f and $f );
 | 
					    $f =~ tr/dh/./cd if ( defined $f && $f );
 | 
				
			||||||
    $items =~ tr/0-9/./cd if ( defined($items) and $items );
 | 
					    $items =~ tr/0-9/./cd if ( defined($items) && $items );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $items = 6 if ( !$items );
 | 
					    $items = 6 if ( !$items );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1053,9 +1113,8 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <table>
 | 
					        <table>
 | 
				
			||||||
        <tr><td>API</td><td><code>DarkSkyAPI</code></td></tr>
 | 
					        <tr><td>API</td><td><code>DarkSkyAPI</code></td></tr>
 | 
				
			||||||
        <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code><br>duration
 | 
					        <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code><br>duration
 | 
				
			||||||
          in seconds to retrieve the forecast from the cache instead from the API<br><code>extend=hourly</code>
 | 
					          in seconds to retrieve the forecast from the cache instead from the API</td></tr>
 | 
				
			||||||
      <br>extends the number of hours forecast records to 149</td></tr>
 | 
					 | 
				
			||||||
        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
					        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
				
			||||||
          geographic coordinates in degrees of the location for which the
 | 
					          geographic coordinates in degrees of the location for which the
 | 
				
			||||||
          weather is forecast; if missing, the values of the attributes
 | 
					          weather is forecast; if missing, the values of the attributes
 | 
				
			||||||
@@ -1067,7 +1126,7 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <table>
 | 
					        <table>
 | 
				
			||||||
        <tr><td>API</td><td><code>OpenWeatherMapAPI</code></td></tr>
 | 
					        <tr><td>API</td><td><code>OpenWeatherMapAPI</code></td></tr>
 | 
				
			||||||
        <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code><br>duration
 | 
					        <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code><br>duration
 | 
				
			||||||
          in seconds to retrieve the forecast from the cache instead from the API</td></tr>
 | 
					          in seconds to retrieve the forecast from the cache instead from the API</td></tr>
 | 
				
			||||||
        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
					        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
				
			||||||
          geographic coordinates in degrees of the location for which the
 | 
					          geographic coordinates in degrees of the location for which the
 | 
				
			||||||
@@ -1080,7 +1139,7 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <table>
 | 
					        <table>
 | 
				
			||||||
        <tr><td>API</td><td><code>wundergroundAPI</code></td></tr>
 | 
					        <tr><td>API</td><td><code>wundergroundAPI</code></td></tr>
 | 
				
			||||||
        <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code><br>duration
 | 
					        <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code><br>duration
 | 
				
			||||||
          in seconds to retrieve the forecast from the cache instead from the API<br><code>stationId:ID-Num</code>
 | 
					          in seconds to retrieve the forecast from the cache instead from the API<br><code>stationId:ID-Num</code>
 | 
				
			||||||
      <br>Station ID of the station to be read.</td></tr>
 | 
					      <br>Station ID of the station to be read.</td></tr>
 | 
				
			||||||
        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
					        <tr><td>location</td><td><code><latitude,longitude></code><br>
 | 
				
			||||||
@@ -1247,10 +1306,9 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <table>
 | 
					    <table>
 | 
				
			||||||
    <tr><td>API</td><td><code>DarkSkyAPI</code></td></tr>
 | 
					    <tr><td>API</td><td><code>DarkSkyAPI</code></td></tr>
 | 
				
			||||||
    <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code><br>Zeitdauer in
 | 
					    <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code><br>Zeitdauer in
 | 
				
			||||||
      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
					      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
				
			||||||
      sondern aus dem Cache zurück geliefert wird.<br><code>extend=hourly</code>
 | 
					      sondern aus dem Cache zurück geliefert wird.</td></tr>
 | 
				
			||||||
      <br>erweitert die Anzahl der Datensätze für die Stundenvorhersage auf 149</td></tr>
 | 
					 | 
				
			||||||
    <tr><td>location</td><td><code><latitude,longitude></code><br> Geographische Breite
 | 
					    <tr><td>location</td><td><code><latitude,longitude></code><br> Geographische Breite
 | 
				
			||||||
      und Länge des Ortes in Grad, für den das Wetter vorhergesagt wird.
 | 
					      und Länge des Ortes in Grad, für den das Wetter vorhergesagt wird.
 | 
				
			||||||
      Bei fehlender Angabe werden die Werte aus den gleichnamigen Attributen
 | 
					      Bei fehlender Angabe werden die Werte aus den gleichnamigen Attributen
 | 
				
			||||||
@@ -1262,7 +1320,7 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <table>
 | 
					    <table>
 | 
				
			||||||
    <tr><td>API</td><td><code>OpenWeatherMapAPI</code></td></tr>
 | 
					    <tr><td>API</td><td><code>OpenWeatherMapAPI</code></td></tr>
 | 
				
			||||||
    <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code> Zeitdauer in
 | 
					    <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code> Zeitdauer in
 | 
				
			||||||
      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
					      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
				
			||||||
      sondern aus dem Cache zurück geliefert wird.</td></tr>
 | 
					      sondern aus dem Cache zurück geliefert wird.</td></tr>
 | 
				
			||||||
    <tr><td>location</td><td><code><latitude,longitude></code> Geographische Breite
 | 
					    <tr><td>location</td><td><code><latitude,longitude></code> Geographische Breite
 | 
				
			||||||
@@ -1276,7 +1334,7 @@ sub WeatherCheckOptions($@) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <table>
 | 
					    <table>
 | 
				
			||||||
    <tr><td>API</td><td><code>wundergroundAPI</code></td></tr>
 | 
					    <tr><td>API</td><td><code>wundergroundAPI</code></td></tr>
 | 
				
			||||||
    <tr><td>apioptions</td><td><code>cachemaxage=<cachemaxage></code> Zeitdauer in
 | 
					    <tr><td>apioptions</td><td><code>cachemaxage:<cachemaxage></code> Zeitdauer in
 | 
				
			||||||
      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
					      Sekunden, innerhalb derer die Wettervorhersage nicht neu abgerufen
 | 
				
			||||||
      sondern aus dem Cache zurück geliefert wird.<br><code>stationId:ID-Num</code>
 | 
					      sondern aus dem Cache zurück geliefert wird.<br><code>stationId:ID-Num</code>
 | 
				
			||||||
      <br>die ID der Station von welcher die Daten gelesen werden sollen.</td></tr>
 | 
					      <br>die ID der Station von welcher die Daten gelesen werden sollen.</td></tr>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,6 +157,8 @@ sub new {
 | 
				
			|||||||
        lat       => ( split( ',', $argsRef->{location} ) )[0],
 | 
					        lat       => ( split( ',', $argsRef->{location} ) )[0],
 | 
				
			||||||
        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
					        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
				
			||||||
        fetchTime => 0,
 | 
					        fetchTime => 0,
 | 
				
			||||||
 | 
					        forecast  => $argsRef->{forecast},
 | 
				
			||||||
 | 
					        alerts    => $argsRef->{alerts},
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{cachemaxage} = (
 | 
					    $self->{cachemaxage} = (
 | 
				
			||||||
@@ -189,6 +191,22 @@ sub parseApiOptions($) {
 | 
				
			|||||||
    return \%h;
 | 
					    return \%h;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setAlerts {
 | 
				
			||||||
 | 
					    my $self        = shift;
 | 
				
			||||||
 | 
					    my $alerts      = shift // 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{alerts} = $alerts;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setForecast {
 | 
				
			||||||
 | 
					    my $self            = shift;
 | 
				
			||||||
 | 
					    my $forecast         = shift // '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{forecast}    = $forecast;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub setFetchTime {
 | 
					sub setFetchTime {
 | 
				
			||||||
    my $self = shift;
 | 
					    my $self = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,8 @@ eval { use Readonly; 1 }
 | 
				
			|||||||
  or $missingModul .= 'Readonly ';    # apt install libreadonly-perl
 | 
					  or $missingModul .= 'Readonly ';    # apt install libreadonly-perl
 | 
				
			||||||
## use critic
 | 
					## use critic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Readonly my $URL => 'https://api.openweathermap.org/data/2.5/';
 | 
					# Readonly my $URL => 'https://api.openweathermap.org/data/2.5/';
 | 
				
			||||||
 | 
					Readonly my $URL => 'https://api.openweathermap.org/data/';
 | 
				
			||||||
## URL . 'weather?' for current data
 | 
					## URL . 'weather?' for current data
 | 
				
			||||||
## URL . 'onecall?' for forecast data
 | 
					## URL . 'onecall?' for forecast data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -180,7 +181,7 @@ my %codes = (
 | 
				
			|||||||
sub new {
 | 
					sub new {
 | 
				
			||||||
    ### geliefert wird ein Hash
 | 
					    ### geliefert wird ein Hash
 | 
				
			||||||
    my ( $class, $argsRef ) = @_;
 | 
					    my ( $class, $argsRef ) = @_;
 | 
				
			||||||
    my $apioptions = parseApiOptions( $argsRef->{apioptions} );
 | 
					    my $apioptions = _parseApiOptions( $argsRef->{apioptions} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $self = {
 | 
					    my $self = {
 | 
				
			||||||
        devName => $argsRef->{devName},
 | 
					        devName => $argsRef->{devName},
 | 
				
			||||||
@@ -194,7 +195,8 @@ sub new {
 | 
				
			|||||||
        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
					        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
				
			||||||
        fetchTime => 0,
 | 
					        fetchTime => 0,
 | 
				
			||||||
        endpoint  => 'none',
 | 
					        endpoint  => 'none',
 | 
				
			||||||
        exclude   => $argsRef->{exclude},
 | 
					        forecast  => $argsRef->{forecast},
 | 
				
			||||||
 | 
					        alerts    => $argsRef->{alerts},
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{cachemaxage} = (
 | 
					    $self->{cachemaxage} = (
 | 
				
			||||||
@@ -203,13 +205,15 @@ sub new {
 | 
				
			|||||||
        : 900
 | 
					        : 900
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{cached} = _CreateForecastRef($self);
 | 
					    $self->{apiversion} = ($apioptions->{version} ? $apioptions->{version} : '2.5');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{cached}     = _CreateForecastRef($self);
 | 
				
			||||||
     
 | 
					     
 | 
				
			||||||
    bless $self, $class;
 | 
					    bless $self, $class;
 | 
				
			||||||
    return $self;
 | 
					    return $self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub parseApiOptions {
 | 
					sub _parseApiOptions {
 | 
				
			||||||
    my $apioptions = shift;
 | 
					    my $apioptions = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my @params;
 | 
					    my @params;
 | 
				
			||||||
@@ -226,27 +230,45 @@ sub parseApiOptions {
 | 
				
			|||||||
    return \%h;
 | 
					    return \%h;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setAlerts {
 | 
				
			||||||
 | 
					    my $self        = shift;
 | 
				
			||||||
 | 
					    my $alerts      = shift // 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{alerts} = $alerts;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setForecast {
 | 
				
			||||||
 | 
					    my $self            = shift;
 | 
				
			||||||
 | 
					    my $forecast         = shift // '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{forecast}    = $forecast;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub setFetchTime {
 | 
					sub setFetchTime {
 | 
				
			||||||
    my $self = shift;
 | 
					    my $self = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{fetchTime} = time();
 | 
					    $self->{fetchTime} = time();
 | 
				
			||||||
    return 0;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub setRetrieveData {
 | 
					sub setRetrieveData {
 | 
				
			||||||
    my $self = shift;
 | 
					    my $self = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _RetrieveDataFromOpenWeatherMap($self);
 | 
					    _RetrieveDataFromOpenWeatherMap($self);
 | 
				
			||||||
    return 0;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub setLocation {
 | 
					sub setLocation {
 | 
				
			||||||
    my ( $self, $lat, $long ) = @_;
 | 
					    my $self    = shift;
 | 
				
			||||||
 | 
					    my $lat     = shift;
 | 
				
			||||||
 | 
					    my $long    = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{lat}  = $lat;
 | 
					    $self->{lat}  = $lat;
 | 
				
			||||||
    $self->{long} = $long;
 | 
					    $self->{long} = $long;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub getFetchTime {
 | 
					sub getFetchTime {
 | 
				
			||||||
@@ -312,13 +334,15 @@ sub _RetrieveDataFromOpenWeatherMap {
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
        $paramRef->{url} =
 | 
					        $paramRef->{url} =
 | 
				
			||||||
            $URL
 | 
					            $URL
 | 
				
			||||||
 | 
					          . $self->{apiversion} . '/'
 | 
				
			||||||
          . $paramRef->{endpoint} . '?' . 'lat='
 | 
					          . $paramRef->{endpoint} . '?' . 'lat='
 | 
				
			||||||
          . $self->{lat} . '&' . 'lon='
 | 
					          . $self->{lat} . '&' . 'lon='
 | 
				
			||||||
          . $self->{long} . '&'
 | 
					          . $self->{long} . '&'
 | 
				
			||||||
          . 'APPID='
 | 
					          . 'APPID='
 | 
				
			||||||
          . $self->{key} . '&' . 'lang='
 | 
					          . $self->{key} . '&' . 'units='
 | 
				
			||||||
 | 
					          . 'metric' . '&' . 'lang='
 | 
				
			||||||
          . $self->{lang} . '&' . 'exclude='
 | 
					          . $self->{lang} . '&' . 'exclude='
 | 
				
			||||||
          . $self->{exclude};
 | 
					          . _createExcludeString($self->{forecast},$self->{alerts});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ::HttpUtils_NonblockingGet($paramRef);
 | 
					        ::HttpUtils_NonblockingGet($paramRef);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -326,6 +350,20 @@ sub _RetrieveDataFromOpenWeatherMap {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _createExcludeString {
 | 
				
			||||||
 | 
					    my $forecast     = shift;
 | 
				
			||||||
 | 
					    my $alerts      = shift;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    my @exclude     = qw/alerts minutely hourly daily/;
 | 
				
			||||||
 | 
					    my @forecast    = split(',',$forecast);
 | 
				
			||||||
 | 
					    my @alerts      = ( $alerts ? ',alerts' : '' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my %in_forecast = map {$_ => 1} @forecast,@alerts;
 | 
				
			||||||
 | 
					    my @diff        = grep {not $in_forecast{$_}} @exclude;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return join(',',@alerts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub _RetrieveDataFinished {
 | 
					sub _RetrieveDataFinished {
 | 
				
			||||||
    my $paramRef = shift;
 | 
					    my $paramRef = shift;
 | 
				
			||||||
    my $err      = shift;
 | 
					    my $err      = shift;
 | 
				
			||||||
@@ -387,36 +425,31 @@ sub _ProcessingRetrieveData {
 | 
				
			|||||||
                        $self->{cached}->{current}       = {
 | 
					                        $self->{cached}->{current}       = {
 | 
				
			||||||
                            'temperature' => int(
 | 
					                            'temperature' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp} - 273.15 ) ) + 0.5
 | 
					                                    $data->{main}->{temp}) + 0.5
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'temp_c' => int(
 | 
					                            'temp_c' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp} - 273.15 ) ) + 0.5
 | 
					                                    $data->{main}->{temp}) + 0.5
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'low_c' => int(
 | 
					                            'low_c' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp_min} - 273.15 ) ) +
 | 
					                                    $data->{main}->{temp_min}) + 0.5
 | 
				
			||||||
                                  0.5
 | 
					 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'high_c' => int(
 | 
					                            'high_c' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp_max} - 273.15 ) ) +
 | 
					                                    $data->{main}->{temp_max}) + 0.5
 | 
				
			||||||
                                  0.5
 | 
					 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'tempLow' => int(
 | 
					                            'tempLow' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp_min} - 273.15 ) ) +
 | 
					                                    $data->{main}->{temp_min}) + 0.5
 | 
				
			||||||
                                  0.5
 | 
					 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'tempHigh' => int(
 | 
					                            'tempHigh' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{temp_max} - 273.15 ) ) +
 | 
					                                    $data->{main}->{temp_max}) + 0.5
 | 
				
			||||||
                                  0.5
 | 
					 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'tempFeelsLike_c' => int(
 | 
					                            'tempFeelsLike_c' => int(
 | 
				
			||||||
                                sprintf( "%.1f",
 | 
					                                sprintf( "%.1f",
 | 
				
			||||||
                                    ( $data->{main}->{feels_like} - 273.15 ) )
 | 
					                                    $data->{main}->{feels_like}) + 0.5
 | 
				
			||||||
                                  + 0.5
 | 
					 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            'humidity'  => $data->{main}->{humidity},
 | 
					                            'humidity'  => $data->{main}->{humidity},
 | 
				
			||||||
                            'condition' => encode_utf8(
 | 
					                            'condition' => encode_utf8(
 | 
				
			||||||
@@ -493,7 +526,7 @@ sub _ProcessingRetrieveData {
 | 
				
			|||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                (
 | 
				
			||||||
                                                    $data->{hourly}->[$i]
 | 
					                                                    $data->{hourly}->[$i]
 | 
				
			||||||
                                                      ->{temp} - 273.15
 | 
					                                                      ->{temp}
 | 
				
			||||||
                                                )
 | 
					                                                )
 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
@@ -502,7 +535,7 @@ sub _ProcessingRetrieveData {
 | 
				
			|||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                (
 | 
				
			||||||
                                                    $data->{hourly}->[$i]
 | 
					                                                    $data->{hourly}->[$i]
 | 
				
			||||||
                                                      ->{temp} - 273.15
 | 
					                                                      ->{temp}
 | 
				
			||||||
                                                )
 | 
					                                                )
 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
@@ -627,126 +660,85 @@ sub _ProcessingRetrieveData {
 | 
				
			|||||||
                                        'temperature' => int(
 | 
					                                        'temperature' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{day}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{day} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'temperature_morn' => int(
 | 
					                                        'temperature_morn' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{morn}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{morn} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'temperature_eve' => int(
 | 
					                                        'temperature_eve' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{eve}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{eve} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'temperature_night' => int(
 | 
					                                        'temperature_night' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{night}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{night} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempFeelsLike_morn' => int(
 | 
					                                        'tempFeelsLike_morn' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{feels_like}->{morn}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{feels_like}->{morn} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempFeelsLike_eve' => int(
 | 
					                                        'tempFeelsLike_eve' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{feels_like}->{eve}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{feels_like}->{eve} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempFeelsLike_night' => int(
 | 
					                                        'tempFeelsLike_night' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{feels_like}->{night}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{feels_like}->{night} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempFeelsLike_day' => int(
 | 
					                                        'tempFeelsLike_day' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{feels_like}->{day}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{feels_like}->{day} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'temp_c' => int(
 | 
					                                        'temp_c' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{day}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{day} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'low_c' => int(
 | 
					                                        'low_c' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{min}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{min} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'high_c' => int(
 | 
					                                        'high_c' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{max}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{max} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempLow' => int(
 | 
					                                        'tempLow' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{min}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{min} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'tempHigh' => int(
 | 
					                                        'tempHigh' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{temp}->{max}
 | 
				
			||||||
                                                    $data->{daily}->[$i]
 | 
					 | 
				
			||||||
                                                      ->{temp}->{max} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'dew_point' => int(
 | 
					                                        'dew_point' => int(
 | 
				
			||||||
                                            sprintf(
 | 
					                                            sprintf(
 | 
				
			||||||
                                                "%.1f",
 | 
					                                                "%.1f",
 | 
				
			||||||
                                                (
 | 
					                                                $data->{daily}->[$i]->{dew_point}
 | 
				
			||||||
                                                    $data->{daily}->[$i]->{dew_point} - 273.15
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            ) + 0.5
 | 
					                                            ) + 0.5
 | 
				
			||||||
                                        ),
 | 
					                                        ),
 | 
				
			||||||
                                        'humidity' =>
 | 
					                                        'humidity' =>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,6 +109,8 @@ sub new {
 | 
				
			|||||||
        lat       => ( split( ',', $argsRef->{location} ) )[0],
 | 
					        lat       => ( split( ',', $argsRef->{location} ) )[0],
 | 
				
			||||||
        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
					        long      => ( split( ',', $argsRef->{location} ) )[1],
 | 
				
			||||||
        fetchTime => 0,
 | 
					        fetchTime => 0,
 | 
				
			||||||
 | 
					        forecast  => $argsRef->{forecast},
 | 
				
			||||||
 | 
					        alerts    => $argsRef->{alerts},
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $self->{cachemaxage} = (
 | 
					    $self->{cachemaxage} = (
 | 
				
			||||||
@@ -181,6 +183,22 @@ sub setLocation {
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setAlerts {
 | 
				
			||||||
 | 
					    my $self        = shift;
 | 
				
			||||||
 | 
					    my $alerts      = shift // 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{alerts} = $alerts;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setForecast {
 | 
				
			||||||
 | 
					    my $self            = shift;
 | 
				
			||||||
 | 
					    my $forecast         = shift // '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $self->{forecast}    = $forecast;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub getFetchTime {
 | 
					sub getFetchTime {
 | 
				
			||||||
    my $self = shift;
 | 
					    my $self = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user