mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 09:16:53 +00:00
55_DWD_OpenData.pm: contrib MOSMIX S version with timeout
git-svn-id: https://svn.fhem.de/fhem/trunk@28550 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
b8b6027256
commit
e26b2a5c0c
@ -920,6 +920,11 @@ sub Attr {
|
||||
return "invalid value for forecastResolution (possible values are 1, 3 and 6)";
|
||||
}
|
||||
}
|
||||
when ("timeout") {
|
||||
unless ($value =~ /^[0-9]+$/x) {
|
||||
return qq{invalid value for timeout. Use only figures 0-9!};
|
||||
}
|
||||
}
|
||||
when ("forecastStation") {
|
||||
my $oldForecastStation = ::AttrVal($name, 'forecastStation', undef);
|
||||
if ($::init_done && defined($oldForecastStation) && $oldForecastStation ne $value) {
|
||||
@ -1599,7 +1604,8 @@ sub GetForecast {
|
||||
# kill old blocking call
|
||||
::BlockingKill($hash->{".forecastBlockingCall"});
|
||||
}
|
||||
$hash->{".forecastBlockingCall"} = ::BlockingCall("DWD_OpenData::GetForecastStart", $hash, "DWD_OpenData::GetForecastFinish", 30, "DWD_OpenData::GetForecastAbort", $hash);
|
||||
my $to = ::AttrVal($name, 'timeout', 60);
|
||||
$hash->{".forecastBlockingCall"} = ::BlockingCall("DWD_OpenData::GetForecastStart", $hash, "DWD_OpenData::GetForecastFinish", $to, "DWD_OpenData::GetForecastAbort", $hash);
|
||||
|
||||
$hash->{forecastUpdating} = time();
|
||||
|
||||
@ -2250,7 +2256,8 @@ sub GetAlerts {
|
||||
# kill old blocking call
|
||||
::BlockingKill($hash->{".alertsBlockingCall".$communeUnion});
|
||||
}
|
||||
$hash->{".alertsBlockingCall".$communeUnion} = ::BlockingCall("DWD_OpenData::GetAlertsStart", $hash, "DWD_OpenData::GetAlertsFinish", 60, "DWD_OpenData::GetAlertsAbort", $hash);
|
||||
my $to = ::AttrVal($name, 'timeout', 60);
|
||||
$hash->{".alertsBlockingCall".$communeUnion} = ::BlockingCall("DWD_OpenData::GetAlertsStart", $hash, "DWD_OpenData::GetAlertsFinish", $to, "DWD_OpenData::GetAlertsAbort", $hash);
|
||||
|
||||
$alertsUpdating[$communeUnion] = time();
|
||||
|
||||
@ -2788,7 +2795,7 @@ sub DWD_OpenData_Initialize {
|
||||
$hash->{AttrList} = 'disable:0,1 '
|
||||
.'forecastStation forecastDays forecastProperties forecastResolution:1,3,6 forecastWW2Text:0,1 forecastPruning:0,1 '
|
||||
.'forecastDataPrecision:low,high alertArea alertLanguage:DE,EN alertExcludeEvents '
|
||||
.'timezone '
|
||||
.'timezone timeout '
|
||||
.$readingFnAttributes;
|
||||
}
|
||||
|
||||
@ -3011,6 +3018,9 @@ sub DWD_OpenData_Initialize {
|
||||
<li>disable {0|1}, default: 0<br>
|
||||
Disable fetching data.
|
||||
</li><br>
|
||||
<li>timeout {Integer}, default: 60<br>
|
||||
Timeout for getting data from DWD in seconds.
|
||||
</li><br>
|
||||
<li>timezone <tz>, default: OS dependent<br>
|
||||
<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">IANA TZ string</a> for date and time readings (e.g. "Europe/Berlin"), can be used to assume the perspective of a station that is in a different timezone or if your OS timezone settings do not match your local timezone. Alternatively you may use <code>tzselect</code> on the Linux command line to find a valid timezone string.
|
||||
</li><br>
|
||||
|
@ -158,9 +158,13 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.16.2" => "19.02.2024 minor changes, R101 -> RR1c, totalrain instead of weatherrainprob, delete wrp r101 ".
|
||||
"1.16.3" => "24.02.2024 store pvcorrf, quality, pvrlsum, pvfcsum, dnumsum with value <sunalt2bin>.<cloud2bin> in pvCircular ".
|
||||
"get pvcorrf / quality from neff in combination with sun altitude (CircularSunCloudkorrVal) ".
|
||||
"delete CircularCloudkorrVal, show sun position in beamgrafic weather mouse over ",
|
||||
"1.16.2" => "22.02.2024 minor changes, R101 -> RR1c, totalrain instead of weatherrainprob, delete wrp r101 ".
|
||||
"delete wrp from circular & airaw, remove rain2bin, __getDWDSolarData: change \$runh, ".
|
||||
"fix Illegal division by zero Forum: https://forum.fhem.de/index.php?msg=1304009 ",
|
||||
"fix Illegal division by zero Forum: https://forum.fhem.de/index.php?msg=1304009 ".
|
||||
"DWD API: check age of Rad1h data, store pvcorrf of sunalt with value 200+x in pvCircular ",
|
||||
"1.16.1" => "14.02.2024 ___isCatFiltered: add eval for regex evaluation, add sunaz to AI raw and get, fillup AI hash ",
|
||||
"1.16.0" => "12.02.2024 new command get dwdCatalog ",
|
||||
"1.15.5" => "11.02.2024 change forecastQualities output, new limits for 'accurate' and 'spreaded' results from AI ".
|
||||
@ -338,10 +342,10 @@ my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx";
|
||||
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
||||
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
||||
my $aistdudef = 1095; # default Haltezeit KI Raw Daten (Tage)
|
||||
my $aiSpreadUpLim = 150; # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiSpreadLowLim = 50; # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiAccUpLim = 170; # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiAccLowLim = 30; # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiSpreadUpLim = 130; # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiSpreadLowLim = 70; # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiAccUpLim = 150; # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiAccLowLim = 50; # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
|
||||
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
|
||||
my @dweattrmust = qw(TTT Neff RR1c ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||
@ -693,6 +697,8 @@ my %htitles = (
|
||||
DE => qq{Ein -> kein off-Kommando definiert!} },
|
||||
natc => { EN => qq{automatic cycle:},
|
||||
DE => qq{automatischer Zyklus:} },
|
||||
predtime => { EN => qq{Prediction time Radiation data:},
|
||||
DE => qq{Vorhersagezeitpunkt Strahlungsdaten:} },
|
||||
upd => { EN => qq{Click for update},
|
||||
DE => qq{Klick für Update} },
|
||||
on => { EN => qq{switched on},
|
||||
@ -703,6 +709,12 @@ my %htitles = (
|
||||
DE => qq{undefiniert} },
|
||||
dela => { EN => qq{delayed},
|
||||
DE => qq{verzoegert} },
|
||||
azimuth => { EN => qq{Azimuth},
|
||||
DE => qq{Azimut} },
|
||||
elevatio => { EN => qq{Elevation},
|
||||
DE => qq{Höhe} },
|
||||
sunpos => { EN => qq{Sun position},
|
||||
DE => qq{Sonnenstand} },
|
||||
conrec => { EN => qq{Current time is within the consumption planning},
|
||||
DE => qq{Aktuelle Zeit liegt innerhalb der Verbrauchsplanung} },
|
||||
conrecba => { EN => qq{Current time is within the consumption planning, Priority charging Battery is active},
|
||||
@ -745,6 +757,8 @@ my %htitles = (
|
||||
DE => qq{Planungsstatus: <pstate>\nInfo: <supplmnt>\n\nEin: <start>\nAus: <stop>\nverbleibende Sperrzeit: <RLT> Sekunden} },
|
||||
ainuse => { EN => qq{AI Perl module is installed, but the AI support is not used.\nRun 'set <NAME> plantConfiguration check' for hints.},
|
||||
DE => qq{KI Perl Modul ist installiert, aber die KI Unterstützung wird nicht verwendet.\nPrüfen sie 'set <NAME> plantConfiguration check' für Hinweise.} },
|
||||
arsrad2o => { EN => qq{API query successful but the radiation values are outdated.\nCheck the plant with 'set <NAME> plantConfiguration check'.},
|
||||
DE => qq{API Abfrage erfolgreich aber die Strahlungswerte sind veraltet.\nPrüfen sie die Anlage mit 'set <NAME> plantConfiguration check'.} },
|
||||
);
|
||||
|
||||
my %weather_ids = (
|
||||
@ -962,7 +976,6 @@ sub Initialize {
|
||||
"affectConsForecastIdentWeekdays:1,0 ".
|
||||
"affectConsForecastInPlanning:1,0 ".
|
||||
"affectMaxDayVariance ".
|
||||
"affectNumHistDays:obsolete ".
|
||||
"affectSolCastPercentile:select,10,50,90 ".
|
||||
"consumerLegend:none,icon_top,icon_bottom,text_top,text_bottom ".
|
||||
"consumerAdviceIcon ".
|
||||
@ -2531,7 +2544,11 @@ return $getlist;
|
||||
sub _getRoofTopData {
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $hash->{NAME};
|
||||
my $name = $paref->{name};
|
||||
my $type = $paref->{type};
|
||||
|
||||
delete $data{$type}{$name}{current}{dwdRad1hAge};
|
||||
delete $data{$type}{$name}{current}{dwdRad1hAgeTS};
|
||||
|
||||
if($hash->{MODEL} eq 'SolCastAPI') {
|
||||
__getSolCastData ($paref);
|
||||
@ -3372,6 +3389,10 @@ sub __getDWDSolarData {
|
||||
$data{$type}{$name}{solcastapi}{'?All'}{'?All'}{lastretrieval_timestamp} = $t;
|
||||
$data{$type}{$name}{solcastapi}{'?All'}{'?All'}{todayDoneAPIrequests} += 1;
|
||||
|
||||
my $fctime = ReadingsVal ($raname, 'fc_time', '-');
|
||||
$data{$type}{$name}{current}{dwdRad1hAge} = $fctime;
|
||||
$data{$type}{$name}{current}{dwdRad1hAgeTS} = timestringToTimestamp ($fctime);
|
||||
|
||||
debugLog ($paref, "apiCall", "DWD API - collect DWD Radiation data with start >$stime<- device: $raname =>");
|
||||
|
||||
for my $num (0..47) {
|
||||
@ -3381,7 +3402,6 @@ sub __getDWDSolarData {
|
||||
|
||||
next if($fh == 24);
|
||||
|
||||
my $stime = ReadingsVal ($raname, "fc${fd}_${runh}_time", 0);
|
||||
my $rad = ReadingsVal ($raname, "fc${fd}_${runh}_Rad1h", undef);
|
||||
|
||||
if (!defined $rad) {
|
||||
@ -4608,17 +4628,16 @@ sub Attr {
|
||||
my ($do,$val, $err);
|
||||
|
||||
### nicht mehr benötigte Daten löschen - Bereich kann später wieder raus !!
|
||||
##########################################################################################
|
||||
if ($cmd eq 'set' && $aName eq 'affectNumHistDays') { # 30.01.2024
|
||||
if (!$init_done) {
|
||||
return qq{Device "$name" -> The attribute '$aName' is obsolete and will be deleted soon. Please press "save config" when restart is finished.};
|
||||
}
|
||||
else {
|
||||
return qq{The attribute '$aName' is obsolete and will be deleted soon.};
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################################
|
||||
######################################################################################################################
|
||||
#if ($cmd eq 'set' && $aName eq 'affectNumHistDays') {
|
||||
# if (!$init_done) {
|
||||
# return qq{Device "$name" -> The attribute '$aName' is obsolete and will be deleted soon. Please press "save config" when restart is finished.};
|
||||
# }
|
||||
# else {
|
||||
# return qq{The attribute '$aName' is obsolete and will be deleted soon.};
|
||||
# }
|
||||
#}
|
||||
######################################################################################################################
|
||||
|
||||
if ($aName eq 'disable') {
|
||||
if($cmd eq 'set') {
|
||||
@ -4681,7 +4700,7 @@ sub Attr {
|
||||
if ($cmd eq 'set') {
|
||||
if ($aName eq 'ctrlInterval' || $aName eq 'ctrlBackupFilesKeep' || $aName eq 'ctrlAIdataStorageDuration') {
|
||||
unless ($aVal =~ /^[0-9]+$/x) {
|
||||
return qq{The value for $aName is not valid. Use only figures 0-9 !};
|
||||
return qq{Invalid value for $aName. Use only figures 0-9!};
|
||||
}
|
||||
}
|
||||
|
||||
@ -5620,7 +5639,6 @@ sub centralTask {
|
||||
my $sabin = sunalt2bin ($alt);
|
||||
$data{$type}{$name}{aidectree}{airaw}{$idx}{sunalt} = $sabin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
my $sunaz = AiRawdataVal ($hash, $idx, 'sunaz', '');
|
||||
@ -5638,7 +5656,6 @@ sub centralTask {
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
Log3 ($name, 1, "$name - add sunaz - idx: $idx, hod: $h, err: $@");
|
||||
delete $data{$type}{$name}{aidectree}{airaw}{$idx};
|
||||
}
|
||||
else {
|
||||
@ -5673,15 +5690,94 @@ sub centralTask {
|
||||
}
|
||||
|
||||
## nicht-Bin Werte löschen / wrp löschen
|
||||
my $ra = '0|00|05|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100|percentile|simple';
|
||||
my $ra = '0|00|05|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100|.*\..*|simple';
|
||||
|
||||
for my $hod (keys %{$data{$type}{$name}{circular}}) { # 30.01.2024
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvcorrf}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
}
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range} if(!defined $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range});
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{quality}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
}
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range} if(!defined $data{$type}{$name}{circular}{$hod}{quality}{$range});
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvrlsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvfcsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{dnumsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{dnumsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $wp (keys %{$data{$type}{$name}{circular}{$hod}}) { # 19.02.204
|
||||
@ -5689,6 +5785,7 @@ sub centralTask {
|
||||
delete $data{$type}{$name}{circular}{$hod}{$wp};
|
||||
}
|
||||
}
|
||||
|
||||
## currentWeatherDev in Attr umsetzen
|
||||
my $cwd = ReadingsVal ($name, 'currentWeatherDev', ''); # 30.01.2024
|
||||
if ($cwd) {
|
||||
@ -6583,17 +6680,19 @@ sub _transferAPIRadiationValues {
|
||||
}
|
||||
|
||||
if($fd == 0 && $fh1) {
|
||||
$paref->{nhour} = sprintf "%02d", $fh1;
|
||||
$paref->{nhour} = sprintf "%02d", $fh1;
|
||||
|
||||
$paref->{calcpv} = $pvfc;
|
||||
$paref->{val} = $pvfc;
|
||||
$paref->{histname} = 'pvfc';
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{rad1h} = $rad1h;
|
||||
$paref->{val} = $rad1h;
|
||||
$paref->{histname} = 'radiation';
|
||||
setPVhistory ($paref);
|
||||
|
||||
delete $paref->{histname};
|
||||
delete $paref->{val};
|
||||
delete $paref->{nhour};
|
||||
}
|
||||
}
|
||||
|
||||
@ -6769,44 +6868,51 @@ sub ___readCandQ {
|
||||
my $cc = $paref->{cloudcover};
|
||||
|
||||
my ($acu, $aln) = isAutoCorrUsed ($name); # Autokorrekturmodus
|
||||
my $hc = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor
|
||||
my $sunalt = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), 'sunalt', ''); # Sun Altitude
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
my $hc = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor
|
||||
my $hq = '-'; # keine Qualität definiert
|
||||
my $crang = 'simple';
|
||||
|
||||
delete $data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange};
|
||||
|
||||
if ($acu =~ /on_complex/xs) { # Autokorrektur complex soll genutzt werden
|
||||
my $range = cloud2bin ($cc); # Range errechnen
|
||||
($hc, $hq) = CircularAutokorrVal ($hash, sprintf("%02d",$fh1), $range, undef); # Korrekturfaktor/Qualität der Stunde des Tages (complex)
|
||||
$crang = cloud2bin ($cc); # Range errechnen
|
||||
($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, $crang, undef); # Korrekturfaktor/Qualität der Stunde des Tages (complex)
|
||||
$hq //= '-';
|
||||
$hc //= 1; # Korrekturfaktor = 1 (keine Korrektur) # keine Qualität definiert
|
||||
$hc = 1 if(1 * $hc == 0); # 0.0-Werte ignorieren (Schleifengefahr)
|
||||
|
||||
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange} = $range;
|
||||
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange} = $crang;
|
||||
}
|
||||
elsif ($acu =~ /on_simple/xs) {
|
||||
($hc, $hq) = CircularAutokorrVal ($hash, sprintf("%02d",$fh1), 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
$hq //= '-';
|
||||
$hc //= 1; # Korrekturfaktor = 1
|
||||
$hc = 1 if(1 * $hc == 0); # 0.0-Werte ignorieren (Schleifengefahr)
|
||||
}
|
||||
else { # keine Autokorrektur
|
||||
($hc, $hq) = CircularAutokorrVal ($hash, sprintf("%02d",$fh1), 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
$hq //= '-';
|
||||
$hc = 1;
|
||||
}
|
||||
|
||||
$hc = sprintf "%.2f", $hc;
|
||||
|
||||
debugLog ($paref, 'pvCorrection', "___readCandQ - fd: $fd, hod: ".sprintf("%02d",$fh1).", Sun Altitude Bin: $sabin, Cloud range: $crang, corrf: $hc, quality: $hq");
|
||||
|
||||
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{pvcorrf} = $hc."/".$hq;
|
||||
|
||||
if($fd == 0 && $fh1) {
|
||||
$paref->{pvcorrf} = $hc."/".$hq;
|
||||
$paref->{val} = $hc.'/'.$hq;
|
||||
$paref->{nhour} = sprintf "%02d", $fh1;
|
||||
$paref->{histname} = 'pvcorrfactor';
|
||||
|
||||
setPVhistory ($paref);
|
||||
|
||||
delete $paref->{histname};
|
||||
delete $paref->{val};
|
||||
delete $paref->{nhour};
|
||||
}
|
||||
|
||||
return ($hc, $hq);
|
||||
@ -6950,13 +7056,15 @@ sub _transferInverterValues {
|
||||
|
||||
my $ethishour;
|
||||
if (!$histetot) { # etotal der aktuelle Stunde gesetzt ?
|
||||
$paref->{etotal} = $etotal;
|
||||
$paref->{nhour} = sprintf("%02d",$nhour);
|
||||
$paref->{val} = $etotal;
|
||||
$paref->{nhour} = sprintf "%02d", $nhour;
|
||||
$paref->{histname} = 'etotal';
|
||||
|
||||
setPVhistory ($paref);
|
||||
|
||||
delete $paref->{histname};
|
||||
delete $paref->{nhour};
|
||||
delete $paref->{val};
|
||||
|
||||
my $etot = CurrentVal ($hash, "etotal", $etotal);
|
||||
$ethishour = int ($etotal - $etot);
|
||||
@ -9521,25 +9629,29 @@ sub _calcCaQcomplex {
|
||||
return;
|
||||
}
|
||||
|
||||
my $chwcc = HistoryVal ($hash, $day, sprintf("%02d",$h), 'wcc', 0); # Wolkenbedeckung Heute & abgefragte Stunde
|
||||
my $range = cloud2bin ($chwcc);
|
||||
my $chwcc = HistoryVal ($hash, $day, sprintf("%02d",$h), 'wcc', 0); # Wolkenbedeckung Heute & abgefragte Stunde
|
||||
my $sunalt = HistoryVal ($hash, $day, sprintf("%02d",$h), 'sunalt', 0); # Sonne Altitude
|
||||
my $crang = cloud2bin ($chwcc);
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
|
||||
$paref->{pvrl} = $pvrl;
|
||||
$paref->{pvfc} = $pvfc;
|
||||
$paref->{range} = $range;
|
||||
$paref->{crang} = $crang;
|
||||
$paref->{sabin} = $sabin;
|
||||
$paref->{calc} = 'Complex';
|
||||
|
||||
my ($oldfac, $factor, $dnum) = __calcNewFactor ($paref);
|
||||
|
||||
delete $paref->{pvrl};
|
||||
delete $paref->{pvfc};
|
||||
delete $paref->{range};
|
||||
delete $paref->{crang};
|
||||
delete $paref->{sabin};
|
||||
delete $paref->{calc};
|
||||
|
||||
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_cloudcover', 'done');
|
||||
|
||||
if ($acu =~ /on_complex/xs) {
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, cloudiness range: $range, days in range: $dnum)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Sun Alt range: $sabin, Cloud range: $crang, days in range: $dnum)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h).'_autocalc', 'done');
|
||||
}
|
||||
|
||||
@ -9581,16 +9693,21 @@ sub _calcCaQsimple {
|
||||
return;
|
||||
}
|
||||
|
||||
$paref->{pvrl} = $pvrl;
|
||||
$paref->{pvfc} = $pvfc;
|
||||
$paref->{range} = 'simple';
|
||||
$paref->{calc} = 'Simple';
|
||||
my $sunalt = HistoryVal ($hash, $day, sprintf("%02d",$h), 'sunalt', 0); # Sonne Altitude
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
|
||||
$paref->{pvrl} = $pvrl;
|
||||
$paref->{pvfc} = $pvfc;
|
||||
$paref->{sabin} = $sabin;
|
||||
$paref->{crang} = 'simple';
|
||||
$paref->{calc} = 'Simple';
|
||||
|
||||
my ($oldfac, $factor, $dnum) = __calcNewFactor ($paref);
|
||||
|
||||
delete $paref->{pvrl};
|
||||
delete $paref->{pvfc};
|
||||
delete $paref->{range};
|
||||
delete $paref->{sabin};
|
||||
delete $paref->{crang};
|
||||
delete $paref->{calc};
|
||||
|
||||
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_apipercentil', 'done');
|
||||
@ -9614,7 +9731,8 @@ sub __calcNewFactor {
|
||||
my $type = $paref->{type};
|
||||
my $pvrl = $paref->{pvrl};
|
||||
my $pvfc = $paref->{pvfc};
|
||||
my $range = $paref->{range};
|
||||
my $crang = $paref->{crang};
|
||||
my $sabin = $paref->{sabin};
|
||||
my $h = $paref->{h};
|
||||
my $calc = $paref->{calc};
|
||||
|
||||
@ -9622,8 +9740,8 @@ sub __calcNewFactor {
|
||||
my $pvrlsum = $pvrl;
|
||||
my $pvfcsum = $pvfc;
|
||||
|
||||
my ($oldfac, $oldq) = CircularAutokorrVal ($hash, sprintf("%02d",$h), $range, 0); # bisher definierter Korrekturfaktor
|
||||
my ($pvhis, $fchis, $dnum) = CircularSumVal ($hash, sprintf("%02d",$h), $range, 0);
|
||||
my ($oldfac, $oldq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$h), $sabin, $crang, 0); # bisher definierter Korrekturfaktor / Qualität
|
||||
my ($pvhis, $fchis, $dnum) = CircularSumVal ($hash, sprintf("%02d",$h), $crang, 0);
|
||||
$oldfac = 1 if(1 * $oldfac == 0);
|
||||
|
||||
if ($dnum) { # Werte in History vorhanden -> haben Prio !
|
||||
@ -9644,10 +9762,6 @@ sub __calcNewFactor {
|
||||
$factor = sprintf "%.2f", ($pvrl / $pvfc);
|
||||
}
|
||||
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$range} = $pvrlsum; # PV Erzeugung Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$range} = $pvfcsum; # PV Prognose Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$range} = $dnum; # Anzahl aller historischen Tade dieser Range
|
||||
|
||||
my $maxvar = AttrVal ($name, 'affectMaxDayVariance', $defmaxvar); # max. Korrekturvarianz
|
||||
$factor = 1.00 if(1 * $factor == 0); # 0.00-Werte ignorieren (Schleifengefahr)
|
||||
|
||||
@ -9665,11 +9779,24 @@ sub __calcNewFactor {
|
||||
my $qual = __calcFcQuality ($pvfc, $pvrl); # Qualität der Vorhersage für die vergangene Stunde
|
||||
|
||||
debugLog ($paref, 'pvCorrection', "$calc Corrf -> start calculation correction factor for hour: $h");
|
||||
debugLog ($paref, 'pvCorrection', "$calc Corrf -> determined values - hour: $h, cloudiness range: $range, old corrf: $oldfac, new corrf: $factor, days: $dnum");
|
||||
debugLog ($paref, 'pvCorrection|saveData2Cache', "$calc Corrf -> write correction values into Circular - hour: $h, cloudiness range: $range, factor: $factor, quality: $qual");
|
||||
debugLog ($paref, 'pvCorrection', "$calc Corrf -> determined values - hour: $h, Sun Altitude range: $sabin, Cloud range: $crang, old factor: $oldfac, new factor: $factor, days: $dnum");
|
||||
debugLog ($paref, 'pvCorrection|saveData2Cache', "$calc Corrf -> write correction values into Circular - hour: $h, Sun Altitude range: $sabin, Cloud range: $crang, factor: $factor, quality: $qual");
|
||||
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$range} = $factor; # Korrekturfaktor der jeweiligen Stunde als Datenquelle eintragen
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$range} = $qual;
|
||||
if ($crang ne 'simple') {
|
||||
my $idx = $sabin.'.'.$crang; # value für pvcorrf Sonne Altitude
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$idx} = $pvrlsum; # PV Erzeugung Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$idx} = $pvfcsum; # PV Prognose Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$idx} = $dnum; # Anzahl aller historischen Tade dieser Range
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$idx} = $factor;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$idx} = $qual;
|
||||
}
|
||||
else {
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$crang} = $pvrlsum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$crang} = $pvfcsum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$crang} = $dnum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$crang} = $factor;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$crang} = $qual;
|
||||
}
|
||||
|
||||
return ($oldfac, $factor, $dnum);
|
||||
}
|
||||
@ -10715,7 +10842,14 @@ sub _graphicHeader {
|
||||
$api .= ' '.$lrt;
|
||||
|
||||
if ($scrm eq 'success') {
|
||||
$img = FW_makeImage('10px-kreis-gruen.png', $htitles{scaresps}{$lang}.' '.$htitles{natc}{$lang}.' '.$nscc);
|
||||
my $ptr = CurrentVal ($hash, 'dwdRad1hAge', '-');
|
||||
$img = FW_makeImage('10px-kreis-gruen.png', $htitles{scaresps}{$lang}.' '.$htitles{predtime}{$lang}.' '.$ptr);
|
||||
|
||||
if ($paref->{t} - CurrentVal ($hash, 'dwdRad1hAgeTS', 0) > 7200) {
|
||||
my $agetit = $htitles{arsrad2o}{$lang};
|
||||
$agetit =~ s/<NAME>/$name/xs;
|
||||
$img = FW_makeImage('10px-kreis-gelb.png', $agetit.' '.$htitles{predtime}{$lang}.' '.$ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$img = FW_makeImage('10px-kreis-rot.png', $htitles{scarespf}{$lang}.': '. $scrm);
|
||||
@ -11651,6 +11785,8 @@ sub _beamGraphicFirstHour {
|
||||
|
||||
$hfcg->{0}{weather} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'weatherid', 999);
|
||||
$hfcg->{0}{wcc} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'wcc', '-');
|
||||
$hfcg->{0}{sunalt} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'sunalt', '-');
|
||||
$hfcg->{0}{sunaz} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'sunaz', '-');
|
||||
}
|
||||
else {
|
||||
$val1 = CircularVal ($hash, $hfcg->{0}{time_str}, 'pvfc', 0);
|
||||
@ -11721,6 +11857,8 @@ sub _beamGraphicRemainingHours {
|
||||
|
||||
$hfcg->{$i}{weather} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'weatherid', 999);
|
||||
$hfcg->{$i}{wcc} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'wcc', '-');
|
||||
$hfcg->{$i}{sunalt} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'sunalt', '-');
|
||||
$hfcg->{$i}{sunaz} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'sunaz', '-');
|
||||
}
|
||||
else {
|
||||
$nh = sprintf '%02d', $i + $offset;
|
||||
@ -11735,6 +11873,8 @@ sub _beamGraphicRemainingHours {
|
||||
$val4 = NexthoursVal ($hash, 'NextHour'.$nh, 'confc', 0);
|
||||
$hfcg->{$i}{weather} = NexthoursVal ($hash, 'NextHour'.$nh, 'weatherid', 999);
|
||||
$hfcg->{$i}{wcc} = NexthoursVal ($hash, 'NextHour'.$nh, 'cloudcover', '-');
|
||||
$hfcg->{$i}{sunalt} = NexthoursVal ($hash, 'NextHour'.$nh, 'sunalt', '-');
|
||||
$hfcg->{$i}{sunaz} = NexthoursVal ($hash, 'NextHour'.$nh, 'sunaz', '-');
|
||||
#$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
|
||||
}
|
||||
|
||||
@ -12124,6 +12264,12 @@ sub __weatherOnBeam {
|
||||
|
||||
$wcc += 0 if(isNumeric ($wcc)); # Javascript Fehler vermeiden: https://forum.fhem.de/index.php/topic,117864.msg1233661.html#msg1233661
|
||||
$title .= ': '.$wcc;
|
||||
$title .= ' ';
|
||||
$title .= $htitles{sunpos}{$lang}.':';
|
||||
$title .= ' ';
|
||||
$title .= $htitles{elevatio}{$lang}.' '.$hfcg->{$i}{sunalt};
|
||||
$title .= ' ';
|
||||
$title .= $htitles{azimuth}{$lang}.' '.$hfcg->{$i}{sunaz};
|
||||
|
||||
if ($icon_name eq 'unknown') {
|
||||
debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer");
|
||||
@ -13286,21 +13432,17 @@ sub setPVhistory {
|
||||
my $dayname = $paref->{dayname}; # aktueller Wochentagsname
|
||||
my $histname = $paref->{histname} // qq{};
|
||||
my $pvrlvd = $paref->{pvrlvd}; # 1: Eintrag 'pvrl' wird im Lernprozess berücksichtigt
|
||||
my $ethishour = $paref->{ethishour} // 0;
|
||||
my $etotal = $paref->{etotal};
|
||||
my $ethishour = $paref->{ethishour};
|
||||
my $batinthishour = $paref->{batinthishour}; # Batterieladung in Stunde
|
||||
my $btotin = $paref->{batintotal}; # totale Batterieladung
|
||||
my $batoutthishour = $paref->{batoutthishour}; # Batterieentladung in Stunde
|
||||
my $btotout = $paref->{batouttotal}; # totale Batterieentladung
|
||||
my $calcpv = $paref->{calcpv} // 0;
|
||||
my $gcthishour = $paref->{gctotthishour} // 0; # Netzbezug
|
||||
my $fithishour = $paref->{gftotthishour} // 0; # Netzeinspeisung
|
||||
my $con = $paref->{con} // 0; # realer Hausverbrauch Energie
|
||||
my $confc = $paref->{confc} // 0; # Verbrauchsvorhersage
|
||||
my $consumerco = $paref->{consumerco}; # Verbrauch eines Verbrauchers
|
||||
my $pvcorrf = $paref->{pvcorrf} // "1.00/0"; # pvCorrectionFactor
|
||||
my $val = $paref->{val}; # Wert zur Speicherung in pvHistory (soll mal generell verwendet werden -> Change)
|
||||
my $rad1h = $paref->{rad1h}; # Strahlungsdaten speichern
|
||||
my $reorg = $paref->{reorg} // 0; # Neuberechnung von Werten in Stunde "99" nach Löschen von Stunden eines Tages
|
||||
my $reorgday = $paref->{reorgday} // q{}; # Tag der reorganisiert werden soll
|
||||
|
||||
@ -13353,13 +13495,12 @@ sub setPVhistory {
|
||||
$data{$type}{$name}{pvhist}{$day}{99}{pvrl} = $pvrlsum;
|
||||
}
|
||||
|
||||
if ($histname eq "radiation") { # irradiation
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{rad1h} = $rad1h;
|
||||
if ($histname eq 'radiation') { # irradiation
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{rad1h} = $val;
|
||||
}
|
||||
|
||||
if ($histname eq 'pvfc') { # prognostizierter Energieertrag
|
||||
$val = $calcpv;
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{pvfc} = $calcpv;
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{pvfc} = $val;
|
||||
|
||||
my $pvfcsum = 0;
|
||||
for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) {
|
||||
@ -13461,9 +13602,8 @@ sub setPVhistory {
|
||||
$data{$type}{$name}{pvhist}{$day}{99}{"hourscsme${num}"} = sprintf "%.2f", ($minutes / 60 ) if($cycles);
|
||||
}
|
||||
|
||||
if ($histname eq "etotal") { # etotal des Wechselrichters
|
||||
$val = $etotal;
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{etotal} = $etotal;
|
||||
if ($histname eq 'etotal') { # etotal des Wechselrichters
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{etotal} = $val;
|
||||
$data{$type}{$name}{pvhist}{$day}{99}{etotal} = q{};
|
||||
}
|
||||
|
||||
@ -13494,9 +13634,8 @@ sub setPVhistory {
|
||||
$data{$type}{$name}{pvhist}{$day}{99}{rr1c} = q{};
|
||||
}
|
||||
|
||||
if ($histname eq "pvcorrfactor") { # pvCorrectionFactor
|
||||
$val = $pvcorrf;
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{pvcorrf} = $pvcorrf;
|
||||
if ($histname eq 'pvcorrfactor') { # pvCorrectionFactor
|
||||
$data{$type}{$name}{pvhist}{$day}{$nhour}{pvcorrf} = $val;
|
||||
$data{$type}{$name}{pvhist}{$day}{99}{pvcorrf} = q{};
|
||||
}
|
||||
|
||||
@ -13799,7 +13938,7 @@ sub listDataPool {
|
||||
my $aihit = NexthoursVal ($hash, $idx, 'aihit', '-'); # KI ForeCast Treffer Status
|
||||
my $wid = NexthoursVal ($hash, $idx, 'weatherid', '-');
|
||||
my $neff = NexthoursVal ($hash, $idx, 'cloudcover', '-');
|
||||
my $crange = NexthoursVal ($hash, $idx, 'cloudrange', '-');
|
||||
my $crang = NexthoursVal ($hash, $idx, 'cloudrange', '-');
|
||||
my $rr1c = NexthoursVal ($hash, $idx, 'totalrain', '-');
|
||||
my $rrange = NexthoursVal ($hash, $idx, 'rainrange', '-');
|
||||
my $rad1h = NexthoursVal ($hash, $idx, 'rad1h', '-');
|
||||
@ -13821,7 +13960,7 @@ sub listDataPool {
|
||||
$sq .= "\n ";
|
||||
$sq .= "rad1h: $rad1h, sunaz: $sunaz, sunalt: $sunalt";
|
||||
$sq .= "\n ";
|
||||
$sq .= "rrange: $rrange, crange: $crange, correff: $pvcorrf";
|
||||
$sq .= "rrange: $rrange, crange: $crang, correff: $pvcorrf";
|
||||
}
|
||||
}
|
||||
|
||||
@ -13839,10 +13978,11 @@ sub listDataPool {
|
||||
my $aihit = NexthoursVal ($hash, $idx, 'aihit', '-');
|
||||
my $pvfc = NexthoursVal ($hash, $idx, 'pvfc', '-');
|
||||
my $neff = NexthoursVal ($hash, $idx, 'cloudcover', '-');
|
||||
my $sunalt = NexthoursVal ($hash, $idx, 'sunalt', '-');
|
||||
|
||||
my ($f,$q) = split "/", $pvcorrf;
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Cloud: $neff";
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Sun Alt: $sunalt, Cloud: $neff";
|
||||
}
|
||||
}
|
||||
|
||||
@ -13945,17 +14085,31 @@ sub _ldchash2val {
|
||||
my $key = $paref->{key};
|
||||
my $cval = $paref->{cval};
|
||||
|
||||
my $ret = qq{};
|
||||
my $ret = qq{};
|
||||
my $ret2 = qq{};
|
||||
|
||||
if (ref $cval eq 'HASH') {
|
||||
no warnings 'numeric';
|
||||
|
||||
for my $f (sort {$a<=>$b} keys %{$pool->{$idx}{$key}}) {
|
||||
next if($f eq 'simple');
|
||||
$ret .= " " if($ret);
|
||||
$ret .= "$f=".$pool->{$idx}{$key}{$f};
|
||||
my $ct = ($ret =~ tr/=// // 0) / 10;
|
||||
$ret .= "\n " if($ct =~ /^([1-9])?$/);
|
||||
if ($f !~ /\./xs) {
|
||||
$ret .= " " if($ret);
|
||||
$ret .= "$f=".$pool->{$idx}{$key}{$f};
|
||||
my $ct = ($ret =~ tr/=// // 0) / 10;
|
||||
$ret .= "\n " if($ct =~ /^[1-9](.{1})?$/);
|
||||
}
|
||||
elsif ($f =~ /\./xs) {
|
||||
$ret2 .= " " if($ret2);
|
||||
$ret2 .= "$f=".$pool->{$idx}{$key}{$f};
|
||||
my $ct2 = ($ret2 =~ tr/=// // 0) / 10;
|
||||
$ret2 .= "\n " if($ct2 =~ /^[1-9](.{1})?$/);
|
||||
}
|
||||
}
|
||||
|
||||
if ($ret2) {
|
||||
$ret .= "\n " if($ret && $ret !~ /\n\s+$/xs);
|
||||
$ret .= $ret2;
|
||||
}
|
||||
|
||||
use warnings;
|
||||
@ -14095,8 +14249,7 @@ sub checkPlantConfig {
|
||||
$result->{'DWD Weather Attributes'}{fault} = 1;
|
||||
}
|
||||
else {
|
||||
$result->{'DWD Weather Attributes'}{note} .= qq{checked attributes of device "$fcname": <br>}. join (' ', @dweattrmust).'<br>';
|
||||
$err = checkdwdattr ($name, $fcname, \@dweattrmust);
|
||||
$err = checkdwdattr ($name, $fcname, \@dweattrmust);
|
||||
|
||||
if ($err) {
|
||||
$result->{'DWD Weather Attributes'}{state} = $nok;
|
||||
@ -14106,34 +14259,52 @@ sub checkPlantConfig {
|
||||
else {
|
||||
$result->{'DWD Weather Attributes'}{result} .= $hqtxt{fulfd}{$lang}." ($hqtxt{attrib}{$lang}: ctrlWeatherDev$step)<br>";
|
||||
}
|
||||
|
||||
$result->{'DWD Weather Attributes'}{note} .= qq{checked parameters and attributes of device "$fcname": <br>};
|
||||
$result->{'DWD Weather Attributes'}{note} .= 'forecastProperties -> '.join (' ', @dweattrmust).'<br>';
|
||||
}
|
||||
}
|
||||
|
||||
## Check Attribute DWD Radiation Device
|
||||
#########################################
|
||||
## Check DWD Radiation Device
|
||||
###############################
|
||||
if (isDWDUsed ($hash)) {
|
||||
$result->{'DWD Radiation Attributes'}{state} = $ok;
|
||||
$result->{'DWD Radiation Attributes'}{result} = '';
|
||||
$result->{'DWD Radiation Attributes'}{note} = '';
|
||||
$result->{'DWD Radiation Attributes'}{fault} = 0;
|
||||
$result->{'DWD Radiation Properties'}{state} = $ok;
|
||||
$result->{'DWD Radiation Properties'}{result} = '';
|
||||
$result->{'DWD Radiation Properties'}{note} = '';
|
||||
$result->{'DWD Radiation Properties'}{fault} = 0;
|
||||
|
||||
if (!$raname || !$defs{$raname}) {
|
||||
$result->{'DWD Radiation Attributes'}{state} = $nok;
|
||||
$result->{'DWD Radiation Attributes'}{result} .= qq{The DWD device "$raname" doesn't exist <br>};
|
||||
$result->{'DWD Radiation Attributes'}{fault} = 1;
|
||||
$result->{'DWD Radiation Properties'}{state} = $nok;
|
||||
$result->{'DWD Radiation Properties'}{result} .= qq{The DWD device "$raname" doesn't exist <br>};
|
||||
$result->{'DWD Radiation Properties'}{fault} = 1;
|
||||
}
|
||||
else {
|
||||
$result->{'DWD Radiation Attributes'}{note} .= qq{checked attributes of device "$raname": <br>}. join ' ', @draattrmust;
|
||||
$err = checkdwdattr ($name, $raname, \@draattrmust);
|
||||
$err = checkdwdattr ($name, $raname, \@draattrmust);
|
||||
|
||||
if ($err) {
|
||||
$result->{'DWD Radiation Attributes'}{state} = $nok;
|
||||
$result->{'DWD Radiation Attributes'}{result} = $err;
|
||||
$result->{'DWD Radiation Attributes'}{fault} = 1;
|
||||
$result->{'DWD Radiation Properties'}{state} = $nok;
|
||||
$result->{'DWD Radiation Properties'}{result} .= $err.'<br>';
|
||||
$result->{'DWD Radiation Properties'}{note} .= qq{<br>Check the parameters set in device '$raname': attribute 'forecastProperties' <br>};
|
||||
$result->{'DWD Radiation Properties'}{fault} = 1;
|
||||
}
|
||||
else {
|
||||
$result->{'DWD Radiation Attributes'}{result} = $hqtxt{fulfd}{$lang};
|
||||
|
||||
if (time() - CurrentVal ($hash, 'dwdRad1hAgeTS', 0) > 7200) {
|
||||
$result->{'DWD Radiation Properties'}{state} = $warn;
|
||||
$result->{'DWD Radiation Properties'}{note} .= qq{The Prediction time of radiation data (Rad1h) is older than 2 hours. <br>};
|
||||
$result->{'DWD Radiation Properties'}{note} .= qq{Check the DWD device '$raname' for proper functioning of the data retrieval.<br>};
|
||||
$result->{'DWD Radiation Properties'}{warn} = 1;
|
||||
}
|
||||
|
||||
if (!$err) {
|
||||
$result->{'DWD Radiation Properties'}{result} .= $hqtxt{fulfd}{$lang}.'<br>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$result->{'DWD Radiation Properties'}{fault}) {
|
||||
$result->{'DWD Radiation Properties'}{result} = $hqtxt{fulfd}{$lang};
|
||||
$result->{'DWD Radiation Properties'}{note} .= qq{<br>checked parameters and attributes device "$raname": <br>};
|
||||
$result->{'DWD Radiation Properties'}{note} .= 'Age of Rad1h data <br>';
|
||||
$result->{'DWD Radiation Properties'}{note} .= 'forecastProperties -> '.join (' ', @draattrmust).'<br>';
|
||||
}
|
||||
}
|
||||
|
||||
@ -14357,7 +14528,7 @@ sub checkPlantConfig {
|
||||
$result->{'API Access'}{state} = $nok;
|
||||
$result->{'API Access'}{result} .= qq{DWD last message:<br>"$lam"<br>};
|
||||
$result->{'API Access'}{note} .= qq{Check the setup of the device "$raname". <br>};
|
||||
$result->{'API Access'}{note} .= qq{It is possible that not all readings are transmitted when "$raname" is newly set up. <br>};
|
||||
$result->{'API Access'}{note} .= qq{It is possible that not all readings are transmitted when "$raname" is newly set up or was changed. <br>};
|
||||
$result->{'API Access'}{note} .= qq{In this case, wait until tomorrow and check again.<br>};
|
||||
$result->{'API Access'}{fault} = 1;
|
||||
}
|
||||
@ -15967,7 +16138,8 @@ return $def;
|
||||
# wcc - DWD Wolkendichte
|
||||
# rr1c - Gesamtniederschlag (1-stündig) letzte 1 Stunde kg/m2
|
||||
# temp - Außentemperatur
|
||||
# pvcorrf - PV Autokorrekturfaktoren (HASH)
|
||||
# pvcorrf - PV Autokorrekturfaktoren (HASH),
|
||||
# - <Sonne Altitude>.<Cloudcover>
|
||||
# lastTsMaxSocRchd - Timestamp des letzten Erreichens von SoC >= maxSoC
|
||||
# nextTsMaxSocChge - Timestamp bis zu dem die Batterie mindestens einmal maxSoC erreichen soll
|
||||
# days2care - verbleibende Tage bis der Batterie Pflege-SoC (default $maxSoCdef) erreicht sein soll
|
||||
@ -16003,69 +16175,76 @@ sub CircularVal {
|
||||
return $def;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Wert des Autokorrekturfaktors und dessen Qualität
|
||||
# für eine bestimmte Bewölkungs-Range aus dem circular-Hash
|
||||
# zurückliefern
|
||||
# Usage:
|
||||
# ($f,$q) = CircularAutokorrVal ($hash, $hod, $range, $def)
|
||||
###################################################################
|
||||
# Wert des Autokorrekturfaktors
|
||||
# für eine bestimmte Sun Altitude-Range aus dem Circular-Hash
|
||||
# zurückliefern
|
||||
# Usage:
|
||||
# $f = CircularSunCloudkorrVal ($hash, $hod, $sabin, $crang, $def)
|
||||
#
|
||||
# $f: Korrekturfaktor f. Stunde des Tages
|
||||
# $q: Qualität des Korrekturfaktors
|
||||
# $f: Korrekturfaktor f. Stunde des Tages
|
||||
#
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $range: Range Bewölkung (1...100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $sabin: Sun Altitude Bin (0..90)
|
||||
# $crang: Bewölkung Bin (0..100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
#
|
||||
################################################################
|
||||
sub CircularAutokorrVal {
|
||||
###################################################################
|
||||
sub CircularSunCloudkorrVal {
|
||||
my $hash = shift;
|
||||
my $hod = shift;
|
||||
my $range = shift;
|
||||
my $sabin = shift;
|
||||
my $crang = shift;
|
||||
my $def = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $corrf = $def;
|
||||
my $qual = $def;
|
||||
my $idx = 'simple';
|
||||
|
||||
my $pvcorrf = $def;
|
||||
my $quality = $def;
|
||||
if ($crang ne 'simple') {
|
||||
$idx = $sabin.'.'.$crang;
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}{$range})) {
|
||||
$pvcorrf = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}{$idx})) {
|
||||
$corrf = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}{$range})) {
|
||||
$quality = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}{$idx})) {
|
||||
$qual = $data{$type}{$name}{circular}{$hod}{quality}{$idx};
|
||||
}
|
||||
|
||||
return ($pvcorrf, $quality);
|
||||
return ($corrf, $qual);
|
||||
}
|
||||
|
||||
########################################################################################################
|
||||
# Die durchschnittliche reale PV Erzeugung, PV Prognose und Tage
|
||||
# einer bestimmten Bewölkungs-Range aus dem circular-Hash zurückliefern
|
||||
# Usage:
|
||||
# ($pvrlsum, $pvfcsum, $dnumsum) = CircularSumVal ($hash, $hod, $range, $def)
|
||||
# ($pvrlsum, $pvfcsum, $dnumsum) = CircularSumVal ($hash, $hod, $crang, $def)
|
||||
#
|
||||
# $pvrlsum: Summe reale PV Erzeugung pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
# $pvfcsum: Summe PV Prognose pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
# $dnumsum: Anzahl Tage pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
#
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $range: Range Bewölkung (1...100) oder "simple"
|
||||
# $hod: Stunde des Tages (01,02,..,24)
|
||||
# $sabin: Sun Altitude Bin (0..90)
|
||||
# $crang: Bewölkung Bin (1..100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
#
|
||||
#######################################################################################################
|
||||
sub CircularSumVal {
|
||||
my $hash = shift;
|
||||
my $hod = shift;
|
||||
my $range = shift;
|
||||
my $sabin = shift;
|
||||
my $crang = shift;
|
||||
my $def = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
@ -16074,26 +16253,31 @@ sub CircularSumVal {
|
||||
my $pvrlsum = $def;
|
||||
my $pvfcsum = $def;
|
||||
my $dnumsum = $def;
|
||||
my $idx = 'simple';
|
||||
|
||||
if ($crang ne 'simple') {
|
||||
$idx = $sabin.'.'.$crang;
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}{$range})) {
|
||||
$pvrlsum = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}{$idx})) {
|
||||
$pvrlsum = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}{$range})) {
|
||||
$pvfcsum = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}{$idx})) {
|
||||
$pvfcsum = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}{$range})) {
|
||||
$dnumsum = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}{$idx})) {
|
||||
$dnumsum = $data{$type}{$name}{circular}{$hod}{dnumsum}{$idx};
|
||||
}
|
||||
|
||||
return ($pvrlsum, $pvfcsum, $dnumsum);
|
||||
@ -16153,6 +16337,8 @@ return $def;
|
||||
# batcharge - Bat SOC in %
|
||||
# batinstcap - installierte Batteriekapazität in Wh
|
||||
# ctrunning - aktueller Ausführungsstatus des Central Task
|
||||
# dwdRad1hAge - Alter des Rad1h Wertes als Datumstring
|
||||
# dwdRad1hAgeTS - Alter des Rad1h Wertes als Unix Timestamp
|
||||
# genslidereg - Schieberegister PV Erzeugung (Array)
|
||||
# h4fcslidereg - Schieberegister 4h PV Forecast (Array)
|
||||
# socslidereg - Schieberegister Batterie SOC (Array)
|
||||
@ -17421,6 +17607,8 @@ to ensure that the system configuration is correct.
|
||||
The hours 01 - 24 refer to the hour of the day, e.g. the hour 09 refers to the time from
|
||||
08 - 09 o'clock. <br>
|
||||
Hour 99 has a special function. <br>
|
||||
The values of the keys pvcorrf, quality, pvrlsum, pvfcsum and dnumsum are coded in the form
|
||||
<range sun elevation>.<cloud cover range>. <br>
|
||||
Explanation of the values: <br><br>
|
||||
|
||||
<ul>
|
||||
@ -19552,6 +19740,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
Die Stundenangaben 01 - 24 beziehen sich auf die Stunde des Tages, z.B. bezieht sich die Stunde 09 auf die Zeit von
|
||||
08 - 09 Uhr. <br>
|
||||
Die Stunde 99 hat eine Sonderfunktion. <br>
|
||||
Die Werte der Schlüssel pvcorrf, quality, pvrlsum, pvfcsum und dnumsum sind in der Form
|
||||
<Bereich Sonnenstand Höhe>.<Bewölkungsbreich> kodiert. <br>
|
||||
Erläuterung der Werte: <br><br>
|
||||
|
||||
<ul>
|
||||
|
Loading…
x
Reference in New Issue
Block a user