new OpenWeatherMapAPI onecall v3 Support

This commit is contained in:
Marko Oldenburg 2022-11-20 21:10:22 +01:00
parent 714c95d6d0
commit ddefbac55a
3 changed files with 170 additions and 1592 deletions

View File

@ -269,8 +269,9 @@ sub Weather_Initialize($) {
$hash->{SetFn} = 'Weather_Set'; $hash->{SetFn} = 'Weather_Set';
$hash->{AttrList} = $hash->{AttrList} =
'disable:0,1 ' 'disable:0,1 '
. 'forecast:hourly,daily,every,off ' . 'forecast:multiple-strict,hourly,daily '
. 'forecastLimit ' . 'forecastLimit '
. 'alerts:0,1 '
. $readingFnAttributes; . $readingFnAttributes;
$hash->{NotifyFn} = 'Weather_Notify'; $hash->{NotifyFn} = 'Weather_Notify';
@ -329,6 +330,11 @@ sub Weather_RetrieveCallbackFn($) {
sub Weather_WriteReadings($$) { sub Weather_WriteReadings($$) {
my ( $hash, $dataRef ) = @_; my ( $hash, $dataRef ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $hourly = ( AttrVal( $name, 'forecast', '' ) =~ m{hourly}xms ? 1: 0 );
my $daily = ( AttrVal( $name, 'forecast', '' ) =~ m{daily}xms ? 1 : 0 );
my $alerts = ( AttrVal( $name, 'forecast', '' ) =~ m{alerts}xms ? 1 : 0 );
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
# delete some unused readings # delete some unused readings
@ -382,15 +388,14 @@ sub Weather_WriteReadings($$) {
### forecast ### forecast
if ( ref( $dataRef->{forecast} ) eq 'HASH' if ( ref( $dataRef->{forecast} ) eq 'HASH'
and AttrVal( $name, 'forecast', 'every' ) ne 'off' ) and ($hourly or $daily) )
{ {
## hourly ## hourly
if ( if (
defined( $dataRef->{forecast}->{hourly} ) defined( $dataRef->{forecast}->{hourly} )
and ref( $dataRef->{forecast}->{hourly} ) eq 'ARRAY' and ref( $dataRef->{forecast}->{hourly} ) eq 'ARRAY'
and scalar( @{ $dataRef->{forecast}->{hourly} } ) > 0 and scalar( @{ $dataRef->{forecast}->{hourly} } ) > 0
and ( AttrVal( $name, 'forecast', 'every' ) eq 'every' and $hourly
or AttrVal( $name, 'forecast', 'hourly' ) eq 'hourly' )
) )
{ {
my $i = 0; my $i = 0;
@ -445,8 +450,7 @@ sub Weather_WriteReadings($$) {
defined( $dataRef->{forecast}->{daily} ) defined( $dataRef->{forecast}->{daily} )
and ref( $dataRef->{forecast}->{daily} ) eq 'ARRAY' and ref( $dataRef->{forecast}->{daily} ) eq 'ARRAY'
and scalar( @{ $dataRef->{forecast}->{daily} } ) > 0 and scalar( @{ $dataRef->{forecast}->{daily} } ) > 0
and ( AttrVal( $name, 'forecast', 'every' ) eq 'every' and $daily
or AttrVal( $name, 'forecast', 'daily' ) eq 'daily' )
) )
{ {
my $i = 0; my $i = 0;
@ -496,6 +500,16 @@ sub Weather_WriteReadings($$) {
} }
} }
if ( ref( $dataRef->{alerts} ) eq 'HASH'
and $alerts )
{
while ( my ( $r, $v ) = each %{ $dataRef->{alerts} } ) {
readingsBulkUpdate( $hash, $r, $v )
if ( ref( $dataRef->{$r} ) ne 'HASH'
and ref( $dataRef->{$r} ) ne 'ARRAY' );
}
}
my $val = 'T: ' my $val = 'T: '
. $dataRef->{current}->{temperature} . ' °C' . ' ' . $dataRef->{current}->{temperature} . ' °C' . ' '
. substr( $status_items_txt_i18n{1}, 0, 1 ) . ': ' . substr( $status_items_txt_i18n{1}, 0, 1 ) . ': '
@ -529,7 +543,7 @@ sub Weather_GetUpdate($) {
Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} ); Weather_RearmTimer( $hash, gettimeofday() + $hash->{INTERVAL} );
} }
else { else {
# Weather_RetrieveData($name, 0); $hash->{fhem}->{api}->{exclude} = Weather_parseForcastAttr($hash);
$hash->{fhem}->{api}->setRetrieveData; $hash->{fhem}->{api}->setRetrieveData;
} }
@ -537,6 +551,20 @@ sub Weather_GetUpdate($) {
} }
################################### ###################################
sub Weather_parseForcastAttr {
my $hash = shift;
my $name = $hash->{NAME};
my @exclude = qw 'alerts minutely hourly daily';
my @forecast = split(',',AttrVal($name,'forcast','') . (AttrVal($name,'alerts',0) ? ',alerts' : ''));
my %exclude =();
@exclude{@exclude} = @exclude;
delete @exclude{@forecast};
return join(',',keys %exclude);
}
sub Weather_Get($@) { sub Weather_Get($@) {
my ( $hash, @a ) = @_; my ( $hash, @a ) = @_;
@ -712,6 +740,7 @@ sub Weather_Define($$) {
location => $hash->{fhem}->{LOCATION}, location => $hash->{fhem}->{LOCATION},
apioptions => $hash->{APIOPTIONS}, apioptions => $hash->{APIOPTIONS},
language => $hash->{LANG} language => $hash->{LANG}
exclude => Weather_parseForcastAttr($hash),
} }
); );
@ -1373,7 +1402,7 @@ sub WeatherCheckOptions($@) {
], ],
"release_status": "stable", "release_status": "stable",
"license": "GPL_2", "license": "GPL_2",
"version": "v2.1.4", "version": "v2.2.5",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"
], ],

