2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 01:09:47 +00:00

76_SolarForecast.pm: contrib 0.19.0

git-svn-id: https://svn.fhem.de/fhem/trunk@24058 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2021-03-22 20:33:54 +00:00
parent 2bab87deb7
commit 1eb42e94d4

View File

@ -116,7 +116,8 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"0.18.0" => "21.03.2021 new sub forecastGraphic from Wzut ", "0.19.0" => "22.03.2021 new sub HistoryVal, some fixes ",
"0.18.0" => "21.03.2021 implement sub forecastGraphic from Wzut ",
"0.17.1" => "21.03.2021 bug fixes, delete Helper->NextHour ", "0.17.1" => "21.03.2021 bug fixes, delete Helper->NextHour ",
"0.17.0" => "20.03.2021 new attr cloudFactorSlope / rainFactorSlope, fixes in Graphic sub ", "0.17.0" => "20.03.2021 new attr cloudFactorSlope / rainFactorSlope, fixes in Graphic sub ",
"0.16.0" => "19.03.2021 new getter nextHours, some fixes ", "0.16.0" => "19.03.2021 new getter nextHours, some fixes ",
@ -1400,7 +1401,7 @@ sub _transferDWDForecastValues {
Log3($name, 5, "$name - collect DWD forecast data: device=$fcname, rad=fc${fd}_${fh}_Rad1h, Rad1h=$v"); Log3($name, 5, "$name - collect DWD forecast data: device=$fcname, rad=fc${fd}_${fh}_Rad1h, Rad1h=$v");
my $calcpv = calcPVforecast ($name, $v, $num, $t, $fd); # Vorhersage gewichtet kalkulieren my $calcpv = calcPVforecast ($name, $v, $num, $t, $fh, $fd); # Vorhersage gewichtet kalkulieren
my $num1 = $num-1; my $num1 = $num-1;
if($num1 >= 0) { if($num1 >= 0) {
@ -1413,6 +1414,7 @@ sub _transferDWDForecastValues {
$data{$type}{$name}{nexthours}{$time_str}{pvforecast} = $calcpv; $data{$type}{$name}{nexthours}{$time_str}{pvforecast} = $calcpv;
$data{$type}{$name}{nexthours}{$time_str}{starttime} = $ta; $data{$type}{$name}{nexthours}{$time_str}{starttime} = $ta;
$data{$type}{$name}{nexthours}{$time_str}{Rad1h} = $v; # nur Info: original Vorhersage Strahlungsdaten
} }
if($num < 23 && $fh > 0 && $fh < 24) { # Ringspeicher PV forecast Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350 if($num < 23 && $fh > 0 && $fh < 24) { # Ringspeicher PV forecast Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
@ -1420,7 +1422,7 @@ sub _transferDWDForecastValues {
} }
$hash->{HELPER}{"fc${fd}_".sprintf("%02d",$fh)."_Rad1h"} = $v." kJ/m2"; # nur Info: original Vorhersage Strahlungsdaten zur Berechnung Auto-Korrekturfaktor in Helper speichern # $hash->{HELPER}{"fc${fd}_".sprintf("%02d",$fh)."_Rad1h"} = $v." kJ/m2"; # nur Info: original Vorhersage Strahlungsdaten zur Berechnung Auto-Korrekturfaktor in Helper speichern
if($fd == 0 && int $calcpv > 0) { # Vorhersagedaten des aktuellen Tages zum manuellen Vergleich in Reading speichern if($fd == 0 && int $calcpv > 0) { # Vorhersagedaten des aktuellen Tages zum manuellen Vergleich in Reading speichern
push @$daref, "Today_Hour".sprintf("%02d",$fh)."_PVforecast:$calcpv Wh"; push @$daref, "Today_Hour".sprintf("%02d",$fh)."_PVforecast:$calcpv Wh";
@ -1807,7 +1809,7 @@ sub forecastGraphic {
my ($val,$height); my ($val,$height);
my ($z2,$z3,$z4); my ($z2,$z3,$z4);
my $he; # Balkenhöhe my $he; # Balkenhöhe
#my (%is,%di);
my $hfcg = $data{$hash->{TYPE}}{$name}{html}; #(hfcg = hash forecast graphic) my $hfcg = $data{$hash->{TYPE}}{$name}{html}; #(hfcg = hash forecast graphic)
my $pvhist = $data{$hash->{TYPE}}{$name}{pvhist}; my $pvhist = $data{$hash->{TYPE}}{$name}{pvhist};
my $next_hour = $data{$hash->{TYPE}}{$name}{nexthours}; my $next_hour = $data{$hash->{TYPE}}{$name}{nexthours};
@ -1994,8 +1996,6 @@ sub forecastGraphic {
my $dlink = "<a href=\"/fhem?detail=$name\">$alias</a>"; my $dlink = "<a href=\"/fhem?detail=$name\">$alias</a>";
my $lup = ReadingsTimestamp($name, "NextHour00_PVforecast", "0000-00-00 00:00:00"); # letzter Forecast Update my $lup = ReadingsTimestamp($name, "NextHour00_PVforecast", "0000-00-00 00:00:00"); # letzter Forecast Update
# ToDo : warum geht das hier nicht ?
#my $lup = (exists($next_hour->{NextHour00}{starttime})) ? $next_hour->{NextHour00}{starttime} : '0000-00-00 00:00:00' ;
my $lupt = "last update:"; my $lupt = "last update:";
my $autoct = "automatic correction:"; my $autoct = "automatic correction:";
@ -2113,13 +2113,11 @@ sub forecastGraphic {
my $day; my $day;
my $t = (exists($next_hour->{'NextHour00'}{starttime})) ? $next_hour->{'NextHour00'}{starttime} : (AttrVal('global', 'language', '') eq 'DE') ? '00.00.0000 24' : '0000-00-00 24'; my $t = (exists($next_hour->{'NextHour00'}{starttime})) ? $next_hour->{'NextHour00'}{starttime} : (AttrVal('global', 'language', '') eq 'DE') ? '00.00.0000 24' : '0000-00-00 24';
#($year,$month,$day,$thishour) = ReadingsVal($name, "NextHour00_Time", '0000-00-00 24') =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x;
($year,$month,$day_str,$thishour) = $t =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x; ($year,$month,$day_str,$thishour) = $t =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x;
#($day,$month,$year,$thishour) = ReadingsVal($name, "NextHour00_Time", '00.00.0000 24') =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x if (AttrVal('global', 'language', '') eq 'DE');
#$t = (exists($next_hour->{'NextHour00'}{starttime})) ? $next_hour->{'NextHour00'}{starttime} : '00.00.0000 24';
($day_str,$month,$year,$thishour) = $t =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x if (AttrVal('global', 'language', '') eq 'DE'); ($day_str,$month,$year,$thishour) = $t =~ m/(\d{2}).(\d{2}).(\d{4})\s(\d{2})/x if (AttrVal('global', 'language', '') eq 'DE');
$thishour++;
$hfcg->{0}{time_str} = $thishour; $hfcg->{0}{time_str} = $thishour;
$thishour = int($thishour); # keine führende Null $thishour = int($thishour); # keine führende Null
@ -2127,9 +2125,7 @@ sub forecastGraphic {
$hfcg->{0}{day_str} = $day_str; $hfcg->{0}{day_str} = $day_str;
$day = int($day_str); $day = int($day_str);
$hfcg->{0}{day} = $day; $hfcg->{0}{day} = $day;
# gleich die Unix Zeit dazu holen $hfcg->{0}{mktime} = fhemTimeLocal(0,0,$thishour,$day,int($month),$year); # gleich die Unix Zeit dazu holen
#$hfcg->{0}{mktime} = timelocal(0,0,$thishour,$day,int($month),$year);
$hfcg->{0}{mktime} = fhemTimeLocal(0,0,$thishour,$day,int($month),$year);
my $val1 = 0; my $val1 = 0;
my $val2 = 0; my $val2 = 0;
@ -2141,21 +2137,16 @@ sub forecastGraphic {
if ($hfcg->{0}{time} < 0) { if ($hfcg->{0}{time} < 0) {
$hfcg->{0}{time} += 24; $hfcg->{0}{time} += 24;
# Achtung : Tageswechsel - day muss jetzt neu berechnet werden ! my $n_day = strftime "%d", localtime($hfcg->{0}{mktime} - (3600 * abs($offset))); # Achtung : Tageswechsel - day muss jetzt neu berechnet werden !
my $n_day = strftime "%d", localtime($hfcg->{0}{mktime} - (3600 * abs($offset)));
$hfcg->{0}{day} = int($n_day); $hfcg->{0}{day} = int($n_day);
$hfcg->{0}{day_str} = $n_day; $hfcg->{0}{day_str} = $n_day;
# hfcg->{0}{day_str} muss jetzt ungleich dem $day_str sein !
} }
$hfcg->{0}{time_str} = sprintf('%02d', $hfcg->{0}{time}); $hfcg->{0}{time_str} = sprintf('%02d', $hfcg->{0}{time});
# Achtung Falle : $val1 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "pvfc", 0);
#if (exists($pvhist->{$hfcg->{0}{day_str}})) { $val2 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "pvrl", 0);
$val1 = (exists($pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{pvfc})) ? $pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{pvfc} : 0; $val3 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "gcons", 0);
$val2 = (exists($pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{pvrl})) ? $pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{pvrl} : 0;
$val3 = (exists($pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{gcons})) ? $pvhist->{$hfcg->{0}{day_str}}{$hfcg->{0}{time_str}}{gcons} : 0;
#}
$hfcg->{0}{weather} = (exists($data{$hash->{TYPE}}{$name}{weather}{$hfcg->{0}{time_str}}{id})) ? $data{$hash->{TYPE}}{$name}{weather}{$hfcg->{0}{time_str}}{id} : undef; $hfcg->{0}{weather} = (exists($data{$hash->{TYPE}}{$name}{weather}{$hfcg->{0}{time_str}}{id})) ? $data{$hash->{TYPE}}{$name}{weather}{$hfcg->{0}{time_str}}{id} : undef;
} }
@ -2168,14 +2159,13 @@ sub forecastGraphic {
#$val4 = (ReadingsVal($name,"ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef; #$val4 = (ReadingsVal($name,"ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : undef;
} }
$hfcg->{0}{time_str} .= $hourstyle; $hfcg->{0}{time_str} = sprintf('%02d', $hfcg->{0}{time}-1).$hourstyle;
$hfcg->{0}{beam1} = ($beam1cont eq 'forecast') ? $val1 : ($beam1cont eq 'real') ? $val2 : ($beam1cont eq 'consumption') ? $val3 : $val4; $hfcg->{0}{beam1} = ($beam1cont eq 'forecast') ? $val1 : ($beam1cont eq 'real') ? $val2 : ($beam1cont eq 'consumption') ? $val3 : $val4;
$hfcg->{0}{beam2} = ($beam2cont eq 'forecast') ? $val1 : ($beam2cont eq 'real') ? $val2 : ($beam2cont eq 'consumption') ? $val3 : $val4; $hfcg->{0}{beam2} = ($beam2cont eq 'forecast') ? $val1 : ($beam2cont eq 'real') ? $val2 : ($beam2cont eq 'consumption') ? $val3 : $val4;
$hfcg->{0}{diff} = $hfcg->{0}{beam1} - $hfcg->{0}{beam2}; $hfcg->{0}{diff} = $hfcg->{0}{beam1} - $hfcg->{0}{beam2};
# User Auswahl überschreiben wenn beide Werte die gleiche Basis haben ! $lotype = 'pv' if ($beam1cont eq $beam2cont); # User Auswahl überschreiben wenn beide Werte die gleiche Basis haben !
$lotype = 'pv' if ($beam1cont eq $beam2cont);
########################################################### ###########################################################
# get consumer list and display it in portalGraphics # get consumer list and display it in portalGraphics
@ -2242,7 +2232,7 @@ sub forecastGraphic {
$hfcg->{$i}{time} = $hfcg->{0}{time} + $i; $hfcg->{$i}{time} = $hfcg->{0}{time} + $i;
while ($hfcg->{$i}{time} > 23) { while ($hfcg->{$i}{time} > 24) {
$hfcg->{$i}{time} -= 24; # wird bis zu 2x durchlaufen $hfcg->{$i}{time} -= 24; # wird bis zu 2x durchlaufen
} }
@ -2270,12 +2260,11 @@ sub forecastGraphic {
if (defined($nh)) { if (defined($nh)) {
$val1 = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{pvforecast} // 0 : 0; $val1 = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{pvforecast} // 0 : 0;
# ToDo : klären ob -1 oder nicht !
$hfcg->{$i}{weather} = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{weatherid} // undef : undef; $hfcg->{$i}{weather} = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{weatherid} // undef : undef;
#$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef; #$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
} }
$hfcg->{$i}{time_str} .= $hourstyle; $hfcg->{$i}{time_str} = sprintf('%02d', $hfcg->{$i}{time}-1).$hourstyle;
$hfcg->{$i}{beam1} = ($beam1cont eq 'forecast') ? $val1 : ($beam1cont eq 'real') ? $val2 : ($beam1cont eq 'consumption') ? $val3 : $val4; $hfcg->{$i}{beam1} = ($beam1cont eq 'forecast') ? $val1 : ($beam1cont eq 'real') ? $val2 : ($beam1cont eq 'consumption') ? $val3 : $val4;
$hfcg->{$i}{beam2} = ($beam2cont eq 'forecast') ? $val1 : ($beam2cont eq 'real') ? $val2 : ($beam2cont eq 'consumption') ? $val3 : $val4; $hfcg->{$i}{beam2} = ($beam2cont eq 'forecast') ? $val1 : ($beam2cont eq 'real') ? $val2 : ($beam2cont eq 'consumption') ? $val3 : $val4;
@ -2325,7 +2314,7 @@ sub forecastGraphic {
for my $i (0..($maxhours*2)-1) { for my $i (0..($maxhours*2)-1) {
last if (!exists($hfcg->{$i}{weather})); last if (!exists($hfcg->{$i}{weather}));
next if (!$show_night && ($hfcg->{$i}{weather} > 99) && !$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}); next if (!$show_night && defined($hfcg->{$i}{weather}) && ($hfcg->{$i}{weather} > 99) && !$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2});
# Lässt Nachticons aber noch durch wenn es einen Wert gibt , ToDo : klären ob die Nacht richtig gesetzt wurde # Lässt Nachticons aber noch durch wenn es einen Wert gibt , ToDo : klären ob die Nacht richtig gesetzt wurde
$ii++; # wieviele Stunden Icons haben wir bisher beechnet ? $ii++; # wieviele Stunden Icons haben wir bisher beechnet ?
last if ($ii > $maxhours); # vorzeitiger Abbruch last if ($ii > $maxhours); # vorzeitiger Abbruch
@ -2378,7 +2367,7 @@ sub forecastGraphic {
my $ii = 0; my $ii = 0;
for my $i (0..($maxhours*2)-1) { for my $i (0..($maxhours*2)-1) {
# gleiche Bedingung wie oben # gleiche Bedingung wie oben
next if (!$show_night && ($hfcg->{$i}{weather} > 99) && !$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}); next if (!$show_night && defined($hfcg->{$i}{weather}) && ($hfcg->{$i}{weather} > 99) && !$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2});
$ii++; $ii++;
last if ($ii > $maxhours); last if ($ii > $maxhours);
@ -2544,7 +2533,6 @@ sub forecastGraphic {
$ret .= "<tr class='odd' style='height:".$z2."px'>"; $ret .= "<tr class='odd' style='height:".$z2."px'>";
$ret .= "<td align='center' class='smaportal' ".$style1.">$val"; $ret .= "<td align='center' class='smaportal' ".$style1.">$val";
#$ret .= $is{$i} if (defined $is{$i});
################################## ##################################
# inject the new icon if defined # inject the new icon if defined
@ -2561,7 +2549,6 @@ sub forecastGraphic {
if ($lotype eq 'diff') { # Type diff if ($lotype eq 'diff') { # Type diff
my $style = "style=\"padding-bottom:0px; padding-top:1px; vertical-align:top; margin-left:auto; margin-right:auto;"; my $style = "style=\"padding-bottom:0px; padding-top:1px; vertical-align:top; margin-left:auto; margin-right:auto;";
$ret .= "<table width='100%' border='0'>\n"; # Tipp : das nachfolgende border=0 auf 1 setzen hilft sehr Ausgabefehler zu endecken $ret .= "<table width='100%' border='0'>\n"; # Tipp : das nachfolgende border=0 auf 1 setzen hilft sehr Ausgabefehler zu endecken
#$val = ($hfcg->{$i}{diff} >= 0) ? formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}) : '';
$val = ($hfcg->{$i}{diff} > 0) ? formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}) : ''; $val = ($hfcg->{$i}{diff} > 0) ? formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}) : '';
$val = '&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;' if ($hfcg->{$i}{diff} == 0); # Sonderfall , hier wird die 0 gebraucht ! $val = '&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;' if ($hfcg->{$i}{diff} == 0); # Sonderfall , hier wird die 0 gebraucht !
@ -2576,7 +2563,6 @@ sub forecastGraphic {
$z2 = 1 if ($hfcg->{$i}{diff} == 0); # Sonderfall , 1px dünnen Strich ausgeben $z2 = 1 if ($hfcg->{$i}{diff} == 0); # Sonderfall , 1px dünnen Strich ausgeben
$ret .= "<tr class='odd' style='height:".$z2."px'>"; $ret .= "<tr class='odd' style='height:".$z2."px'>";
$ret .= "<td align='center' class='smaportal' ".$style.">"; $ret .= "<td align='center' class='smaportal' ".$style.">";
#$ret .= $is{$i} if (defined $is{$i});
$ret .= "</td></tr>"; $ret .= "</td></tr>";
} }
else { # ohne Farbe else { # ohne Farbe
@ -2606,8 +2592,6 @@ sub forecastGraphic {
if ($show_diff eq 'bottom') { # zusätzliche diff Anzeige if ($show_diff eq 'bottom') { # zusätzliche diff Anzeige
$val = formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}); $val = formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather});
#$val = 0 if ($val eq '&nbsp;');
#$hfcg->{$i}{diff} = 0 if ($hfcg->{$i}{diff} eq ' ');
$val = ($hfcg->{$i}{diff} < 0) ? '<b>'.$val.'<b/>' : ($val > 0 ) ? '+'.$val : $val if ($val ne '&nbsp;'); # negative Zahlen in Fettschrift, 0 aber ohne + $val = ($hfcg->{$i}{diff} < 0) ? '<b>'.$val.'<b/>' : ($val > 0 ) ? '+'.$val : $val if ($val ne '&nbsp;'); # negative Zahlen in Fettschrift, 0 aber ohne +
$ret .= "<tr class='even'><td class='smaportal' style='vertical-align:middle; text-align:center;'>$val</td></tr>"; $ret .= "<tr class='even'><td class='smaportal' style='vertical-align:middle; text-align:center;'>$val</td></tr>";
} }
@ -2616,8 +2600,7 @@ sub forecastGraphic {
$ret .= (($hfcg->{$i}{time} == $thishour) && ($offset < 0)) ? '<a class="changed" style="visibility:visible"><span>'.$hfcg->{$i}{time_str}.'</span></a>' : $hfcg->{$i}{time_str}; $ret .= (($hfcg->{$i}{time} == $thishour) && ($offset < 0)) ? '<a class="changed" style="visibility:visible"><span>'.$hfcg->{$i}{time_str}.'</span></a>' : $hfcg->{$i}{time_str};
$thishour = 99 if ($hfcg->{$i}{time} == $thishour); # nur einmal verwenden ! $thishour = 99 if ($hfcg->{$i}{time} == $thishour); # nur einmal verwenden !
$ret .="</td></tr></table></td>"; $ret .="</td></tr></table></td>";
} ## for i }
$ret .= "<td class='smaportal'></td></tr>"; $ret .= "<td class='smaportal'></td></tr>";
@ -2808,8 +2791,9 @@ return @aneeded;
sub calcPVforecast { sub calcPVforecast {
my $name = shift; my $name = shift;
my $rad = shift; # Nominale Strahlung aus DWD Device my $rad = shift; # Nominale Strahlung aus DWD Device
my $num = shift; # Stunde des Tages my $num = shift; # Nexthour
my $t = shift; # aktueller Unix Timestamp my $t = shift; # aktueller Unix Timestamp
my $fh = shift;
my $fd = shift; my $fd = shift;
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -2831,7 +2815,7 @@ sub calcPVforecast {
my $rcf = 1 - ((($rainprob - $rain_base)/100) * $rainslope/100); # Rain Correction Faktor mit Steilheit my $rcf = 1 - ((($rainprob - $rain_base)/100) * $rainslope/100); # Rain Correction Faktor mit Steilheit
my $kw = AttrVal ($name, 'Wh/kWh', 'Wh'); my $kw = AttrVal ($name, 'Wh/kWh', 'Wh');
my $hc = ReadingsNum ($name, "pvCorrectionFactor_".sprintf("%02d",$num), 1); # Korrekturfaktor für die Stunde des Tages my $hc = ReadingsNum ($name, "pvCorrectionFactor_".sprintf("%02d",$fh+1), 1); # Korrekturfaktor der Stunde des Tages einbeziehen
my $pvsum = 0; my $pvsum = 0;
@ -2945,6 +2929,9 @@ sub calcVariance {
my ($pvavg,$fcavg) = calcFromHistory ($paref); # historische PV / Forecast Vergleichswerte ermitteln my ($pvavg,$fcavg) = calcFromHistory ($paref); # historische PV / Forecast Vergleichswerte ermitteln
$pvval = $pvavg ? ($pvval + $pvavg) / 2 : $pvval; # Ertrag aktuelle Stunde berücksichtigen $pvval = $pvavg ? ($pvval + $pvavg) / 2 : $pvval; # Ertrag aktuelle Stunde berücksichtigen
$fcval = $fcavg ? ($fcval + $fcavg) / 2 : $fcval; # Vorhersage aktuelle Stunde berücksichtigen $fcval = $fcavg ? ($fcval + $fcavg) / 2 : $fcval; # Vorhersage aktuelle Stunde berücksichtigen
Log3 ($name, 4, "$name - PV History -> average hour ($h) -> real: $pvval, forecast: $fcval");
my $factor = sprintf "%.2f", ($pvval / $fcval); # Faktorberechnung: reale PV / Prognose my $factor = sprintf "%.2f", ($pvval / $fcval); # Faktorberechnung: reale PV / Prognose
if(abs($factor - $oldfac) > $maxvar) { if(abs($factor - $oldfac) > $maxvar) {
@ -3010,15 +2997,13 @@ sub calcFromHistory {
my ($pvrl,$pvfc) = (0,0); my ($pvrl,$pvfc) = (0,0);
for my $dayfa (@efa) { for my $dayfa (@efa) {
$pvrl += $pvhh->{$dayfa}{$hour}{pvrl} // 0; $pvrl += HistoryVal ($hash, $dayfa, $hour, "pvrl", 0);
$pvfc += $pvhh->{$dayfa}{$hour}{pvfc} // 0; $pvfc += HistoryVal ($hash, $dayfa, $hour, "pvfc", 0);
} }
my $pvavg = sprintf "%.2f", $pvrl / $anzavg; my $pvavg = sprintf "%.2f", $pvrl / $anzavg;
my $fcavg = sprintf "%.2f", $pvfc / $anzavg; my $fcavg = sprintf "%.2f", $pvfc / $anzavg;
Log3 ($name, 4, "$name - PV History -> average hour ($hour) -> real: $pvavg, forecast: $fcavg");
return ($pvavg,$fcavg); return ($pvavg,$fcavg);
} }
@ -3051,7 +3036,7 @@ sub setPVhistory {
my $pvrlsum = 0; my $pvrlsum = 0;
for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) { for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) {
next if($k eq "99"); next if($k eq "99");
$pvrlsum += $data{$type}{$name}{pvhist}{$day}{$k}{pvrl} // 0; $pvrlsum += HistoryVal ($hash, $day, $k, "pvrl", 0);
} }
$data{$type}{$name}{pvhist}{$day}{99}{pvrl} = $pvrlsum; $data{$type}{$name}{pvhist}{$day}{99}{pvrl} = $pvrlsum;
} }
@ -3063,7 +3048,7 @@ sub setPVhistory {
my $pvfcsum = 0; my $pvfcsum = 0;
for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) { for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) {
next if($k eq "99"); next if($k eq "99");
$pvfcsum += $data{$type}{$name}{pvhist}{$day}{$k}{pvfc} // 0; $pvfcsum += HistoryVal ($hash, $day, $k, "pvfc", 0);
} }
$data{$type}{$name}{pvhist}{$day}{99}{pvfc} = $pvfcsum; $data{$type}{$name}{pvhist}{$day}{99}{pvfc} = $pvfcsum;
} }
@ -3075,7 +3060,7 @@ sub setPVhistory {
my $gcsum = 0; my $gcsum = 0;
for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) { for my $k (keys %{$data{$type}{$name}{pvhist}{$day}}) {
next if($k eq "99"); next if($k eq "99");
$gcsum += $data{$type}{$name}{pvhist}{$day}{$k}{gcons} // 0; $gcsum += HistoryVal ($hash, $day, $k, "gcons", 0);
} }
$data{$type}{$name}{pvhist}{$day}{99}{gcons} = $gcsum; $data{$type}{$name}{pvhist}{$day}{99}{gcons} = $gcsum;
} }
@ -3102,9 +3087,9 @@ sub listDataPool {
my $day = shift; my $day = shift;
my $ret; my $ret;
for my $key (sort{$a<=>$b} keys %{$h->{$day}}) { for my $key (sort{$a<=>$b} keys %{$h->{$day}}) {
my $pvrl = $h->{$day}{$key}{pvrl} // 0; my $pvrl = HistoryVal ($hash, $day, $key, "pvrl", 0);
my $pvfc = $h->{$day}{$key}{pvfc} // 0; my $pvfc = HistoryVal ($hash, $day, $key, "pvfc", 0);
my $cons = $h->{$day}{$key}{gcons} // 0; my $cons = HistoryVal ($hash, $day, $key, "gcons", 0);
$ret .= "\n " if($ret); $ret .= "\n " if($ret);
$ret .= $key." => pvreal: $pvrl, pvforecast: $pvfc, gridcon: $cons"; $ret .= $key." => pvreal: $pvrl, pvforecast: $pvfc, gridcon: $cons";
} }
@ -3165,8 +3150,9 @@ sub listDataPool {
my $wid = $data{$type}{$name}{nexthours}{$idx}{weatherid}; my $wid = $data{$type}{$name}{nexthours}{$idx}{weatherid};
my $neff = $data{$type}{$name}{nexthours}{$idx}{cloudcover}; my $neff = $data{$type}{$name}{nexthours}{$idx}{cloudcover};
my $r101 = $data{$type}{$name}{nexthours}{$idx}{rainprob}; my $r101 = $data{$type}{$name}{nexthours}{$idx}{rainprob};
my $rad1h = $data{$type}{$name}{nexthours}{$idx}{Rad1h};
$sq .= "\n" if($sq); $sq .= "\n" if($sq);
$sq .= $idx." => starttime: $nhts, pvforecast: $nhfc, weatherid: $wid, cloudcover: $neff, rainprob: $r101"; $sq .= $idx." => starttime: $nhts, pvforecast: $nhfc, weatherid: $wid, cloudcover: $neff, rainprob: $r101, Rad1h: $rad1h";
} }
} }
@ -3360,6 +3346,40 @@ sub createNotifyDev {
return; return;
} }
################################################################
# Wert des pvhist-Hash zurückliefern
# Usage:
# HistoryVal ($hash, $day, $hod, $key, $def)
#
# $day: Tag des Monats (01,02,...,31)
# $hod: Stunde des Tages (01,02,...,24,99)
# $key: pvrl - realer PV Ertrag
# pvfc - PV Vorhersage
# gcons - realer Netzbezug
# $def: Defaultwert
#
################################################################
sub HistoryVal {
my $hash = shift;
my $day = shift;
my $hod = shift;
my $key = shift;
my $def = shift;
my $name = $hash->{NAME};
my $type = $hash->{TYPE};
my ($d,$n,$default) = @_;
if(defined($data{$type}{$name}{pvhist}) &&
defined($data{$type}{$name}{pvhist}{$day}) &&
defined($data{$type}{$name}{pvhist}{$day}{$hod}) &&
defined($data{$type}{$name}{pvhist}{$day}{$hod}{$key})) {
return $data{$type}{$name}{pvhist}{$day}{$hod}{$key};
}
return $def;
}
1; 1;
=pod =pod