76_SMAPortal: internal code changes, bug fixes show weather_icon

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@22160 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2020-06-11 12:18:13 +00:00
parent 01a32ec7e7
commit 78ac6cf921
3 changed files with 325 additions and 272 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # 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. # Do not insert empty lines here, update check depends on it.
- bugfix: 76_SMAPortal: internal code changes, bug fixes show weather_icon
- changed: 76_SMAPortal: internal code changes, minor bug fixes - changed: 76_SMAPortal: internal code changes, minor bug fixes
- bugfix: 70_BRAVIA: fix register procedure - bugfix: 70_BRAVIA: fix register procedure
- change: 32_withings: added sleep apnea readings - change: 32_withings: added sleep apnea readings

View File

@ -135,6 +135,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"2.10.3" => "11.06.2020 internal code changes, bug fixes show weather_icon ",
"2.10.2" => "10.06.2020 bug fixes get/switch consumers ", "2.10.2" => "10.06.2020 bug fixes get/switch consumers ",
"2.10.1" => "08.06.2020 internal code changes, bug fixes ", "2.10.1" => "08.06.2020 internal code changes, bug fixes ",
"2.10.0" => "03.06.2020 refactored login process ", "2.10.0" => "03.06.2020 refactored login process ",
@ -212,13 +213,26 @@ my %statkeys = ( # Statistikdaten auszulesende Schlüs
AutarkyRate => 1, AutarkyRate => 1,
); );
# Tags der verfügbaren Datenquellen
my @pd = qw( balanceDayData
liveData
weatherData
forecastData
consumerLiveData
consumerDayData
consumerMonthData
consumerYearData
);
############################################################### ###############################################################
# SMAPortal Initialize # SMAPortal Initialize
############################################################### ###############################################################
sub Initialize { sub Initialize {
my ($hash) = @_; my ($hash) = @_;
my $v5d = join ",", @pd;
$hash->{DefFn} = \&Define; $hash->{DefFn} = \&Define;
$hash->{UndefFn} = \&Undefine; $hash->{UndefFn} = \&Undefine;
$hash->{DeleteFn} = \&Delete; $hash->{DeleteFn} = \&Delete;
@ -232,7 +246,7 @@ sub Initialize {
"interval ". "interval ".
"showPassInLog:1,0 ". "showPassInLog:1,0 ".
"userAgent ". "userAgent ".
"verbose5Data:none,loginData,balanceDayData,liveData,weatherData,forecastData,consumerLiveData,consumerDayData,consumerMonthData,consumerYearData ". "verbose5Data:none,loginData,".$v5d." ".
$readingFnAttributes; $readingFnAttributes;
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval' # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html) eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval' # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html)
@ -753,19 +767,17 @@ sub GetSetData { ## no cri
my ($string) = @_; my ($string) = @_;
my ($name,$getp,$setp) = split("\\|",$string); my ($name,$getp,$setp) = split("\\|",$string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $errstate = 0;
my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt"); my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt");
my $v5d = AttrVal($name, "verbose5Data", "none"); my $v5d = AttrVal($name, "verbose5Data", "none");
my $dl = AttrVal($name, "detailLevel", 1); # selected Detail Level my $dl = AttrVal($name, "detailLevel", 1); # selected Detail Level
my $state = "ok"; my $state = "ok";
my ($reread,$retry) = (0,0);
my ($exceed,$newcycle) = (0,0);
my ($st,$lc) = ("",""); my ($st,$lc) = ("","");
my @da = (); my @da = ();
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content) = ("","","");
my ($d,$op,$paref);
my ($errstate,$reread,$retry,$exceed,$newcycle) = (0,0,0,0,0);
my ($d,$op);
if($setp ne "none") { if($setp ne "none") {
# Verbraucher soll in den Status $op geschaltet werden # Verbraucher soll in den Status $op geschaltet werden
($d,$op) = split(":",$setp); ($d,$op) = split(":",$setp);
@ -803,7 +815,7 @@ sub GetSetData { ## no cri
### Login ### Login
############## ##############
$paref = [ $name, $ua, $state, $errstate ]; my $paref = [ $name, $ua, $state, $errstate ];
($state, $errstate) = _checkLogin ($paref); ($state, $errstate) = _checkLogin ($paref);
if($errstate) { if($errstate) {
@ -854,18 +866,16 @@ sub GetSetData { ## no cri
### Live-Daten ### Live-Daten
################ ################
my ($livedata,$livedata_content) = _getData ({ name => $name, ($errstate,$state,$reread,$retry) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/homemanager?t='.$time, call => 'https://www.sunnyportal.com/homemanager?t='.$time,
tag => "liveData" tag => "liveData",
}); state => $state,
fnaref => [ qw( extractLiveData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state,
data => $livedata
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -897,37 +907,25 @@ sub GetSetData { ## no cri
Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...}); Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...});
$newcycle = 1; $newcycle = 1;
return "$name|$exceed|$newcycle|$errstate|$getp|$setp"; return "$name|$exceed|$newcycle|$errstate|$getp|$setp";
} }
if ($livedata_content && $livedata_content !~ m/undefined/ix) {
extractLiveData ($hash,\@da,$livedata_content);
}
### Wetterdaten ### Wetterdaten
##################### #####################
my ($weatherdata,$weatherdata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/Dashboard/Weather', call => 'https://www.sunnyportal.com/Dashboard/Weather',
tag => "weatherData" tag => "weatherData",
}); state => $state,
fnaref => [ qw( extractWeatherData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $weatherdata
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($weatherdata_content && $weatherdata_content !~ m/undefined/ix) {
extractWeatherData ($hash,\@da,$weatherdata_content);
}
@ -938,57 +936,41 @@ sub GetSetData { ## no cri
my $tab = 1; # Tab 1 -> Tag , 2->Monat, 3->Jahr, 4->Gesamt my $tab = 1; # Tab 1 -> Tag , 2->Monat, 3->Jahr, 4->Gesamt
my %fields = ("Content-Type" => "application/json; charset=utf-8"); my %fields = ("Content-Type" => "application/json; charset=utf-8");
my $cont = qq{ {"tabNumber":$tab,"anchorTime":$anchort} }; my $cont = qq{ {"tabNumber":$tab,"anchorTime":$anchort} };
my ($balancedataday,$balancedataday_content) = _putData ({ name => $name,
ua => $ua,
call => 'https://www.sunnyportal.com/FixedPages/HoManEnergyRedesign.aspx/GetLegendWithValues',
fields => \%fields,
content => $cont,
tag => "balanceDayData"
});
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name,
errstate => $errstate,
state => $state,
data => $balancedataday
});
($errstate,$state) = _dispatchPost ({ name => $name,
ua => $ua,
call => 'https://www.sunnyportal.com/FixedPages/HoManEnergyRedesign.aspx/GetLegendWithValues',
tag => "balanceDayData",
state => $state,
fnaref => [ qw( extractStatisticData ) ],
fields => \%fields,
content => $cont,
addon => "Day",
daref => \@da
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($balancedataday_content && $balancedataday_content !~ m/undefined/ix) {
extractStatisticData ($hash,\@da,$balancedataday_content,"Day");
}
### Forecast Daten abrufen ### Forecast Daten abrufen
########################### ###########################
if($dl > 1) { if($dl > 1) {
my ($forecastdata,$forecastdata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData', call => 'https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData',
tag => "forecastData" tag => "forecastData",
}); state => $state,
fnaref => [ qw( extractPlantData extractForecastData extractConsumerData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $forecastdata
});
if($errstate) { if($errstate) {
$st = encode_base64 ($state, ""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($forecastdata_content && $forecastdata_content !~ m/undefined/ix) {
extractPlantData ($hash,\@da,$forecastdata_content);
extractForecastData ($hash,\@da,$forecastdata_content);
extractConsumerData ($hash,\@da,$forecastdata_content);
}
} }
@ -997,26 +979,19 @@ sub GetSetData { ## no cri
### Consumer Livedaten und historische Energiedaten ### Consumer Livedaten und historische Energiedaten
##################################################### #####################################################
if($dl > 2) { if($dl > 2) {
my ($consumerlivedata,$consumerlivedata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues', call => 'https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues',
tag => "consumerLiveData" tag => "consumerLiveData",
}); state => $state,
fnaref => [ qw( extractConsumerLiveData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $consumerlivedata
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($consumerlivedata_content && $consumerlivedata_content !~ m/undefined/ix) {
extractConsumerLiveData ($hash,\@da,$consumerlivedata_content);
}
if($hash->{HELPER}{PLANTOID}) { if($hash->{HELPER}{PLANTOID}) {
@ -1044,15 +1019,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde"); Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde");
Log3 ($name, 5, "$name - Request consumer current day data string ->\n$ccdd"); Log3 ($name, 5, "$name - Request consumer current day data string ->\n$ccdd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccdd, call => $ccdd,
tag => "consumerDayData", tag => "consumerDayData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "day", addon => "day",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1063,15 +1038,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde"); Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde");
Log3 ($name, 5, "$name - Request consumer current month data string ->\n$ccmd"); Log3 ($name, 5, "$name - Request consumer current month data string ->\n$ccmd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccmd, call => $ccmd,
tag => "consumerMonthData", tag => "consumerMonthData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "month", addon => "month",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1082,15 +1057,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde"); Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde");
Log3 ($name, 5, "$name - Request consumer current year data string ->\n$ccyd"); Log3 ($name, 5, "$name - Request consumer current year data string ->\n$ccyd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccyd, call => $ccyd,
tag => "consumerYearData", tag => "consumerYearData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "year", addon => "year",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1198,16 +1173,16 @@ return ($state, $errstate);
} }
################################################################ ################################################################
# Dispatcher # Dispatcher GET
################################################################ ################################################################
sub _dispatch { sub _dispatchGet {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent my $ua = $paref->{ua}; # LWP Useragent
my $call = $paref->{call}; # Seitenaufruf zur Datenquelle my $call = $paref->{call}; # Seitenaufruf zur Datenquelle
my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten
my $state = $paref->{state}; my $state = $paref->{state};
my $fn = $paref->{function}; # aufzurufende Funktion zur Datenextraktion my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -1226,15 +1201,65 @@ sub _dispatch {
data => $data data => $data
}); });
return ($errstate,$state) if($errstate); return ($errstate,$state,$reread,$retry) if($errstate || $reread || $retry);
if ($data_cont && $data_cont !~ m/undefined/ix) { if ($data_cont && $data_cont !~ m/undefined/ix) {
my @func = @$fnref;
no strict "refs"; ## no critic 'NoStrict' no strict "refs"; ## no critic 'NoStrict'
&{$fn} ($hash,$daref,$data_cont,$fnaddon); for my $fn (@func) {
&{$fn} ($hash,$daref,$data_cont,$fnaddon);
}
use strict "refs"; use strict "refs";
} }
return ($errstate,$state); return ($errstate,$state,$reread,$retry);
}
################################################################
# Dispatcher POST
################################################################
sub _dispatchPost {
my $paref = shift;
my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent
my $call = $paref->{call}; # Seitenaufruf zur Datenquelle
my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten
my $state = $paref->{state};
my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fields = $paref->{fields}; # Referenz zum Hash der zu übertragenden PUSH Header
my $cont = $paref->{content}; # Content Daten für PUSH (String)
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name};
my ($reread,$retry,$errstate) = (0,0,0);
my ($data,$data_cont) = _postData ({ name => $name,
ua => $ua,
call => $call,
tag => $tag,
fields => $fields,
content => $cont,
});
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name,
errstate => $errstate,
state => $state,
data => $data
});
return ($errstate,$state) if($errstate);
if ($data_cont && $data_cont !~ m/undefined/ix) {
my @func = @$fnref;
no strict "refs"; ## no critic 'NoStrict'
for my $fn (@func) {
&{$fn} ($hash,$daref,$data_cont,$fnaddon);
}
use strict "refs";
}
return ($errstate,$state,$reread,$retry);
} }
################################################################ ################################################################
@ -1268,7 +1293,7 @@ return ($data,$dcont);
################################################################ ################################################################
# Standard Abruf Daten POST # Standard Abruf Daten POST
################################################################ ################################################################
sub _putData { sub _postData {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $ua = $paref->{ua}; my $ua = $paref->{ua};
@ -1692,7 +1717,7 @@ sub extractForecastData { ## no critic 'complexity'
push @$daref, "L4_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh"; push @$daref, "L4_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh";
# add WeatherId Helper to show weather icon # add WeatherId Helper to show weather icon
$hash->{HELPER}{"L4_".${time_str}."_WeatherId"} = int($fc_obj->{'WeatherId'}) if(defined $fc_obj->{'WeatherId'}); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "L4_".${time_str}."_WeatherId:".int($fc_obj->{'WeatherId'}) ], 1) if(defined $fc_obj->{'WeatherId'});
} }
if($time_str =~ /ThisHour/x && $dl >= 2) { if($time_str =~ /ThisHour/x && $dl >= 2) {
push @$daref, "L2_${time_str}_Time:". TimeAdjust($hash,$fc_obj->{'TimeStamp'}->{'DateTime'},$tkind); push @$daref, "L2_${time_str}_Time:". TimeAdjust($hash,$fc_obj->{'TimeStamp'}->{'DateTime'},$tkind);
@ -1702,7 +1727,7 @@ sub extractForecastData { ## no critic 'complexity'
push @$daref, "L2_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh"; push @$daref, "L2_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh";
# add WeatherId Helper to show weather icon # add WeatherId Helper to show weather icon
$hash->{HELPER}{"L2_".${time_str}."_WeatherId"} = int($fc_obj->{'WeatherId'}) if(defined $fc_obj->{'WeatherId'}); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "L2_".${time_str}."_WeatherId:".int($fc_obj->{'WeatherId'}) ], 1) if(defined $fc_obj->{'WeatherId'});
} }
} }
} }
@ -2485,7 +2510,7 @@ sub PortalAsHtml {
$di{0} = $pv{0} - $co{0}; $di{0} = $pv{0} - $co{0};
$is{0} = (ReadingsVal($name,"L2_ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef; $is{0} = (ReadingsVal($name,"L2_ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef;
$we{0} = $hash->{HELPER}{L2_ThisHour_WeatherId} if($weather); # für Wettericons $we{0} = $hash->{HELPER}{L2_ThisHour_WeatherId} if($weather); # für Wettericons
$we{0} = $we{0}?$we{0}:0; $we{0} = $we{0} ? $we{0} : 999;
if(AttrVal("global","language","EN") eq "DE") { if(AttrVal("global","language","EN") eq "DE") {
(undef,undef,undef,$t{0}) = ReadingsVal($name,"L2_ThisHour_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x; (undef,undef,undef,$t{0}) = ReadingsVal($name,"L2_ThisHour_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x;
@ -2558,7 +2583,7 @@ sub PortalAsHtml {
$is{$i} = (ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef; $is{$i} = (ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
$we{$i} = $hash->{HELPER}{"L4_NextHour".sprintf("%02d",$i)."_WeatherId"} if($weather); # für Wettericons $we{$i} = $hash->{HELPER}{"L4_NextHour".sprintf("%02d",$i)."_WeatherId"} if($weather); # für Wettericons
$we{$i} = $we{$i}?$we{$i}:0; $we{$i} = $we{$i} ? $we{$i} : 999;
if(AttrVal("global","language","EN") eq "DE") { if(AttrVal("global","language","EN") eq "DE") {
(undef,undef,undef,$t{$i}) = ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x; (undef,undef,undef,$t{$i}) = ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x;
@ -3010,7 +3035,8 @@ sub weather_icon {
'170' => 'weather_night_snow_rain', # Mond, Wolke mit Schnee (1 Flocke) - Nacht # neu '170' => 'weather_night_snow_rain', # Mond, Wolke mit Schnee (1 Flocke) - Nacht # neu
'171' => 'weather_night_snow_heavy', # Mond, Wolke mit Schnee (3 Flocken) - Nacht # neu '171' => 'weather_night_snow_heavy', # Mond, Wolke mit Schnee (3 Flocken) - Nacht # neu
'180' => 'weather_night_thunderstorm_light', # Wolke mit Blitz - Nacht # neu '180' => 'weather_night_thunderstorm_light', # Wolke mit Blitz - Nacht # neu
'181' => 'weather_night_thunderstorm' # Wolke mit Blitz und Starkregen - Nacht # neu '181' => 'weather_night_thunderstorm', # Wolke mit Blitz und Starkregen - Nacht # neu
'999' => '1px-spacer' # Dummy - keine Anzeige Wettericon # vorhanden
); );
return $weather_ids{$id} if(defined($weather_ids{$id})); return $weather_ids{$id} if(defined($weather_ids{$id}));

View File

@ -135,6 +135,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"2.10.3" => "11.06.2020 internal code changes, bug fixes show weather_icon ",
"2.10.2" => "10.06.2020 bug fixes get/switch consumers ", "2.10.2" => "10.06.2020 bug fixes get/switch consumers ",
"2.10.1" => "08.06.2020 internal code changes, bug fixes ", "2.10.1" => "08.06.2020 internal code changes, bug fixes ",
"2.10.0" => "03.06.2020 refactored login process ", "2.10.0" => "03.06.2020 refactored login process ",
@ -212,13 +213,26 @@ my %statkeys = ( # Statistikdaten auszulesende Schlüs
AutarkyRate => 1, AutarkyRate => 1,
); );
# Tags der verfügbaren Datenquellen
my @pd = qw( balanceDayData
liveData
weatherData
forecastData
consumerLiveData
consumerDayData
consumerMonthData
consumerYearData
);
############################################################### ###############################################################
# SMAPortal Initialize # SMAPortal Initialize
############################################################### ###############################################################
sub Initialize { sub Initialize {
my ($hash) = @_; my ($hash) = @_;
my $v5d = join ",", @pd;
$hash->{DefFn} = \&Define; $hash->{DefFn} = \&Define;
$hash->{UndefFn} = \&Undefine; $hash->{UndefFn} = \&Undefine;
$hash->{DeleteFn} = \&Delete; $hash->{DeleteFn} = \&Delete;
@ -232,7 +246,7 @@ sub Initialize {
"interval ". "interval ".
"showPassInLog:1,0 ". "showPassInLog:1,0 ".
"userAgent ". "userAgent ".
"verbose5Data:none,loginData,balanceDayData,liveData,weatherData,forecastData,consumerLiveData,consumerDayData,consumerMonthData,consumerYearData ". "verbose5Data:none,loginData,".$v5d." ".
$readingFnAttributes; $readingFnAttributes;
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval' # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html) eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval' # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html)
@ -753,19 +767,17 @@ sub GetSetData { ## no cri
my ($string) = @_; my ($string) = @_;
my ($name,$getp,$setp) = split("\\|",$string); my ($name,$getp,$setp) = split("\\|",$string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $errstate = 0;
my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt"); my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt");
my $v5d = AttrVal($name, "verbose5Data", "none"); my $v5d = AttrVal($name, "verbose5Data", "none");
my $dl = AttrVal($name, "detailLevel", 1); # selected Detail Level my $dl = AttrVal($name, "detailLevel", 1); # selected Detail Level
my $state = "ok"; my $state = "ok";
my ($reread,$retry) = (0,0);
my ($exceed,$newcycle) = (0,0);
my ($st,$lc) = ("",""); my ($st,$lc) = ("","");
my @da = (); my @da = ();
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content) = ("","","");
my ($d,$op,$paref);
my ($errstate,$reread,$retry,$exceed,$newcycle) = (0,0,0,0,0);
my ($d,$op);
if($setp ne "none") { if($setp ne "none") {
# Verbraucher soll in den Status $op geschaltet werden # Verbraucher soll in den Status $op geschaltet werden
($d,$op) = split(":",$setp); ($d,$op) = split(":",$setp);
@ -803,7 +815,7 @@ sub GetSetData { ## no cri
### Login ### Login
############## ##############
$paref = [ $name, $ua, $state, $errstate ]; my $paref = [ $name, $ua, $state, $errstate ];
($state, $errstate) = _checkLogin ($paref); ($state, $errstate) = _checkLogin ($paref);
if($errstate) { if($errstate) {
@ -854,18 +866,16 @@ sub GetSetData { ## no cri
### Live-Daten ### Live-Daten
################ ################
my ($livedata,$livedata_content) = _getData ({ name => $name, ($errstate,$state,$reread,$retry) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/homemanager?t='.$time, call => 'https://www.sunnyportal.com/homemanager?t='.$time,
tag => "liveData" tag => "liveData",
}); state => $state,
fnaref => [ qw( extractLiveData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state,
data => $livedata
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -897,37 +907,25 @@ sub GetSetData { ## no cri
Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...}); Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...});
$newcycle = 1; $newcycle = 1;
return "$name|$exceed|$newcycle|$errstate|$getp|$setp"; return "$name|$exceed|$newcycle|$errstate|$getp|$setp";
} }
if ($livedata_content && $livedata_content !~ m/undefined/ix) {
extractLiveData ($hash,\@da,$livedata_content);
}
### Wetterdaten ### Wetterdaten
##################### #####################
my ($weatherdata,$weatherdata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/Dashboard/Weather', call => 'https://www.sunnyportal.com/Dashboard/Weather',
tag => "weatherData" tag => "weatherData",
}); state => $state,
fnaref => [ qw( extractWeatherData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $weatherdata
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($weatherdata_content && $weatherdata_content !~ m/undefined/ix) {
extractWeatherData ($hash,\@da,$weatherdata_content);
}
@ -938,57 +936,41 @@ sub GetSetData { ## no cri
my $tab = 1; # Tab 1 -> Tag , 2->Monat, 3->Jahr, 4->Gesamt my $tab = 1; # Tab 1 -> Tag , 2->Monat, 3->Jahr, 4->Gesamt
my %fields = ("Content-Type" => "application/json; charset=utf-8"); my %fields = ("Content-Type" => "application/json; charset=utf-8");
my $cont = qq{ {"tabNumber":$tab,"anchorTime":$anchort} }; my $cont = qq{ {"tabNumber":$tab,"anchorTime":$anchort} };
my ($balancedataday,$balancedataday_content) = _putData ({ name => $name,
ua => $ua,
call => 'https://www.sunnyportal.com/FixedPages/HoManEnergyRedesign.aspx/GetLegendWithValues',
fields => \%fields,
content => $cont,
tag => "balanceDayData"
});
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name,
errstate => $errstate,
state => $state,
data => $balancedataday
});
($errstate,$state) = _dispatchPost ({ name => $name,
ua => $ua,
call => 'https://www.sunnyportal.com/FixedPages/HoManEnergyRedesign.aspx/GetLegendWithValues',
tag => "balanceDayData",
state => $state,
fnaref => [ qw( extractStatisticData ) ],
fields => \%fields,
content => $cont,
addon => "Day",
daref => \@da
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($balancedataday_content && $balancedataday_content !~ m/undefined/ix) {
extractStatisticData ($hash,\@da,$balancedataday_content,"Day");
}
### Forecast Daten abrufen ### Forecast Daten abrufen
########################### ###########################
if($dl > 1) { if($dl > 1) {
my ($forecastdata,$forecastdata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData', call => 'https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData',
tag => "forecastData" tag => "forecastData",
}); state => $state,
fnaref => [ qw( extractPlantData extractForecastData extractConsumerData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $forecastdata
});
if($errstate) { if($errstate) {
$st = encode_base64 ($state, ""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($forecastdata_content && $forecastdata_content !~ m/undefined/ix) {
extractPlantData ($hash,\@da,$forecastdata_content);
extractForecastData ($hash,\@da,$forecastdata_content);
extractConsumerData ($hash,\@da,$forecastdata_content);
}
} }
@ -997,26 +979,19 @@ sub GetSetData { ## no cri
### Consumer Livedaten und historische Energiedaten ### Consumer Livedaten und historische Energiedaten
##################################################### #####################################################
if($dl > 2) { if($dl > 2) {
my ($consumerlivedata,$consumerlivedata_content) = _getData ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => 'https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues', call => 'https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues',
tag => "consumerLiveData" tag => "consumerLiveData",
}); state => $state,
fnaref => [ qw( extractConsumerLiveData ) ],
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name, addon => "",
errstate => $errstate, daref => \@da
state => $state, });
data => $consumerlivedata
});
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
} }
if ($consumerlivedata_content && $consumerlivedata_content !~ m/undefined/ix) {
extractConsumerLiveData ($hash,\@da,$consumerlivedata_content);
}
if($hash->{HELPER}{PLANTOID}) { if($hash->{HELPER}{PLANTOID}) {
@ -1044,15 +1019,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde"); Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde");
Log3 ($name, 5, "$name - Request consumer current day data string ->\n$ccdd"); Log3 ($name, 5, "$name - Request consumer current day data string ->\n$ccdd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccdd, call => $ccdd,
tag => "consumerDayData", tag => "consumerDayData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "day", addon => "day",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1063,15 +1038,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde"); Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde");
Log3 ($name, 5, "$name - Request consumer current month data string ->\n$ccmd"); Log3 ($name, 5, "$name - Request consumer current month data string ->\n$ccmd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccmd, call => $ccmd,
tag => "consumerMonthData", tag => "consumerMonthData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "month", addon => "month",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1082,15 +1057,15 @@ sub GetSetData { ## no cri
Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde"); Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde");
Log3 ($name, 5, "$name - Request consumer current year data string ->\n$ccyd"); Log3 ($name, 5, "$name - Request consumer current year data string ->\n$ccyd");
($errstate,$state) = _dispatch ({ name => $name, ($errstate,$state) = _dispatchGet ({ name => $name,
ua => $ua, ua => $ua,
call => $ccyd, call => $ccyd,
tag => "consumerYearData", tag => "consumerYearData",
state => $state, state => $state,
function => "extractConsumerHistData", fnaref => [ qw( extractConsumerHistData ) ],
addon => "year", addon => "year",
daref => \@da daref => \@da
}); });
if($errstate) { if($errstate) {
$st = encode_base64 ( $state,""); $st = encode_base64 ( $state,"");
return "$name|0|0|$errstate|$getp|$setp|$st"; return "$name|0|0|$errstate|$getp|$setp|$st";
@ -1198,16 +1173,16 @@ return ($state, $errstate);
} }
################################################################ ################################################################
# Dispatcher # Dispatcher GET
################################################################ ################################################################
sub _dispatch { sub _dispatchGet {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent my $ua = $paref->{ua}; # LWP Useragent
my $call = $paref->{call}; # Seitenaufruf zur Datenquelle my $call = $paref->{call}; # Seitenaufruf zur Datenquelle
my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten
my $state = $paref->{state}; my $state = $paref->{state};
my $fn = $paref->{function}; # aufzurufende Funktion zur Datenextraktion my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -1226,15 +1201,65 @@ sub _dispatch {
data => $data data => $data
}); });
return ($errstate,$state) if($errstate); return ($errstate,$state,$reread,$retry) if($errstate || $reread || $retry);
if ($data_cont && $data_cont !~ m/undefined/ix) { if ($data_cont && $data_cont !~ m/undefined/ix) {
my @func = @$fnref;
no strict "refs"; ## no critic 'NoStrict' no strict "refs"; ## no critic 'NoStrict'
&{$fn} ($hash,$daref,$data_cont,$fnaddon); for my $fn (@func) {
&{$fn} ($hash,$daref,$data_cont,$fnaddon);
}
use strict "refs"; use strict "refs";
} }
return ($errstate,$state); return ($errstate,$state,$reread,$retry);
}
################################################################
# Dispatcher POST
################################################################
sub _dispatchPost {
my $paref = shift;
my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent
my $call = $paref->{call}; # Seitenaufruf zur Datenquelle
my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten
my $state = $paref->{state};
my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fields = $paref->{fields}; # Referenz zum Hash der zu übertragenden PUSH Header
my $cont = $paref->{content}; # Content Daten für PUSH (String)
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name};
my ($reread,$retry,$errstate) = (0,0,0);
my ($data,$data_cont) = _postData ({ name => $name,
ua => $ua,
call => $call,
tag => $tag,
fields => $fields,
content => $cont,
});
($reread,$retry,$errstate,$state) = _analyzeData ({ name => $name,
errstate => $errstate,
state => $state,
data => $data
});
return ($errstate,$state) if($errstate);
if ($data_cont && $data_cont !~ m/undefined/ix) {
my @func = @$fnref;
no strict "refs"; ## no critic 'NoStrict'
for my $fn (@func) {
&{$fn} ($hash,$daref,$data_cont,$fnaddon);
}
use strict "refs";
}
return ($errstate,$state,$reread,$retry);
} }
################################################################ ################################################################
@ -1268,7 +1293,7 @@ return ($data,$dcont);
################################################################ ################################################################
# Standard Abruf Daten POST # Standard Abruf Daten POST
################################################################ ################################################################
sub _putData { sub _postData {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $ua = $paref->{ua}; my $ua = $paref->{ua};
@ -1692,7 +1717,7 @@ sub extractForecastData { ## no critic 'complexity'
push @$daref, "L4_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh"; push @$daref, "L4_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh";
# add WeatherId Helper to show weather icon # add WeatherId Helper to show weather icon
$hash->{HELPER}{"L4_".${time_str}."_WeatherId"} = int($fc_obj->{'WeatherId'}) if(defined $fc_obj->{'WeatherId'}); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "L4_".${time_str}."_WeatherId:".int($fc_obj->{'WeatherId'}) ], 1) if(defined $fc_obj->{'WeatherId'});
} }
if($time_str =~ /ThisHour/x && $dl >= 2) { if($time_str =~ /ThisHour/x && $dl >= 2) {
push @$daref, "L2_${time_str}_Time:". TimeAdjust($hash,$fc_obj->{'TimeStamp'}->{'DateTime'},$tkind); push @$daref, "L2_${time_str}_Time:". TimeAdjust($hash,$fc_obj->{'TimeStamp'}->{'DateTime'},$tkind);
@ -1702,7 +1727,7 @@ sub extractForecastData { ## no critic 'complexity'
push @$daref, "L2_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh"; push @$daref, "L2_${time_str}_Total:". (int($fc_obj->{'PvMeanPower'}->{'Amount'}) - int($fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600))." Wh";
# add WeatherId Helper to show weather icon # add WeatherId Helper to show weather icon
$hash->{HELPER}{"L2_".${time_str}."_WeatherId"} = int($fc_obj->{'WeatherId'}) if(defined $fc_obj->{'WeatherId'}); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "L2_".${time_str}."_WeatherId:".int($fc_obj->{'WeatherId'}) ], 1) if(defined $fc_obj->{'WeatherId'});
} }
} }
} }
@ -2485,7 +2510,7 @@ sub PortalAsHtml {
$di{0} = $pv{0} - $co{0}; $di{0} = $pv{0} - $co{0};
$is{0} = (ReadingsVal($name,"L2_ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef; $is{0} = (ReadingsVal($name,"L2_ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef;
$we{0} = $hash->{HELPER}{L2_ThisHour_WeatherId} if($weather); # für Wettericons $we{0} = $hash->{HELPER}{L2_ThisHour_WeatherId} if($weather); # für Wettericons
$we{0} = $we{0}?$we{0}:0; $we{0} = $we{0} ? $we{0} : 999;
if(AttrVal("global","language","EN") eq "DE") { if(AttrVal("global","language","EN") eq "DE") {
(undef,undef,undef,$t{0}) = ReadingsVal($name,"L2_ThisHour_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x; (undef,undef,undef,$t{0}) = ReadingsVal($name,"L2_ThisHour_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x;
@ -2558,7 +2583,7 @@ sub PortalAsHtml {
$is{$i} = (ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef; $is{$i} = (ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
$we{$i} = $hash->{HELPER}{"L4_NextHour".sprintf("%02d",$i)."_WeatherId"} if($weather); # für Wettericons $we{$i} = $hash->{HELPER}{"L4_NextHour".sprintf("%02d",$i)."_WeatherId"} if($weather); # für Wettericons
$we{$i} = $we{$i}?$we{$i}:0; $we{$i} = $we{$i} ? $we{$i} : 999;
if(AttrVal("global","language","EN") eq "DE") { if(AttrVal("global","language","EN") eq "DE") {
(undef,undef,undef,$t{$i}) = ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x; (undef,undef,undef,$t{$i}) = ReadingsVal($name,"L4_NextHour".sprintf("%02d",$i)."_Time",'0') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x;
@ -3010,7 +3035,8 @@ sub weather_icon {
'170' => 'weather_night_snow_rain', # Mond, Wolke mit Schnee (1 Flocke) - Nacht # neu '170' => 'weather_night_snow_rain', # Mond, Wolke mit Schnee (1 Flocke) - Nacht # neu
'171' => 'weather_night_snow_heavy', # Mond, Wolke mit Schnee (3 Flocken) - Nacht # neu '171' => 'weather_night_snow_heavy', # Mond, Wolke mit Schnee (3 Flocken) - Nacht # neu
'180' => 'weather_night_thunderstorm_light', # Wolke mit Blitz - Nacht # neu '180' => 'weather_night_thunderstorm_light', # Wolke mit Blitz - Nacht # neu
'181' => 'weather_night_thunderstorm' # Wolke mit Blitz und Starkregen - Nacht # neu '181' => 'weather_night_thunderstorm', # Wolke mit Blitz und Starkregen - Nacht # neu
'999' => '1px-spacer' # Dummy - keine Anzeige Wettericon # vorhanden
); );
return $weather_ids{$id} if(defined($weather_ids{$id})); return $weather_ids{$id} if(defined($weather_ids{$id}));