From ac230ae8da653e78e034e897421bef53e9cbc2a3 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sat, 22 Oct 2022 08:38:51 +0000 Subject: [PATCH] 76_SolarForecast.pm: contrib 0.70.7 git-svn-id: https://svn.fhem.de/fhem/trunk@26568 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/76_SolarForecast.pm | 135 ++++++++++++-------- 1 file changed, 81 insertions(+), 54 deletions(-) diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index c53f24f18..75d1f90e3 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -1,5 +1,5 @@ ######################################################################################################################## -# $Id: 76_SolarForecast.pm 21735 2022-10-19 20:53:24Z DS_Starter $ +# $Id: 76_SolarForecast.pm 21735 2022-10-22 20:53:24Z DS_Starter $ ######################################################################################################################### # 76_SolarForecast.pm # @@ -129,6 +129,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "0.70.7 "=> "22.10.2022 minor changes (Display is/whereabouts Solacast Requests, SolCast Forecast Quality, setup procedure) ", "0.70.6 "=> "19.10.2022 fix ___setLastAPIcallKeyData ", "0.70.5 "=> "18.10.2022 new hidden getter plantConfigCheck ", "0.70.4 "=> "16.10.2022 change attr historyHour to positive numbers, plantconfig check changed ", @@ -417,8 +418,6 @@ my %hqtxt = ( DE => qq{Bitte geben Sie mindestens eine Kombination Rooftop-ID/SolCast-API mit "set LINK roofIdentPair" an} }, mrt => { EN => qq{Please set the assignment String / Rooftop identification with "set LINK moduleRoofTops"}, DE => qq{Bitte setzen Sie die Zuordnung String / Rooftop Identifikation mit "set LINK moduleRoofTops"} }, - awd => { EN => qq{LINK is waiting for solar forecast data ...}, - DE => qq{LINK wartet auf Solarvorhersagedaten ...} }, cnsm => { EN => qq{Consumer}, DE => qq{Verbraucher} }, eiau => { EN => qq{Off/On}, @@ -449,12 +448,14 @@ my %hqtxt = ( DE => qq{nach} }, pstate => { EN => qq{Planning status: 
On: 
Off: }, DE => qq{Planungsstatus: 
Ein: 
Aus: } }, + awd => { EN => qq{LINK is waiting for solar forecast data ...

(The configuration can be checked with "set LINK plantConfiguration check".) }, + DE => qq{LINK wartet auf Solarvorhersagedaten ...

(Die Konfiguration kann mit "set LINK plantConfiguration check" geprüft werden.)} }, strok => { EN => qq{Congratulations 😊, the system configuration is error-free. Please observe any notes ().}, - DE => qq{Herzlichen Glückwunsch 😊, die Anlagenkonfiguration ist fehlerfrei. Bitte eventuelle Hinweise () beachten. } }, + DE => qq{Herzlichen Glückwunsch 😊, die Anlagenkonfiguration ist fehlerfrei. Bitte eventuelle Hinweise () beachten. } }, strwn => { EN => qq{Looks quite good 😐, the system configuration is basically OK. Please observe the warnings ().}, - DE => qq{Sieht ganz gut aus 😐, die Anlagenkonfiguration ist prinzipiell in Ordnung. Bitte beachten sie die Warnungen ().} }, + DE => qq{Sieht ganz gut aus 😐, die Anlagenkonfiguration ist prinzipiell in Ordnung. Bitte beachten sie die Warnungen ().} }, strnok => { EN => qq{Oh no 🙁, your string configuration is inconsistent.\nPlease check the settings !}, - DE => qq{Oh nein 🙁, Ihre String-Konfiguration ist inkonsistent.\nBitte überprüfen Sie die Einstellungen !} }, + DE => qq{Oh nein 🙁, Ihre String-Konfiguration ist inkonsistent.\nBitte überprüfen Sie die Einstellungen !} }, ); my %htitles = ( # Hash Hilfetexte (Mouse Over) @@ -1087,9 +1088,10 @@ sub _setroofIdentPair { ## no critic "not used" $data{$type}{$name}{solcastapi}{'?IdPair'}{'?'.$pk}{rtid} = $h->{rtid}; $data{$type}{$name}{solcastapi}{'?IdPair'}{'?'.$pk}{apikey} = $h->{apikey}; - writeDataToFile ($hash, "solcastapi", $scpicache.$name); # Cache File SolCast API Werte schreiben + writeDataToFile ($hash, "solcastapi", $scpicache.$name); # Cache File SolCast API Werte schreiben - my $msg = qq{The roofident pair "$pk" has been saved. You can check it by the "get $name solCastData" command.}; + my $msg = qq{The Roof identification pair "$pk" has been saved. }. + qq{Repeat the command if you want to save more Roof identification pairs.}; return $msg; } @@ -1119,13 +1121,14 @@ sub _setmoduleRoofTops { ## no critic "not used" } } - readingsSingleUpdate($hash, "moduleRoofTops", $arg, 1); + readingsSingleUpdate ($hash, "moduleRoofTops", $arg, 1); + writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + my $ret = createStringConfig ($hash); return $ret if($ret); - writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben - return; } @@ -1184,11 +1187,15 @@ sub _setinverterStrings { ## no critic "not used" } readingsSingleUpdate ($hash, "inverterStrings", $prop, 1); - writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben + writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben -return qq{NOTE: After setting or changing "inverterStrings" please check }. - qq{/ set all module parameter (e.g. moduleTiltAngle) again ! \n}. - qq{Use "set $name plantConfiguration check" to validate your Setup.}; + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + + my $ret = qq{NOTE: After setting or changing "inverterStrings" please check }. + qq{/ set all module parameter (e.g. moduleTiltAngle) again ! \n}. + qq{Use "set $name plantConfiguration check" to validate your Setup.}; + +return $ret; } ################################################################ @@ -1352,12 +1359,13 @@ sub _setmodulePeakString { ## no critic "not used" } } - readingsSingleUpdate($hash, "modulePeakString", $arg, 1); + readingsSingleUpdate ($hash, "modulePeakString", $arg, 1); + writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben + + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett my $ret = createStringConfig ($hash); return $ret if($ret); - - writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } @@ -1385,13 +1393,14 @@ sub _setmoduleTiltAngle { ## no critic "not used" } } - readingsSingleUpdate($hash, "moduleTiltAngle", $arg, 1); + readingsSingleUpdate ($hash, "moduleTiltAngle", $arg, 1); + writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben + + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett my $ret = createStringConfig ($hash); return $ret if($ret); - writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben - return; } @@ -1418,12 +1427,13 @@ sub _setmoduleDirection { ## no critic "not used" } } - readingsSingleUpdate($hash, "moduleDirection", $arg, 1); + readingsSingleUpdate ($hash, "moduleDirection", $arg, 1); + writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + my $ret = createStringConfig ($hash); return $ret if($ret); - - writeDataToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } @@ -1442,11 +1452,13 @@ sub _setplantConfiguration { ## no critic "not used" $arg = 'check' if (!$arg); - if($arg eq "check") { - $err = getClHash($hash); + if($arg eq "check") { my $out = checkPlantConfig ($hash); $out = qq{$out}; + ## asynchrone Ausgabe + ####################### + #$err = getClHash($hash); #$paref->{out} = $out; #InternalTimer(gettimeofday()+3, "FHEM::SolarForecast::__plantCfgAsynchOut", $paref, 0); @@ -2939,6 +2951,7 @@ sub createStringConfig { ## no critic "not used" my $type = $hash->{TYPE}; delete $data{$type}{$name}{strings}; # Stringhash zurücksetzen + my @istrings = split ",", ReadingsVal ($name, 'inverterStrings', ''); # Stringbezeichner $data{$type}{$name}{current}{allstringscount} = scalar @istrings; # Anzahl der Anlagenstrings @@ -2946,7 +2959,7 @@ sub createStringConfig { ## no critic "not used" return qq{Define all used strings with command "set $name inverterStrings" first.}; } - my $peak = ReadingsVal ($name, "modulePeakString", ""); # kWp für jeden Stringbezeichner + my $peak = ReadingsVal ($name, 'modulePeakString', ''); # kWp für jeden Stringbezeichner return qq{Please complete command "set $name modulePeakString".} if(!$peak); my ($aa,$ha) = parseParams ($peak); @@ -2963,7 +2976,7 @@ sub createStringConfig { ## no critic "not used" } if (!isSolCastUsed ($hash)) { # DWD Strahlungsquelle - my $tilt = ReadingsVal ($name, "moduleTiltAngle", ""); # Modul Neigungswinkel für jeden Stringbezeichner + my $tilt = ReadingsVal ($name, 'moduleTiltAngle', ''); # Modul Neigungswinkel für jeden Stringbezeichner return qq{Please complete command "set $name moduleTiltAngle".} if(!$tilt); my ($at,$ht) = parseParams ($tilt); @@ -2977,7 +2990,7 @@ sub createStringConfig { ## no critic "not used" } } - my $dir = ReadingsVal ($name, "moduleDirection", ""); # Modul Ausrichtung für jeden Stringbezeichner + my $dir = ReadingsVal ($name, 'moduleDirection', ''); # Modul Ausrichtung für jeden Stringbezeichner return qq{Please complete command "set $name moduleDirection".} if(!$dir); my ($ad,$hd) = parseParams ($dir); @@ -2992,7 +3005,7 @@ sub createStringConfig { ## no critic "not used" } } else { # SolCast-API Strahlungsquelle - my $mrt = ReadingsVal ($name, "moduleRoofTops", ""); # RoofTop Konfiguration -> Zuordnung + my $mrt = ReadingsVal ($name, 'moduleRoofTops', ''); # RoofTop Konfiguration -> Zuordnung return qq{Please complete command "set $name moduleRoofTops".} if(!$mrt); my ($ad,$hd) = parseParams ($mrt); @@ -5986,7 +5999,7 @@ sub entryGraphic { # Setup Vollständigkeit/disabled prüfen ######################################### - my $incomplete = _checkSetupComplete ($hash); + my $incomplete = _checkSetupNotComplete ($hash); return $incomplete if($incomplete); # Kontext des SolarForecast-Devices speichern für Refresh @@ -6156,7 +6169,7 @@ return $ret; ################################################################ # Vollständigkeit Setup prüfen ################################################################ -sub _checkSetupComplete { +sub _checkSetupNotComplete { my $hash = shift; my $ret = q{}; @@ -6215,7 +6228,7 @@ sub _checkSetupComplete { elsif(!$is) { $ret .= $hqtxt{ist}{$lang}; } - elsif(!$peaks) { + elsif(!$peaks) { $ret .= $hqtxt{mps}{$lang}; } elsif(!$rip && isSolCastUsed ($hash)) { # Verwendung SolCast API @@ -6231,13 +6244,14 @@ sub _checkSetupComplete { $ret .= $hqtxt{mta}{$lang}; } elsif(!defined $pv0) { - $ret .= $hqtxt{awd}{$lang}; + $ret .= $hqtxt{awd}{$lang}; } $ret .= ""; $ret .= ""; $ret .= ""; $ret =~ s/LINK/$link/gxs; + return $ret; } @@ -6370,11 +6384,8 @@ sub _graphicHeader { $api .= '  ('; $api .= SolCastAPIVal ($hash, '?All', '?All', 'todayDoneAPIrequests', 0); $api .= '/'; - $api .= SolCastAPIVal ($hash, '?All', '?All', 'todayRemainingAPIrequests', 0); + $api .= SolCastAPIVal ($hash, '?All', '?All', 'todayRemainingAPIrequests', 50); $api .= ')'; - - - } ## Anlagen Check-Icon @@ -6426,9 +6437,16 @@ sub _graphicHeader { ###################### my $pcqicon; + if (isSolCastUsed ($hash)) { + $pcqicon = $pcq < 10 ? FW_makeImage('10px-kreis-rot.png', $pvcanz) : + $pcq < 20 ? FW_makeImage('10px-kreis-gelb.png', $pvcanz) : + FW_makeImage('10px-kreis-gruen.png', $pvcanz); + } + else { $pcqicon = $pcq < 3 ? FW_makeImage('10px-kreis-rot.png', $pvcanz) : $pcq < 5 ? FW_makeImage('10px-kreis-gelb.png', $pvcanz) : - FW_makeImage('10px-kreis-gruen.png', $pvcanz); + FW_makeImage('10px-kreis-gruen.png', $pvcanz); + } $pcqicon = "-" if(!$pvfc00 || $pcq == -1); @@ -8788,8 +8806,7 @@ sub checkPlantConfig { my $name = $hash->{NAME}; my $type = $hash->{TYPE}; - my $lang = AttrVal ("global", 'language', 'EN'); - my $stch = $data{$type}{$name}{strings}; + my $lang = AttrVal ("global", 'language', 'EN'); my $cf = 0; # config fault: 1 -> Konfig fehlerhaft, 0 -> Konfig ok my $wn = 0; # Warnung wenn 1 @@ -8808,9 +8825,9 @@ sub checkPlantConfig { my $string = shift; my $ret; - for my $key (sort keys %{$stch->{$string}}) { + for my $key (sort keys %{$data{$type}{$name}{strings}{$string}}) { $ret .= ", " if($ret); - $ret .= $key.": ".$stch->{$string}{$key}; + $ret .= $key.": ".$data{$type}{$name}{strings}{$string}{$key}; } return $ret; @@ -8827,11 +8844,11 @@ sub checkPlantConfig { $result->{'String Configuration'}{fault} = 1; } - for my $sn (sort keys %{$stch}) { + for my $sn (sort keys %{$data{$type}{$name}{strings}}) { my $sp = $sn." => ".$sub->($sn)."
"; $result->{'String Configuration'}{note} .= $sn." => ".$sub->($sn)."
"; - if ($stch->{$sn}{peak} >= 500) { + if ($data{$type}{$name}{strings}{$sn}{peak} >= 500) { $result->{'String Configuration'}{result} .= qq{The peak value of string "$sn" is very high. }; $result->{'String Configuration'}{result} .= qq{It seems to be given in Wp instead of kWp.
}; $result->{'String Configuration'}{state} = $warn; @@ -8957,6 +8974,14 @@ sub checkPlantConfig { my $osi = AttrVal ($name, 'optimizeSolCastAPIreqInterval', 0); my $pcf = ReadingsVal ($name, 'pvCorrectionFactor_Auto', ''); + my $lam = SolCastAPIVal ($hash, '?All', '?All', 'response_message', 'success'); + + if (!$pcf || $pcf ne 'on') { + $result->{'Common Settings'}{state} = $info; + $result->{'Common Settings'}{result} .= qq{pvCorrectionFactor_Auto is set to "$pcf"
}; + $result->{'Common Settings'}{note} .= qq{set pvCorrectionFactor_Auto to "on" is recommended if the SolCast efficiency factor is already adjusted.
}; + } + if ($cfd eq '' || $cfd != 0) { $result->{'Common Settings'}{state} = $warn; $result->{'Common Settings'}{result} .= qq{Attribute cloudFactorDamping is set to "$cfd"
}; @@ -8971,12 +8996,6 @@ sub checkPlantConfig { $result->{'Common Settings'}{warn} = 1; } - if (!$pcf || $pcf ne 'on') { - $result->{'Common Settings'}{state} = $info; - $result->{'Common Settings'}{result} .= qq{pvCorrectionFactor_Auto is set to "$pcf"
}; - $result->{'Common Settings'}{note} .= qq{set pvCorrectionFactor_Auto to "on" is recommended if the SolCast efficiency factor is already adjusted.
}; - } - if (!$osi) { $result->{'Common Settings'}{state} = $warn; $result->{'Common Settings'}{result} .= qq{Attribute optimizeSolCastAPIreqInterval is set to "$osi"
}; @@ -8984,7 +9003,14 @@ sub checkPlantConfig { $result->{'Common Settings'}{warn} = 1; } - if(!$result->{'Common Settings'}{warn} && !$result->{'Common Settings'}{info}) { + if($lam ne 'success' ) { + $result->{'Common Settings'}{state} = $nok; + $result->{'Common Settings'}{result} .= qq{The last message from SolCast API is "$lam".
}; + $result->{'Common Settings'}{note} .= qq{Check the validity of your API key and Rooftop indentificators.
}; + $result->{'Common Settings'}{fault} = 1; + } + + if(!$result->{'Common Settings'}{fault} && !$result->{'Common Settings'}{warn} && !$result->{'Common Settings'}{info}) { $result->{'Common Settings'}{result} = "fullfilled"; $result->{'Common Settings'}{note} .= qq{checked parameter:
}; $result->{'Common Settings'}{note} .= qq{cloudFactorDamping, rainFactorDamping, optimizeSolCastAPIreqInterval
}; @@ -9913,7 +9939,8 @@ return $def; # SolCastAPIVal ($hash, '?All', '?All', 'todayDoneAPIcalls', $def) - heute ausgeführte API Calls (hat u.U. mehrere Requests) # SolCastAPIVal ($hash, '?All', '?All', 'todayRemaingAPIcalls', $def) - heute noch mögliche API Calls (ungl. Requests !) # SolCastAPIVal ($hash, '?All', '?All', 'solCastAPIcallMultiplier',$def) - APIcalls = APIRequests * solCastAPIcallMultiplier -# SolCastAPIVal ($hash, '?All', '?All', 'currentAPIinterval', $def) - aktuelles API Request Intervall +# SolCastAPIVal ($hash, '?All', '?All', 'currentAPIinterval', $def) - aktuelles API Request Intervall +# SolCastAPIVal ($hash, '?All', '?All', 'response_message', $def) - letzte SolCast API Antwort # SolCastAPIVal ($hash, '?IdPair', '?', 'rtid', $def) - RoofTop-ID, = Paarschlüssel # SolCastAPIVal ($hash, '?IdPair', '?', 'apikey', $def) - API-Key, = Paarschlüssel # @@ -10515,7 +10542,7 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen Der Abruf jedes in SolCast Rooftop Sites angelegten Rooftops ist mit der Angabe eines Paares Rooftop-ID und API-Key zu identifizieren.
Der Schlüssel <pk> kennzeichnet eindeutig ein verbundenes Paar Rooftop-ID / API-Key. Es können beliebig viele - Paare nacheinander angelegt werden. In dem Fall ist jeweils ein neuer Name für "<pk>" zu verwenden. + Paare nacheinander angelegt werden. In dem Fall ist jeweils ein neuer Name für "<pk>" zu verwenden.

Der Schlüssel <pk> wird im Setter moduleRoofTops der abzurufenden