From e455a4edf2617ec53216c5274619078381021a90 Mon Sep 17 00:00:00 2001 From: LeonGaultier Date: Fri, 15 Mar 2019 18:52:14 +0000 Subject: [PATCH] 59_Weather: and APIs fix utf8 encode bug, insert patch from lippie git-svn-id: https://svn.fhem.de/fhem/trunk@18912 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/59_Weather.pm | 120 ++++++++++++++++++++++++--------- fhem/FHEM/DarkSkyAPI.pm | 75 +++++++++++++-------- fhem/FHEM/OpenWeatherMapAPI.pm | 47 +++++++++---- 4 files changed, 171 insertions(+), 72 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 1267554b9..f7963c8b6 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 59_Weather: and APIs fix utf8 encode bug, insert patch from lippie - change: 98_Text2Speech.pm: changed to new mpv API and removed some bugs thanks to RomanticBoy83 - feature: 71_YAMAHA_MC: optional parameter TurnFavNetRadioChannelOn added diff --git a/fhem/FHEM/59_Weather.pm b/fhem/FHEM/59_Weather.pm index 6bad2cff0..50d9c6945 100755 --- a/fhem/FHEM/59_Weather.pm +++ b/fhem/FHEM/59_Weather.pm @@ -5,6 +5,11 @@ # Copyright by Dr. Boris Neubert # e-mail: omega at online dot de # +# Contributors: +# - Marko Oldenburg (CoolTux) +# - Lippie +# +# # This file is part of fhem. # # Fhem is free software: you can redistribute it and/or modify @@ -664,7 +669,7 @@ sub Weather_Define($$) { readingsSingleUpdate( $hash, 'state', 'Initialized', 1 ); Weather_LanguageInitialize( $hash->{LANG} ); - my $apistring = $api . '::Weather'; + my $apistring = 'FHEM::' . $api . '::Weather'; $hash->{fhem}->{api} = $apistring->new( { devName => $hash->{NAME}, @@ -709,10 +714,17 @@ sub WeatherIconIMGTag($) { ##################################### sub WeatherAsHtmlV($;$$) { - my ( $d, $items, $f ) = @_; + my ( $d, $op1, $op2 ) = @_; + my $items = $op2; + my $f = $op1; + if($op1 =~ /[0-9]/g){ $items = $op1; } + if($op2 =~ /[dh]/g){ $f = $op2; } - $d = "" if ( !$d ); - $items = 6 if ( !$items ); + $f =~ tr/dh/./cd; + $f = "h" if ( !$f || length($f) > 1); + $items =~ tr/0-9/./cd; + $items = 6 if ( !$items ); + return "$d is not a Weather instance
" if ( !$defs{$d} || $defs{$d}->{TYPE} ne "Weather" ); @@ -749,32 +761,61 @@ sub WeatherAsHtmlV($;$$) { ); for ( my $i = 1 ; $i < $items ; $i++ ) { - $ret .= sprintf( -'%s%s: %s
min %s°C max %s°C', - $width, - WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ), - ReadingsVal( $d, "${fc}${i}_day_of_week", "" ), - ReadingsVal( $d, "${fc}${i}_condition", "" ), - ReadingsVal( $d, "${fc}${i}_low_c", " - " ), - ReadingsVal( $d, "${fc}${i}_high_c", " - " ) - ); + if(defined($h->{READINGS}->{"${fc}${i}_low_c"}) and $h->{READINGS}->{"${fc}${i}_low_c"}){ + $ret .= sprintf( + '%s%s: %s
min %s°C max %s°C
%s', + $width, + WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ), + ReadingsVal( $d, "${fc}${i}_day_of_week", "" ), + ReadingsVal( $d, "${fc}${i}_condition", "" ), + ReadingsVal( $d, "${fc}${i}_low_c", " - " ), + ReadingsVal( $d, "${fc}${i}_high_c", " - " ), + ReadingsVal( $d, "${fc}${i}_wind_condition", " - " ) + ); + }else{ + $ret .= sprintf( + '%s%s: %s
%s°C
%s', + $width, + WeatherIconIMGTag( ReadingsVal( $d, "${fc}${i}_icon", "" ) ), + ReadingsVal( $d, "${fc}${i}_day_of_week", "" ), + ReadingsVal( $d, "${fc}${i}_condition", "" ), + ReadingsVal( $d, "${fc}${i}_temperature", " - " ), + ReadingsVal( $d, "${fc}${i}_wind_condition", " - " ) + ); + } } $ret .= ""; return $ret; } -sub WeatherAsHtml($;$) { - my ( $d, $i ) = @_; +sub WeatherAsHtml($;$$) { + my ( $d, $op1, $op2 ) = @_; + my $items = $op2; + my $f = $op1; + if($op1 =~ /[0-9]/g){ $items = $op1; } + if($op2 =~ /[dh]/g){ $f = $op2; } - WeatherAsHtmlV( $d, $i ); + $f =~ tr/dh/./cd; + $f = "h" if ( !$f || length($f) > 1); + $items =~ tr/0-9/./cd; + $items = 6 if ( !$items ); + + WeatherAsHtmlV( $d, $f, $items ); } sub WeatherAsHtmlH($;$$) { - my ( $d, $items, $f ) = @_; - - $d = "" if ( !$d ); - $items = 6 if ( !$items ); + my ( $d, $op1, $op2 ) = @_; + my $items = $op2; + my $f = $op1; + if($op1 =~ /[0-9]/g){ $items = $op1; } + if($op2 =~ /[dh]/g){ $f = $op2; } + + $f =~ tr/dh/./cd; + $f = "h" if ( !$f || length($f) > 1); + $items =~ tr/0-9/./cd; + $items = 6 if ( !$items ); + return "$d is not a Weather instance
" if ( !$defs{$d} || $defs{$d}->{TYPE} ne "Weather" ); @@ -832,31 +873,50 @@ sub WeatherAsHtmlH($;$$) { ReadingsVal( $d, "humidity", "" ) ); for ( my $i = 1 ; $i < $items ; $i++ ) { - $ret .= sprintf( 'min %s°C', - ReadingsVal( $d, "${fc}${i}_low_c", " - " ) ); + if(defined($h->{READINGS}->{"${fc}${i}_low_c"}) and $h->{READINGS}->{"${fc}${i}_low_c"}){ + $ret .= sprintf( 'min %s°C', + ReadingsVal( $d, "${fc}${i}_low_c", " - " ) ); + } + else { + $ret .= sprintf( ' %s°C', + ReadingsVal( $d, "${fc}${i}_temperature", " - " ) ); + } } + $ret .= ''; # wind | max $ret .= sprintf( '%s', ReadingsVal( $d, "wind_condition", "" ) ); for ( my $i = 1 ; $i < $items ; $i++ ) { - $ret .= sprintf( 'max %s°C', - ReadingsVal( $d, "${fc}${i}_high_c", " - " ) ); + if(defined($h->{READINGS}->{"${fc}${i}_high_c"}) and $h->{READINGS}->{"${fc}${i}_high_c"}){ + $ret .= sprintf( 'max %s°C', + ReadingsVal( $d, "${fc}${i}_high_c", " - " ) ); + } } + $ret .= ""; return $ret; } -sub WeatherAsHtmlD($;$) { - my ( $d, $i ) = @_; +sub WeatherAsHtmlD($;$$) { + my ( $d, $op1, $op2 ) = @_; + my $items = $op2; + my $f = $op1; + if($op1 =~ /[0-9]/g){ $items = $op1; } + if($op2 =~ /[dh]/g){ $f = $op2; } + + $f =~ tr/dh/./cd; + $f = "h" if ( !$f || length($f) > 1); + $items =~ tr/0-9/./cd; + $items = 6 if ( !$items ); if ($FW_ss) { - WeatherAsHtmlV( $d, $i ); + WeatherAsHtmlV( $d, $f , $items); } else { - WeatherAsHtmlH( $d, $i ); + WeatherAsHtmlH( $d, $f , $items); } } @@ -957,7 +1017,7 @@ sub WeatherAsHtmlD($;$) { to limit the numer of icons to display.

