Merge branch 'master' into devel

This commit is contained in:
Marko Oldenburg
2019-06-04 21:21:30 +02:00
3 changed files with 122 additions and 83 deletions

View File

@ -92,13 +92,13 @@ my %wdays_txt_de = (
'Sun' => 'So' 'Sun' => 'So'
); );
my %wdays_txt_nl = ( my %wdays_txt_nl = (
'Mon' => 'Maa', 'Mon' => 'Ma',
'Tue' => 'Din', 'Tue' => 'Di',
'Wed' => 'Woe', 'Wed' => 'Wo',
'Thu' => 'Don', 'Thu' => 'Do',
'Fri' => 'Vri', 'Fri' => 'Vr',
'Sat' => 'Zat', 'Sat' => 'Za',
'Sun' => 'Zon' 'Sun' => 'Zo'
); );
my %wdays_txt_fr = ( my %wdays_txt_fr = (
'Mon' => 'Lun', 'Mon' => 'Lun',
@ -146,7 +146,7 @@ my %status_items_txt_nl = (
0 => "Wind", 0 => "Wind",
1 => "Vochtigheid", 1 => "Vochtigheid",
2 => "Temperatuur", 2 => "Temperatuur",
3 => "Direct", 3 => "Actueel",
4 => "Weersvoorspelling voor " 4 => "Weersvoorspelling voor "
); );
my %status_items_txt_fr = ( my %status_items_txt_fr = (
@ -608,8 +608,8 @@ sub Weather_Notify($$) {
Weather_RearmTimer( $hash, gettimeofday() + $delay ); Weather_RearmTimer( $hash, gettimeofday() + $delay );
### 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} ) and lc( $hash->{APIKEY} ) eq 'demo' );
return undef; return undef;
} }
@ -646,18 +646,20 @@ sub Weather_Define($$) {
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->{LOCATION} = $hash->{LOCATION} = (
( ( defined($location) and $location ) ( defined($location) and $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) and $lang )
? $lang ? $lang
: lc( AttrVal( 'global', 'language', 'de' ) ) ); : lc( AttrVal( 'global', 'language', 'de' ) )
);
$hash->{API} = $api; $hash->{API} = $api;
$hash->{MODEL} = $api; $hash->{MODEL} = $api;
$hash->{APIKEY} = $apikey; $hash->{APIKEY} = $apikey;
@ -716,7 +718,7 @@ sub WeatherIconIMGTag($) {
sub WeatherAsHtmlV($;$$) { sub WeatherAsHtmlV($;$$) {
my ( $d, $op1, $op2 ) = @_; my ( $d, $op1, $op2 ) = @_;
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 );
@ -751,26 +753,29 @@ sub WeatherAsHtmlV($;$$) {
); );
for ( my $i = 1 ; $i < $items ; $i++ ) { for ( my $i = 1 ; $i < $items ; $i++ ) {
if(defined($h->{READINGS}->{"${fc}${i}_low_c"}) and $h->{READINGS}->{"${fc}${i}_low_c"}){ if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
and $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>',
$width, $width,
WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ), WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ),
ReadingsVal( $d, "${fc}${i}_day_of_week", "" ), ReadingsVal( $d, "${fc}${i}_day_of_week", "" ),
ReadingsVal( $d, "${fc}${i}_condition", "" ), ReadingsVal( $d, "${fc}${i}_condition", "" ),
ReadingsVal( $d, "${fc}${i}_low_c", " - " ), ReadingsVal( $d, "${fc}${i}_low_c", " - " ),
ReadingsVal( $d, "${fc}${i}_high_c", " - " ), ReadingsVal( $d, "${fc}${i}_high_c", " - " ),
ReadingsVal( $d, "${fc}${i}_wind_condition", " - " ) ReadingsVal( $d, "${fc}${i}_wind_condition", " - " )
); );
}else{ }
else {
$ret .= sprintf( $ret .= sprintf(
'<tr><td class="weatherIcon" width=%d>%s</td><td class="weatherValue"><span class="weatherDay">%s: %s</span><br><span class="weatherTemp"> %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="weatherTemp"> %s°C</span><br>%s</td></tr>',
$width, $width,
WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ), WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ),
ReadingsVal( $d, "${fc}${i}_day_of_week", "" ), ReadingsVal( $d, "${fc}${i}_day_of_week", "" ),
ReadingsVal( $d, "${fc}${i}_condition", "" ), ReadingsVal( $d, "${fc}${i}_condition", "" ),
ReadingsVal( $d, "${fc}${i}_temperature", " - " ), ReadingsVal( $d, "${fc}${i}_temperature", " - " ),
ReadingsVal( $d, "${fc}${i}_wind_condition", " - " ) ReadingsVal( $d, "${fc}${i}_wind_condition", " - " )
); );
} }
} }
@ -782,7 +787,7 @@ sub WeatherAsHtmlV($;$$) {
sub WeatherAsHtml($;$$) { sub WeatherAsHtml($;$$) {
my ( $d, $op1, $op2 ) = @_; my ( $d, $op1, $op2 ) = @_;
my ($f,$items) = WeatherCheckOptions($d,$op1,$op2); my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
WeatherAsHtmlV( $d, $f, $items ); WeatherAsHtmlV( $d, $f, $items );
} }
@ -790,7 +795,7 @@ sub WeatherAsHtml($;$$) {
sub WeatherAsHtmlH($;$$) { sub WeatherAsHtmlH($;$$) {
my ( $d, $op1, $op2 ) = @_; my ( $d, $op1, $op2 ) = @_;
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 );
@ -846,13 +851,15 @@ sub WeatherAsHtmlH($;$$) {
ReadingsVal( $d, "humidity", "" ) ReadingsVal( $d, "humidity", "" )
); );
for ( my $i = 1 ; $i < $items ; $i++ ) { for ( my $i = 1 ; $i < $items ; $i++ ) {
if(defined($h->{READINGS}->{"${fc}${i}_low_c"}) and $h->{READINGS}->{"${fc}${i}_low_c"}){ if ( defined( $h->{READINGS}->{"${fc}${i}_low_c"} )
and $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", " - " ) );
} }
else { else {
$ret .= sprintf( '<td class="weatherMin"> %s°C</td>', $ret .= sprintf( '<td class="weatherMin"> %s°C</td>',
ReadingsVal( $d, "${fc}${i}_temperature", " - " ) ); ReadingsVal( $d, "${fc}${i}_temperature", " - " ) );
} }
} }
@ -862,9 +869,11 @@ sub WeatherAsHtmlH($;$$) {
$ret .= sprintf( '<tr><td class="weatherMax">%s</td>', $ret .= sprintf( '<tr><td class="weatherMax">%s</td>',
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"}) and $h->{READINGS}->{"${fc}${i}_high_c"}){ if ( defined( $h->{READINGS}->{"${fc}${i}_high_c"} )
and $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", " - " ) );
} }
} }
@ -876,40 +885,43 @@ sub WeatherAsHtmlH($;$$) {
sub WeatherAsHtmlD($;$$) { sub WeatherAsHtmlD($;$$) {
my ( $d, $op1, $op2 ) = @_; my ( $d, $op1, $op2 ) = @_;
my ($f,$items) = WeatherCheckOptions($d,$op1,$op2); my ( $f, $items ) = WeatherCheckOptions( $d, $op1, $op2 );
if ($FW_ss) { if ($FW_ss) {
WeatherAsHtmlV( $d, $f , $items); WeatherAsHtmlV( $d, $f, $items );
} }
else { else {
WeatherAsHtmlH( $d, $f , $items); WeatherAsHtmlH( $d, $f, $items );
} }
} }
sub WeatherCheckOptions($@) { sub WeatherCheckOptions($@) {
my ($d,$op1,$op2) = @_; my ( $d, $op1, $op2 ) = @_;
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) and $op1 and $op1 =~ /[0-9]/g ) { $items = $op1; }
if( defined($op2) and $op2 and $op2 =~ /[dh]/g){ $f = $op2; } if ( defined($op2) and $op2 and $op2 =~ /[dh]/g ) { $f = $op2; }
$f =~ tr/dh/./cd if ( defined $f and $f ); $f =~ tr/dh/./cd if ( defined $f and $f );
$items =~ tr/0-9/./cd if (defined($items) and $items ); $items =~ tr/0-9/./cd if ( defined($items) and $items );
$items = 6 if ( !$items ); $items = 6 if ( !$items );
return "$d is not a Weather instance<br>" return "$d is not a Weather instance<br>"
if ( !$defs{$d} || $defs{$d}->{TYPE} ne "Weather" ); if ( !$defs{$d} || $defs{$d}->{TYPE} ne "Weather" );
if ( AttrVal($d,'forecast','none') ne 'none' ) { if ( AttrVal( $d, 'forecast', 'none' ) ne 'none' ) {
$f = ( AttrVal($d,'forecast','none') eq 'daily' ? 'd' : 'h' ); $f =
( AttrVal( $d, 'forecast', 'none' ) eq 'daily'
? 'd'
: ( AttrVal( $d, 'forecast', 'none' ) eq 'every' ? $f : 'h' ) );
} }
$f = 'h' if ( !$f || length($f) > 1); $f = 'h' if ( !$f || length($f) > 1 );
return ($f,$items); return ( $f, $items );
} }
##################################### #####################################
@ -977,7 +989,8 @@ sub WeatherCheckOptions($@) {
<table border="1"> <table border="1">
<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=&lt;cachemaxage&gt;</code><br>duration <tr><td>apioptions</td><td><code>cachemaxage=&lt;cachemaxage&gt;</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<br><code>extend=hourly</code>
<br>extends the number of hours forecast records to 149</td></tr>
<tr><td>location</td><td><code>&lt;latitude,longitude&gt;</code><br> <tr><td>location</td><td><code>&lt;latitude,longitude&gt;</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
@ -1144,7 +1157,8 @@ sub WeatherCheckOptions($@) {
<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=&lt;cachemaxage&gt;</code><br>Zeitdauer in <tr><td>apioptions</td><td><code>cachemaxage=&lt;cachemaxage&gt;</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&uuml;ck geliefert wird.</td></tr> sondern aus dem Cache zur&uuml;ck geliefert wird.<br><code>extend=hourly</code>
<br>erweitert die Anzahl der Datens&auml;tze f&uuml;r die Stundenvorhersage auf 149</td></tr>
<tr><td>location</td><td><code>&lt;latitude,longitude&gt;</code><br> Geographische Breite <tr><td>location</td><td><code>&lt;latitude,longitude&gt;</code><br> Geographische Breite
und L&auml;nge des Ortes in Grad, f&uuml;r den das Wetter vorhergesagt wird. und L&auml;nge des Ortes in Grad, f&uuml;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

View File

@ -48,7 +48,7 @@ use constant DEMODATA => '{"latitude":50.112,"longitude":8.686,"timezone":"Europ
use constant URL => 'https://api.darksky.net/forecast/'; use constant URL => 'https://api.darksky.net/forecast/';
use constant VERSION => '0.2.7'; use constant VERSION => '0.2.9';
my %codes = ( my %codes = (
'clear-day' => 32, 'clear-day' => 32,
@ -69,6 +69,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 $self = { my $self = {
devName => $argsRef->{devName}, devName => $argsRef->{devName},
@ -77,27 +78,38 @@ sub new {
? $argsRef->{apikey} ? $argsRef->{apikey}
: 'none' : 'none'
), ),
cachemaxage => (
( defined( $argsRef->{apioptions} ) and $argsRef->{apioptions} )
? (
( split( ':', $argsRef->{apioptions} ) )[0] eq 'cachemaxage'
? ( split( ':', $argsRef->{apioptions} ) )[1]
: 900
)
: 900
),
lang => $argsRef->{language}, lang => $argsRef->{language},
lat => ( split( ',', $argsRef->{location} ) )[0], lat => ( split( ',', $argsRef->{location} ) )[0],
long => ( split( ',', $argsRef->{location} ) )[1], long => ( split( ',', $argsRef->{location} ) )[1],
fetchTime => 0, fetchTime => 0,
}; };
$self->{cachemaxage} = ( defined($apioptions->{cachemaxage}) ? $apioptions->{cachemaxage} : 900 );
$self->{extend} = ( defined($apioptions->{extend}) ? $apioptions->{extend} : 'none' );
$self->{cached} = _CreateForecastRef($self); $self->{cached} = _CreateForecastRef($self);
bless $self, $class; bless $self, $class;
return $self; return $self;
} }
sub parseApiOptions($) {
my $apioptions = shift;
my @params;
my %h;
@params = split(',',$apioptions);
while (@params) {
my $param = shift(@params);
next if($param eq '');
my ($key, $value) = split(':', $param, 2 );
$h{$key} = $value;
}
return \%h;
}
sub setFetchTime { sub setFetchTime {
my $self = shift; my $self = shift;
@ -159,6 +171,9 @@ sub _RetrieveDataFromDarkSky($) {
if ($missingModul); if ($missingModul);
} }
else { else {
my $options = '&units=auto';
$options .= '&extend=' . $self->{extend} if ( $self->{extend} ne 'none' );
$paramRef->{url} = $paramRef->{url} =
URL URL
. $self->{key} . '/' . $self->{key} . '/'
@ -166,7 +181,7 @@ sub _RetrieveDataFromDarkSky($) {
. $self->{long} . $self->{long}
. '?lang=' . '?lang='
. $self->{lang} . $self->{lang}
. '&units=auto&extend=hourly'; . $options;
if ( lc($self->{key}) eq 'demo' ) if ( lc($self->{key}) eq 'demo' )
{ _RetrieveDataFinished($paramRef,undef,DEMODATA); } { _RetrieveDataFinished($paramRef,undef,DEMODATA); }

View File

@ -48,7 +48,7 @@ eval "use Encode qw(encode_utf8);1" or $missingModul .= "Encode ";
# use Data::Dumper; # for Debug only # use Data::Dumper; # for Debug only
## API URL ## API URL
use constant URL => 'https://api.openweathermap.org/data/2.5/'; use constant URL => 'https://api.openweathermap.org/data/2.5/';
use constant VERSION => '0.2.4'; use constant VERSION => '0.2.5';
## URL . 'weather?' for current data ## URL . 'weather?' for current data
## URL . 'forecast?' for forecast data ## URL . 'forecast?' for forecast data
@ -112,6 +112,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 $self = { my $self = {
devName => $argsRef->{devName}, devName => $argsRef->{devName},
@ -120,15 +121,6 @@ sub new {
? $argsRef->{apikey} ? $argsRef->{apikey}
: 'none' : 'none'
), ),
cachemaxage => (
( defined( $argsRef->{apioptions} ) and $argsRef->{apioptions} )
? (
( split( ':', $argsRef->{apioptions} ) )[0] eq 'cachemaxage'
? ( split( ':', $argsRef->{apioptions} ) )[1]
: 900
)
: 900
),
lang => $argsRef->{language}, lang => $argsRef->{language},
lat => ( split( ',', $argsRef->{location} ) )[0], lat => ( split( ',', $argsRef->{location} ) )[0],
long => ( split( ',', $argsRef->{location} ) )[1], long => ( split( ',', $argsRef->{location} ) )[1],
@ -136,12 +128,30 @@ sub new {
endpoint => 'none', endpoint => 'none',
}; };
$self->{cachemaxage} = ( defined($apioptions->{cachemaxage}) ? $apioptions->{cachemaxage} : 900 );
$self->{cached} = _CreateForecastRef($self); $self->{cached} = _CreateForecastRef($self);
bless $self, $class; bless $self, $class;
return $self; return $self;
} }
sub parseApiOptions($) {
my $apioptions = shift;
my @params;
my %h;
@params = split(',',$apioptions);
while (@params) {
my $param = shift(@params);
next if($param eq '');
my ($key, $value) = split(':', $param, 2 );
$h{$key} = $value;
}
return \%h;
}
sub setFetchTime { sub setFetchTime {
my $self = shift; my $self = shift;