testing #29
404
59_Weather.pm
404
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,40 +208,46 @@ my @iconlist = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
sub Weather_LanguageInitialize($) {
|
sub Weather_LanguageInitialize {
|
||||||
my ($lang) = @_;
|
my $lang = shift;
|
||||||
|
|
||||||
if ( $lang eq "de" ) {
|
given ($lang) {
|
||||||
|
when ('de') {
|
||||||
%wdays_txt_i18n = %wdays_txt_de;
|
%wdays_txt_i18n = %wdays_txt_de;
|
||||||
@directions_txt_i18n = @directions_txt_de;
|
@directions_txt_i18n = @directions_txt_de;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_de;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_de;
|
||||||
%status_items_txt_i18n = %status_items_txt_de;
|
%status_items_txt_i18n = %status_items_txt_de;
|
||||||
}
|
}
|
||||||
elsif ( $lang eq "nl" ) {
|
|
||||||
|
when ('nl') {
|
||||||
%wdays_txt_i18n = %wdays_txt_nl;
|
%wdays_txt_i18n = %wdays_txt_nl;
|
||||||
@directions_txt_i18n = @directions_txt_nl;
|
@directions_txt_i18n = @directions_txt_nl;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_nl;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_nl;
|
||||||
%status_items_txt_i18n = %status_items_txt_nl;
|
%status_items_txt_i18n = %status_items_txt_nl;
|
||||||
}
|
}
|
||||||
elsif ( $lang eq "fr" ) {
|
|
||||||
|
when ('fr') {
|
||||||
%wdays_txt_i18n = %wdays_txt_fr;
|
%wdays_txt_i18n = %wdays_txt_fr;
|
||||||
@directions_txt_i18n = @directions_txt_fr;
|
@directions_txt_i18n = @directions_txt_fr;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_fr;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_fr;
|
||||||
%status_items_txt_i18n = %status_items_txt_fr;
|
%status_items_txt_i18n = %status_items_txt_fr;
|
||||||
}
|
}
|
||||||
elsif ( $lang eq "pl" ) {
|
|
||||||
|
when ('pl') {
|
||||||
%wdays_txt_i18n = %wdays_txt_pl;
|
%wdays_txt_i18n = %wdays_txt_pl;
|
||||||
@directions_txt_i18n = @directions_txt_pl;
|
@directions_txt_i18n = @directions_txt_pl;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_pl;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_pl;
|
||||||
%status_items_txt_i18n = %status_items_txt_pl;
|
%status_items_txt_i18n = %status_items_txt_pl;
|
||||||
}
|
}
|
||||||
elsif ( $lang eq "it" ) {
|
|
||||||
|
when ('it') {
|
||||||
%wdays_txt_i18n = %wdays_txt_it;
|
%wdays_txt_i18n = %wdays_txt_it;
|
||||||
@directions_txt_i18n = @directions_txt_it;
|
@directions_txt_i18n = @directions_txt_it;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_it;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_it;
|
||||||
%status_items_txt_i18n = %status_items_txt_it;
|
%status_items_txt_i18n = %status_items_txt_it;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
default {
|
||||||
%wdays_txt_i18n = %wdays_txt_en;
|
%wdays_txt_i18n = %wdays_txt_en;
|
||||||
@directions_txt_i18n = @directions_txt_en;
|
@directions_txt_i18n = @directions_txt_en;
|
||||||
%pressure_trend_txt_i18n = %pressure_trend_txt_en;
|
%pressure_trend_txt_i18n = %pressure_trend_txt_en;
|
||||||
@ -246,9 +255,13 @@ sub Weather_LanguageInitialize($) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->{AttrFn} = \&Weather_Attr;
|
||||||
$hash->{AttrList} =
|
$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 );
|
||||||
@ -354,30 +378,30 @@ sub Weather_WriteReadings($$) {
|
|||||||
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 . ' '
|
||||||
@ -388,14 +412,14 @@ 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;
|
||||||
@ -407,7 +431,7 @@ 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,
|
||||||
@ -419,17 +443,17 @@ sub Weather_WriteReadings($$) {
|
|||||||
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;
|
||||||
@ -462,7 +486,7 @@ 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,
|
||||||
@ -474,16 +498,16 @@ sub Weather_WriteReadings($$) {
|
|||||||
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 $name = shift @$aRef // return;
|
||||||
my @forecast = split(',',AttrVal($name,'forcast','') . (AttrVal($name,'alerts',0) ? ',alerts' : ''));
|
my $reading = shift @$aRef // return;
|
||||||
my %exclude =();
|
|
||||||
|
|
||||||
@exclude{@exclude} = @exclude;
|
|
||||||
delete @exclude{@forecast};
|
|
||||||
|
|
||||||
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 $dev = shift;
|
||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $type = $hash->{TYPE};
|
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 $width = int( $ICONSCALE * $ICONWIDTH );
|
||||||
my $url = FW_IconURL("weather/$icon");
|
my $url = FW_IconURL("weather/$icon");
|
||||||
my $style = " width=$width";
|
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->{apiversion} = ($apioptions->{version} ? $apioptions->{version} : '2.5');
|
||||||
|
|
||||||
$self->{cached} = _CreateForecastRef($self);
|
$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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user