Example:
-      define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather") }
+      define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather","h",10) }
     
@@ -1130,7 +1190,7 @@ sub WeatherAsHtmlD($;$) { Wird der dritte Parameter verwendet muss auch der zweite Parameter für die Anzahl der darzustellenden Icons gesetzt werden.

Beispiel:
-      define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather") }
+      define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather","h",10) }
     
diff --git a/fhem/FHEM/DarkSkyAPI.pm b/fhem/FHEM/DarkSkyAPI.pm index 48115273d..fe9323b9e 100644 --- a/fhem/FHEM/DarkSkyAPI.pm +++ b/fhem/FHEM/DarkSkyAPI.pm @@ -28,7 +28,7 @@ # ############################################################################### -package DarkSkyAPI::Weather; +package FHEM::DarkSkyAPI::Weather; use strict; use warnings; @@ -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 VERSION => '0.2.6'; +use constant VERSION => '0.2.7'; my %codes = ( 'clear-day' => 32, @@ -215,8 +215,8 @@ sub _ProcessingRetrieveData($$) { # print Dumper $data; ## für Debugging $self->{cached}->{current_date_time} = - encode_utf8(strftime( "%a, %e %b %Y %H:%M", - localtime( $self->{fetchTime} ) )); + strftimeWrapper( "%a, %e %b %Y %H:%M", + localtime( $self->{fetchTime} ) ); $self->{cached}->{timezone} = $data->{timezone}; $self->{cached}->{license}{text} = $data->{flags}->{'meteoalarm-license'}; @@ -253,10 +253,10 @@ sub _ProcessingRetrieveData($$) { 'ozone' => $data->{currently}->{ozone}, 'code' => $codes{ $data->{currently}->{icon} }, 'iconAPI' => $data->{currently}->{icon}, - 'pubDate' => encode_utf8(strftime( + 'pubDate' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{currently}->{'time'} ) - )), + ), 'precipProbability' => $data->{currently}->{precipProbability} * 100, 'apparentTemperature' => int( sprintf( @@ -277,12 +277,12 @@ sub _ProcessingRetrieveData($$) { push( @{ $self->{cached}->{forecast}->{daily} }, { - 'pubDate' => encode_utf8(strftime( + 'pubDate' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i]->{'time'} ) - )), + ), 'day_of_week' => strftime( "%a", localtime( @@ -304,49 +304,49 @@ sub _ProcessingRetrieveData($$) { $data->{daily}->{data}->[$i] ->{temperatureLow} ) + 0.5 ), - 'tempLowTime' => encode_utf8(strftime( + 'tempLowTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i] ->{temperatureLowTime} ) - )), + ), 'tempHigh' => int( sprintf( "%.1f", $data->{daily}->{data}->[$i] ->{temperatureHigh} ) + 0.5 ), - 'tempHighTime' => encode_utf8(strftime( + 'tempHighTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i] ->{temperatureHighTime} ) - )), + ), 'apparentTempLow' => int( sprintf( "%.1f", $data->{daily}->{data}->[$i] ->{apparentTemperatureLow} ) + 0.5 ), - 'apparentTempLowTime' => encode_utf8(strftime( + 'apparentTempLowTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i] ->{apparentTemperatureLowTime} ) - )), + ), 'apparentTempHigh' => int( sprintf( "%.1f", $data->{daily}->{data}->[$i] ->{apparentTemperatureHigh} ) + 0.5 ), - 'apparentTempHighTime' => encode_utf8(strftime( + 'apparentTempHighTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i] ->{apparentTemperatureHighTime} ) - )), + ), 'code' => $codes{ $data->{daily}->{data}->[$i]->{icon} }, 'iconAPI' => $data->{daily}->{data}->[$i]->{icon}, @@ -356,12 +356,12 @@ sub _ProcessingRetrieveData($$) { 'ozone' => $data->{daily}->{data}->[$i]->{ozone}, 'uvIndex' => $data->{daily}->{data}->[$i]->{uvIndex}, - 'uvIndexTime' => encode_utf8(strftime( + 'uvIndexTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i]->{uvIndexTime} ) - )), + ), 'dewPoint' => int( sprintf( "%.1f", $data->{daily}->{data}->[$i]->{dewPoint} ) @@ -388,26 +388,26 @@ sub _ProcessingRetrieveData($$) { ($data->{daily}->{data}->[$i]->{windGust} * 3.6) ) + 0.5 ), - 'windGustTime' => encode_utf8(strftime( + 'windGustTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i]->{windGustTime} ) - )), + ), 'moonPhase' => $data->{daily}->{data}->[$i]->{moonPhase}, - 'sunsetTime' => encode_utf8(strftime( + 'sunsetTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i]->{sunsetTime} ) - )), - 'sunriseTime' => encode_utf8(strftime( + ), + 'sunriseTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{daily}->{data}->[$i]->{sunriseTime} ) - )), + ), 'pressure' => int( sprintf( "%.1f", $data->{daily}->{data}->[$i]->{pressure} ) @@ -425,7 +425,7 @@ sub _ProcessingRetrieveData($$) { $self->{cached}->{forecast}->{daily}[$i]{precipIntensity} = ( defined($data->{daily}->{data}->[$i]->{precipIntensity}) ? $data->{daily}->{data}->[$i]->{precipIntensity} : '-' ); $self->{cached}->{forecast}->{daily}[$i]{precipProbability} = ( defined($data->{daily}->{data}->[$i]->{precipProbability}) ? $data->{daily}->{data}->[$i]->{precipProbability} * 100 : '-' ); $self->{cached}->{forecast}->{daily}[$i]{precipType} = ( defined($data->{daily}->{data}->[$i]->{precipType}) ? $data->{daily}->{data}->[$i]->{precipType} : '-' ); - $self->{cached}->{forecast}->{daily}[$i]{precipIntensityMaxTime} = ( defined($data->{daily}->{data}->[$i]->{precipIntensityMaxTime}) ? encode_utf8(strftime("%a, %e %b %Y %H:%M",localtime($data->{daily}->{data}->[$i]->{precipIntensityMaxTime}) )) : '-' ); + $self->{cached}->{forecast}->{daily}[$i]{precipIntensityMaxTime} = ( defined($data->{daily}->{data}->[$i]->{precipIntensityMaxTime}) ? strftimeWrapper("%a, %e %b %Y %H:%M",localtime($data->{daily}->{data}->[$i]->{precipIntensityMaxTime}) ) : '-' ); $i++; } @@ -441,12 +441,12 @@ sub _ProcessingRetrieveData($$) { push( @{ $self->{cached}->{forecast}->{hourly} }, { - 'pubDate' => encode_utf8(strftime( + 'pubDate' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{hourly}->{data}->[$i]->{'time'} ) - )), + ), 'day_of_week' => strftime( "%a, %H:%M", localtime( @@ -522,7 +522,7 @@ sub _ErrorHandling($$) { my ( $self, $err ) = @_; $self->{cached}->{current_date_time} = - encode_utf8(strftime( "%a, %e %b %Y %H:%M", localtime( $self->{fetchTime} ) )), + strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $self->{fetchTime} ) ), $self->{cached}->{status} = $err; $self->{cached}->{validity} = 'stale'; } @@ -543,6 +543,25 @@ sub _CreateForecastRef($) { return $forecastRef; } +sub strftimeWrapper(@) { + my $string = POSIX::strftime(@_); + + $string =~ s/\xe4/ä/g; + $string =~ s/\xc4/Ä/g; + $string =~ s/\xf6/ö/g; + $string =~ s/\xd6/Ö/g; + $string =~ s/\xfc/ü/g; + $string =~ s/\xdc/Ü/g; + $string =~ s/\xdf/ß/g; + $string =~ s/\xdf/ß/g; + $string =~ s/\xe1/á/g; + $string =~ s/\xe9/é/g; + $string =~ s/\xc1/Á/g; + $string =~ s/\xc9/É/g; + + return $string; +} + ############################################################################## 1; diff --git a/fhem/FHEM/OpenWeatherMapAPI.pm b/fhem/FHEM/OpenWeatherMapAPI.pm index a3446b881..7f78224fe 100644 --- a/fhem/FHEM/OpenWeatherMapAPI.pm +++ b/fhem/FHEM/OpenWeatherMapAPI.pm @@ -32,7 +32,7 @@ # https://api.openweathermap.org/data/2.5/forecast?lat=[lat]&lon=[long]&APPID=[API] Forecast # https://openweathermap.org/weather-conditions Icons und Conditions ID's -package OpenWeatherMapAPI::Weather; +package FHEM::OpenWeatherMapAPI::Weather; use strict; use warnings; @@ -48,7 +48,7 @@ eval "use Encode qw(encode_utf8);1" or $missingModul .= "Encode "; # use Data::Dumper; # for Debug only ## API URL use constant URL => 'https://api.openweathermap.org/data/2.5/'; -use constant VERSION => '0.2.3'; +use constant VERSION => '0.2.4'; ## URL . 'weather?' for current data ## URL . 'forecast?' for forecast data @@ -264,12 +264,12 @@ sub _ProcessingRetrieveData($$) { # print 'Response: ' . Dumper $data; ###### Ab hier wird die ResponseHash Referenze für die Rückgabe zusammen gestellt $self->{cached}->{current_date_time} = - encode_utf8(strftime( "%a, %e %b %Y %H:%M", - localtime( $self->{fetchTime} ) )); + strftimeWrapper( "%a, %e %b %Y %H:%M", + localtime( $self->{fetchTime} ) ); if ( $self->{endpoint} eq 'weather' ) { $self->{cached}->{country} = $data->{sys}->{country}; - $self->{cached}->{city} = $data->{name}; + $self->{cached}->{city} = encode_utf8($data->{name}); $self->{cached}->{license}{text} = 'none'; $self->{cached}->{current} = { 'temperature' => int( @@ -311,18 +311,18 @@ sub _ProcessingRetrieveData($$) { int( sprintf( "%.1f", $data->{visibility} ) + 0.5 ), 'code' => $codes{ $data->{weather}->[0]->{id} }, 'iconAPI' => $data->{weather}->[0]->{icon}, - 'sunsetTime' => encode_utf8(strftime( + 'sunsetTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{sys}->{sunset} ) - )), - 'sunriseTime' => encode_utf8(strftime( + ), + 'sunriseTime' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{sys}->{sunrise} ) - )), - 'pubDate' => encode_utf8(strftime( + ), + 'pubDate' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $data->{dt} ) - )), + ), }; } @@ -338,12 +338,12 @@ sub _ProcessingRetrieveData($$) { push( @{ $self->{cached}->{forecast}->{hourly} }, { - 'pubDate' => encode_utf8(strftime( + 'pubDate' => strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( ( $data->{list}->[$i]->{dt} ) - 3600 ) - )), + ), 'day_of_week' => strftime( "%a, %H:%M", localtime( @@ -472,7 +472,7 @@ sub _ErrorHandling($$) { my ( $self, $err ) = @_; $self->{cached}->{current_date_time} = - encode_utf8(strftime( "%a, %e %b %Y %H:%M", localtime( $self->{fetchTime} ) )), + strftimeWrapper( "%a, %e %b %Y %H:%M", localtime( $self->{fetchTime} ) ), $self->{cached}->{status} = $err; $self->{cached}->{validity} = 'stale'; } @@ -493,6 +493,25 @@ sub _CreateForecastRef($) { return $forecastRef; } +sub strftimeWrapper(@) { + my $string = POSIX::strftime(@_); + + $string =~ s/\xe4/ä/g; + $string =~ s/\xc4/Ä/g; + $string =~ s/\xf6/ö/g; + $string =~ s/\xd6/Ö/g; + $string =~ s/\xfc/ü/g; + $string =~ s/\xdc/Ü/g; + $string =~ s/\xdf/ß/g; + $string =~ s/\xdf/ß/g; + $string =~ s/\xe1/á/g; + $string =~ s/\xe9/é/g; + $string =~ s/\xc1/Á/g; + $string =~ s/\xc9/É/g; + + return $string; +} + ############################################################################## 1;