View File

@ -118,7 +118,7 @@ eval { use Readonly; 1 }
Readonly my $URL => 'https://api.openweathermap.org/data/2.5/'; Readonly my $URL => 'https://api.openweathermap.org/data/2.5/';
## URL . 'weather?' for current data ## URL . 'weather?' for current data
## URL . 'forecast?' for forecast data ## URL . 'onecall?' for forecast data
my %codes = ( my %codes = (
200 => 45, 200 => 45,
@ -194,6 +194,7 @@ sub new {
long => ( split( ',', $argsRef->{location} ) )[1], long => ( split( ',', $argsRef->{location} ) )[1],
fetchTime => 0, fetchTime => 0,
endpoint => 'none', endpoint => 'none',
exclude => $argsRef->{exclude},
}; };
$self->{cachemaxage} = ( $self->{cachemaxage} = (
@ -201,6 +202,7 @@ sub new {
? $apioptions->{cachemaxage} ? $apioptions->{cachemaxage}
: 900 : 900
); );
$self->{cached} = _CreateForecastRef($self); $self->{cached} = _CreateForecastRef($self);
bless $self, $class; bless $self, $class;
@ -315,7 +317,8 @@ sub _RetrieveDataFromOpenWeatherMap {
. $self->{long} . '&' . $self->{long} . '&'
. 'APPID=' . 'APPID='
. $self->{key} . '&' . 'lang=' . $self->{key} . '&' . 'lang='
. $self->{lang}; . $self->{lang} . '&' . 'exclude='
. $self->{exclude};
::HttpUtils_NonblockingGet($paramRef); ::HttpUtils_NonblockingGet($paramRef);
} }
@ -369,7 +372,8 @@ sub _ProcessingRetrieveData {
} }
else { else {
### Debug ### Debug
# print 'Response: ' . Dumper $data; # print '!!! DEBUG !!! - Endpoint: ' . $self->{endpoint} . "\n";
# print '!!! DEBUG !!! - Response: ' . Dumper $data;
###### Ab hier wird die ResponseHash Referenze für die Rückgabe zusammen gestellt ###### Ab hier wird die ResponseHash Referenze für die Rückgabe zusammen gestellt
$self->{cached}->{current_date_time} = $self->{cached}->{current_date_time} =
strftimeWrapper( "%a, %e %b %Y %H:%M", strftimeWrapper( "%a, %e %b %Y %H:%M",
@ -489,7 +493,7 @@ sub _ProcessingRetrieveData {
"%.1f", "%.1f",
( (
$data->{hourly}->[$i] $data->{hourly}->[$i]
->{main}->{temp} - 273.15 ->{temp} - 273.15
) )
) + 0.5 ) + 0.5
), ),
@ -498,52 +502,12 @@ sub _ProcessingRetrieveData {
"%.1f", "%.1f",
( (
$data->{hourly}->[$i] $data->{hourly}->[$i]
->{main}->{temp} - 273.15 ->{temp} - 273.15
)
) + 0.5
),
'low_c' => int(
sprintf(
"%.1f",
(
$data->{hourly}->[$i]
->{main}->{temp_min} -
273.15
)
) + 0.5
),
'high_c' => int(
sprintf(
"%.1f",
(
$data->{hourly}->[$i]
->{main}->{temp_max} -
273.15
)
) + 0.5
),
'tempLow' => int(
sprintf(
"%.1f",
(
$data->{hourly}->[$i]
->{main}->{temp_min} -
273.15
)
) + 0.5
),
'tempHigh' => int(
sprintf(
"%.1f",
(
$data->{hourly}->[$i]
->{main}->{temp_max} -
273.15
) )
) + 0.5 ) + 0.5
), ),
'humidity' => 'humidity' =>
$data->{hourly}->[$i]->{main} $data->{hourly}->[$i]
->{humidity}, ->{humidity},
'condition' => encode_utf8( 'condition' => encode_utf8(
$data->{hourly}->[$i]->{weather} $data->{hourly}->[$i]->{weather}
@ -551,7 +515,7 @@ sub _ProcessingRetrieveData {
), ),
'pressure' => int( 'pressure' => int(
sprintf( "%.1f", sprintf( "%.1f",
$data->{hourly}->[$i]->{main} $data->{hourly}->[$i]
->{pressure} ) + 0.5 ->{pressure} ) + 0.5
), ),
'wind' => int( 'wind' => int(
@ -559,7 +523,7 @@ sub _ProcessingRetrieveData {
"%.1f", "%.1f",
( (
$data->{hourly}->[$i] $data->{hourly}->[$i]
->{wind}->{speed} * 3.6 ->{wind_speed} * 3.6
) )
) + 0.5 ) + 0.5
), ),
@ -568,7 +532,7 @@ sub _ProcessingRetrieveData {
"%.1f", "%.1f",
( (
$data->{hourly}->[$i] $data->{hourly}->[$i]
->{wind}->{speed} * 3.6 ->{wind_speed} * 3.6
) )
) + 0.5 ) + 0.5
), ),
@ -577,13 +541,13 @@ sub _ProcessingRetrieveData {
"%.1f", "%.1f",
( (
$data->{hourly}->[$i] $data->{hourly}->[$i]
->{wind}->{gust} * 3.6 ->{wind_gust} * 3.6
) )
) + 0.5 ) + 0.5
), ),
'cloudCover' => 'cloudCover' =>
$data->{hourly}->[$i]->{clouds} $data->{hourly}->[$i]
->{all}, ->{clouds},
'code' => $codes{ 'code' => $codes{
$data->{hourly}->[$i]->{weather} $data->{hourly}->[$i]->{weather}
->[0]->{id} ->[0]->{id}
@ -593,12 +557,8 @@ sub _ProcessingRetrieveData {
->{icon}, ->{icon},
'rain1h' => 'rain1h' =>
$data->{hourly}->[$i]->{rain}->{'1h'}, $data->{hourly}->[$i]->{rain}->{'1h'},
'rain3h' =>
$data->{hourly}->[$i]->{rain}->{'3h'},
'snow1h' => 'snow1h' =>
$data->{hourly}->[$i]->{snow}->{'1h'}, $data->{hourly}->[$i]->{snow}->{'1h'},
'snow3h' =>
$data->{hourly}->[$i]->{snow}->{'3h'},
}, },
); );
@ -673,6 +633,69 @@ sub _ProcessingRetrieveData {
) )
) + 0.5 ) + 0.5
), ),
'temperature_morn' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{temp}->{morn} - 273.15
)
) + 0.5
),
'temperature_eve' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{temp}->{eve} - 273.15
)
) + 0.5
),
'temperature_night' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{temp}->{night} - 273.15
)
) + 0.5
),
'tempFeelsLike_morn' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{feels_like}->{morn} - 273.15
)
) + 0.5
),
'tempFeelsLike_eve' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{feels_like}->{eve} - 273.15
)
) + 0.5
),
'tempFeelsLike_night' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{feels_like}->{night} - 273.15
)
) + 0.5
),
'tempFeelsLike_day' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]
->{feels_like}->{day} - 273.15
)
) + 0.5
),
'temp_c' => int( 'temp_c' => int(
sprintf( sprintf(
"%.1f", "%.1f",
@ -718,6 +741,14 @@ sub _ProcessingRetrieveData {
) )
) + 0.5 ) + 0.5
), ),
'dew_point' => int(
sprintf(
"%.1f",
(
$data->{daily}->[$i]->{dew_point} - 273.15
)
) + 0.5
),
'humidity' => 'humidity' =>
$data->{daily}->[$i]->{humidity}, $data->{daily}->[$i]->{humidity},
'condition' => encode_utf8( 'condition' => encode_utf8(
@ -783,6 +814,47 @@ sub _ProcessingRetrieveData {
$i++; $i++;
} }
} }
if ( ref( $data->{alerts} ) eq "ARRAY"
&& scalar( @{ $data->{alerts} } ) > 0 )
{
## löschen des alten Datensatzes
delete $self->{cached}->{alerts};
my $i = 0;
for ( @{ $data->{alerts} } ) {
push(
@{ $self->{cached}->{alerts} },
{
'warn_'.$i.'_End' => strftimeWrapper(
"%a, %e %b %Y %H:%M",
localtime(
( $data->{alerts}->[$i]->{end} )
- 3600
)
),
'warn_'.$i.'_Start' => strftimeWrapper(
"%a, %e %b %Y %H:%M",
localtime(
( $data->{alerts}->[$i]->{start} )
- 3600
)
),
'warn_'.$i.'_Description' => encode_utf8(
$data->{alerts}->[$i]->{description}
),
'warn_'.$i.'_SenderName' => encode_utf8(
$data->{alerts}->[$i]->{sender_name}
),
'warn_'.$i.'_Event' => encode_utf8(
$data->{alerts}->[$i]->{event}
),
},
);
$i++;
}
}
} }
} }
} }

File diff suppressed because it is too large Load Diff