mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-04 05:16:45 +00:00
76_SolarForecast.pm: contrib 0.20.0
git-svn-id: https://svn.fhem.de/fhem/trunk@24068 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
2b09c88ad7
commit
3255c671a5
@ -116,7 +116,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
"0.20.0" => "23.03.2021 new sub CircularVal, some fixes ",
|
"0.20.0" => "23.03.2021 new sub CircularVal, NexthoursVal, some fixes ",
|
||||||
"0.19.0" => "22.03.2021 new sub HistoryVal, some fixes ",
|
"0.19.0" => "22.03.2021 new sub HistoryVal, some fixes ",
|
||||||
"0.18.0" => "21.03.2021 implement sub forecastGraphic from Wzut ",
|
"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 ",
|
||||||
@ -1465,12 +1465,20 @@ sub _transferWeatherValues {
|
|||||||
$data{$type}{$name}{nexthours}{$time_str}{rainprob} = $r101;
|
$data{$type}{$name}{nexthours}{$time_str}{rainprob} = $r101;
|
||||||
#}
|
#}
|
||||||
|
|
||||||
if($num < 23 && $fh < 24) { # Ringspeicher Weather Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
if($num < 23 && $fh < 24) { # Ringspeicher Weather Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
||||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weatherid} = $wid;
|
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weatherid} = $wid;
|
||||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weathertxt} = $txt;
|
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weathertxt} = $txt;
|
||||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weathercloudcover} = $neff;
|
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weathercloudcover} = $neff;
|
||||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weatherrainprob} = $r101;
|
$data{$type}{$name}{circular}{sprintf("%02d",$fh+1)}{weatherrainprob} = $r101;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($fd == 0 && $fh) { # WeatherId in pvhistory speichern
|
||||||
|
$paref->{wid} = $wid;
|
||||||
|
$paref->{histname} = "weatherid";
|
||||||
|
$paref->{nhour} = sprintf("%02d",$fh+1);
|
||||||
|
setPVhistory ($paref);
|
||||||
|
delete $paref->{histname};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1776,7 +1784,6 @@ sub forecastGraphic {
|
|||||||
|
|
||||||
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};
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Kontext des SolarForecast-Devices speichern für Refresh
|
# Kontext des SolarForecast-Devices speichern für Refresh
|
||||||
@ -1789,11 +1796,11 @@ sub forecastGraphic {
|
|||||||
my ($a,$h) = parseParams ($indev);
|
my ($a,$h) = parseParams ($indev);
|
||||||
$indev = $a->[0] // "";
|
$indev = $a->[0] // "";
|
||||||
|
|
||||||
my $pv0 = (exists($next_hour->{'NextHour00'}{pvforecast})) ? $next_hour->{'NextHour00'}{pvforecast} : undef;
|
my $pv0 = NexthoursVal ($hash, "NextHour00", "pvforecast", undef);
|
||||||
my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
|
my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
|
||||||
my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
|
my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
|
||||||
my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
|
my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
|
||||||
my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
|
my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
|
||||||
|
|
||||||
if(!$is || !$fcdev || !$indev || !$peak || !defined $pv0 || !$dir || !$ta) {
|
if(!$is || !$fcdev || !$indev || !$peak || !defined $pv0 || !$dir || !$ta) {
|
||||||
my $link = qq{<a href="/fhem?detail=$name">$name</a>};
|
my $link = qq{<a href="/fhem?detail=$name">$name</a>};
|
||||||
@ -2076,7 +2083,7 @@ sub forecastGraphic {
|
|||||||
my $day_str;
|
my $day_str;
|
||||||
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 = NexthoursVal ($hash, "NextHour00", "starttime", AttrVal('global', 'language', '') eq 'DE' ? '00.00.0000 24' : '0000-00-00 24');
|
||||||
($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_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');
|
||||||
|
|
||||||
@ -2112,7 +2119,8 @@ sub forecastGraphic {
|
|||||||
$val2 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "pvrl", 0);
|
$val2 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "pvrl", 0);
|
||||||
$val3 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "gcons", 0);
|
$val3 = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "gcons", 0);
|
||||||
|
|
||||||
$hfcg->{0}{weather} = CircularVal ($hash, $hfcg->{0}{time_str}, "weatherid", undef);
|
# $hfcg->{0}{weather} = CircularVal ($hash, $hfcg->{0}{time_str}, "weatherid", undef);
|
||||||
|
$hfcg->{0}{weather} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, "weatherid", undef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$val1 = CircularVal ($hash, $hfcg->{0}{time_str}, "pvfc", 0);
|
$val1 = CircularVal ($hash, $hfcg->{0}{time_str}, "pvfc", 0);
|
||||||
@ -2212,7 +2220,7 @@ sub forecastGraphic {
|
|||||||
$val1 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "pvfc", 0);
|
$val1 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "pvfc", 0);
|
||||||
$val2 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "pvrl", 0);
|
$val2 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "pvrl", 0);
|
||||||
$val3 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "gcons", 0);
|
$val3 = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "gcons", 0);
|
||||||
$hfcg->{$i}{weather} = CircularVal ($hash, $hfcg->{$i}{time_str}, "weatherid", undef);
|
$hfcg->{$i}{weather} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, "weatherid", undef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$nh = sprintf('%02d', $i+$offset);
|
$nh = sprintf('%02d', $i+$offset);
|
||||||
@ -2223,8 +2231,8 @@ sub forecastGraphic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (defined($nh)) {
|
if (defined($nh)) {
|
||||||
$val1 = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{pvforecast} // 0 : 0;
|
$val1 = NexthoursVal ($hash, 'NextHour'.$nh, "pvforecast", 0);
|
||||||
$hfcg->{$i}{weather} = $next_hour->{'NextHour'.$nh} ? $next_hour->{'NextHour'.$nh}{weatherid} // undef : undef;
|
$hfcg->{$i}{weather} = NexthoursVal ($hash, 'NextHour'.$nh, "weatherid", undef);
|
||||||
#$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
|
#$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2772,10 +2780,10 @@ sub calcPVforecast {
|
|||||||
my $rainslope = AttrVal($name, "rainFactorSlope", $rslopedef); # prozentuale Berücksichtigung des Regenkorrekturfaktors
|
my $rainslope = AttrVal($name, "rainFactorSlope", $rslopedef); # prozentuale Berücksichtigung des Regenkorrekturfaktors
|
||||||
my @strings = sort keys %{$stch};
|
my @strings = sort keys %{$stch};
|
||||||
|
|
||||||
my $cloudcover = $data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudcover} // 0; # effektive Wolkendecke
|
my $cloudcover = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), "cloudcover", 0); # effektive Wolkendecke
|
||||||
my $ccf = 1 - ((($cloudcover - $cloud_base)/100) * $cloudslope/100); # Cloud Correction Faktor mit Steilheit und Fußpunkt
|
my $ccf = 1 - ((($cloudcover - $cloud_base)/100) * $cloudslope/100); # Cloud Correction Faktor mit Steilheit und Fußpunkt
|
||||||
|
|
||||||
my $rainprob = $data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{rainprob} // 0; # Niederschlagswahrscheinlichkeit> 0,1 mm während der letzten Stunde
|
my $rainprob = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), "rainprob", 0); # Niederschlagswahrscheinlichkeit> 0,1 mm während der letzten Stunde
|
||||||
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');
|
||||||
@ -2989,6 +2997,7 @@ sub setPVhistory {
|
|||||||
my $ethishour = $paref->{ethishour} // 0;
|
my $ethishour = $paref->{ethishour} // 0;
|
||||||
my $calcpv = $paref->{calcpv} // 0;
|
my $calcpv = $paref->{calcpv} // 0;
|
||||||
my $gthishour = $paref->{gctotthishour} // 0;
|
my $gthishour = $paref->{gctotthishour} // 0;
|
||||||
|
my $wid = $paref->{wid} // -1;
|
||||||
|
|
||||||
my $type = $hash->{TYPE};
|
my $type = $hash->{TYPE};
|
||||||
my $val = q{};
|
my $val = q{};
|
||||||
@ -3029,6 +3038,11 @@ sub setPVhistory {
|
|||||||
$data{$type}{$name}{pvhist}{$day}{99}{gcons} = $gcsum;
|
$data{$type}{$name}{pvhist}{$day}{99}{gcons} = $gcsum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($histname eq "weatherid") { # bezogene Energie
|
||||||
|
$val = $wid;
|
||||||
|
$data{$type}{$name}{pvhist}{$day}{$nhour}{weatherid} = $wid;
|
||||||
|
}
|
||||||
|
|
||||||
Log3 ($name, 5, "$name - set PV History hour: $nhour, hash: $histname, val: $val");
|
Log3 ($name, 5, "$name - set PV History hour: $nhour, hash: $histname, val: $val");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -3051,11 +3065,12 @@ 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 = HistoryVal ($hash, $day, $key, "pvrl", 0);
|
my $pvrl = HistoryVal ($hash, $day, $key, "pvrl", 0);
|
||||||
my $pvfc = HistoryVal ($hash, $day, $key, "pvfc", 0);
|
my $pvfc = HistoryVal ($hash, $day, $key, "pvfc", 0);
|
||||||
my $cons = HistoryVal ($hash, $day, $key, "gcons", 0);
|
my $cons = HistoryVal ($hash, $day, $key, "gcons", 0);
|
||||||
|
my $wid = HistoryVal ($hash, $day, $key, "weatherid", -1);
|
||||||
$ret .= "\n " if($ret);
|
$ret .= "\n " if($ret);
|
||||||
$ret .= $key." => pvreal: $pvrl, pvforecast: $pvfc, gridcon: $cons";
|
$ret .= $key." => pvreal: $pvrl, pvforecast: $pvfc, gridcon: $cons, weatherid: $wid";
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
};
|
};
|
||||||
@ -3094,12 +3109,12 @@ sub listDataPool {
|
|||||||
return qq{NextHours cache is empty.};
|
return qq{NextHours cache is empty.};
|
||||||
}
|
}
|
||||||
for my $idx (sort keys %{$h}) {
|
for my $idx (sort keys %{$h}) {
|
||||||
my $nhts = $data{$type}{$name}{nexthours}{$idx}{starttime};
|
my $nhts = NexthoursVal ($hash, $idx, "starttime", qq{});
|
||||||
my $nhfc = $data{$type}{$name}{nexthours}{$idx}{pvforecast};
|
my $nhfc = NexthoursVal ($hash, $idx, "pvforecast", 0);
|
||||||
my $wid = $data{$type}{$name}{nexthours}{$idx}{weatherid};
|
my $wid = NexthoursVal ($hash, $idx, "weatherid", -1);
|
||||||
my $neff = $data{$type}{$name}{nexthours}{$idx}{cloudcover};
|
my $neff = NexthoursVal ($hash, $idx, "cloudcover", 0);
|
||||||
my $r101 = $data{$type}{$name}{nexthours}{$idx}{rainprob};
|
my $r101 = NexthoursVal ($hash, $idx, "rainprob", 0);
|
||||||
my $rad1h = $data{$type}{$name}{nexthours}{$idx}{Rad1h};
|
my $rad1h = NexthoursVal ($hash, $idx, "Rad1h", 0);
|
||||||
$sq .= "\n" if($sq);
|
$sq .= "\n" if($sq);
|
||||||
$sq .= $idx." => starttime: $nhts, pvforecast: $nhfc, weatherid: $wid, cloudcover: $neff, rainprob: $r101, Rad1h: $rad1h";
|
$sq .= $idx." => starttime: $nhts, pvforecast: $nhfc, weatherid: $wid, cloudcover: $neff, rainprob: $r101, Rad1h: $rad1h";
|
||||||
}
|
}
|
||||||
@ -3168,14 +3183,14 @@ sub collectSummaries {
|
|||||||
my $todaySum = { "PV" => 0, "Consumption" => 0, "Total" => 0, "ConsumpRcmd" => 0 };
|
my $todaySum = { "PV" => 0, "Consumption" => 0, "Total" => 0, "ConsumpRcmd" => 0 };
|
||||||
|
|
||||||
my $rdh = 24 - $chour - 1; # verbleibende Anzahl Stunden am Tag beginnend mit 00 (abzüglich aktuelle Stunde)
|
my $rdh = 24 - $chour - 1; # verbleibende Anzahl Stunden am Tag beginnend mit 00 (abzüglich aktuelle Stunde)
|
||||||
my $thforecast = $data{$type}{$name}{nexthours}{NextHour00}{pvforecast};
|
my $thforecast = NexthoursVal ($hash, "NextHour00", "pvforecast", 0);
|
||||||
|
|
||||||
$next4HoursSum->{PV} = $thforecast;
|
$next4HoursSum->{PV} = $thforecast;
|
||||||
$restOfDaySum->{PV} = $thforecast;
|
$restOfDaySum->{PV} = $thforecast;
|
||||||
|
|
||||||
for my $h (1..47) {
|
for my $h (1..47) {
|
||||||
next if(!$data{$type}{$name}{nexthours}{"NextHour".sprintf "%02d",$h});
|
next if(!$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$h)});
|
||||||
my $pvfc = $data{$type}{$name}{nexthours}{"NextHour".sprintf "%02d",$h}{pvforecast} // 0;
|
my $pvfc = NexthoursVal ($hash, "NextHour".sprintf("%02d",$h), "pvforecast", 0);
|
||||||
|
|
||||||
$next4HoursSum->{PV} += $pvfc if($h <= 3);
|
$next4HoursSum->{PV} += $pvfc if($h <= 3);
|
||||||
$restOfDaySum->{PV} += $pvfc if($h <= $rdh);
|
$restOfDaySum->{PV} += $pvfc if($h <= $rdh);
|
||||||
@ -3305,7 +3320,7 @@ return;
|
|||||||
# $key: pvrl - realer PV Ertrag
|
# $key: pvrl - realer PV Ertrag
|
||||||
# pvfc - PV Vorhersage
|
# pvfc - PV Vorhersage
|
||||||
# gcons - realer Netzbezug
|
# gcons - realer Netzbezug
|
||||||
# $def: Defaultwert
|
# $def: Defaultwert
|
||||||
#
|
#
|
||||||
################################################################
|
################################################################
|
||||||
sub HistoryVal {
|
sub HistoryVal {
|
||||||
@ -3333,7 +3348,7 @@ return $def;
|
|||||||
# Usage:
|
# Usage:
|
||||||
# CircularVal ($hash, $hod, $key, $def)
|
# CircularVal ($hash, $hod, $key, $def)
|
||||||
#
|
#
|
||||||
# $hod: Stunde des Tages (01,02,...,24,99)
|
# $hod: Stunde des Tages (01,02,...,24)
|
||||||
# $key: pvrl - realer PV Ertrag
|
# $key: pvrl - realer PV Ertrag
|
||||||
# pvfc - PV Vorhersage
|
# pvfc - PV Vorhersage
|
||||||
# gcons - realer Netzbezug
|
# gcons - realer Netzbezug
|
||||||
@ -3341,7 +3356,7 @@ return $def;
|
|||||||
# weathertxt - DWD Wetter Text
|
# weathertxt - DWD Wetter Text
|
||||||
# weathercloudcover - DWD Wolkendichte
|
# weathercloudcover - DWD Wolkendichte
|
||||||
# weatherrainprob - DWD Regenwahrscheinlichkeit
|
# weatherrainprob - DWD Regenwahrscheinlichkeit
|
||||||
# $def: Defaultwert
|
# $def: Defaultwert
|
||||||
#
|
#
|
||||||
################################################################
|
################################################################
|
||||||
sub CircularVal {
|
sub CircularVal {
|
||||||
@ -3362,6 +3377,39 @@ sub CircularVal {
|
|||||||
return $def;
|
return $def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# Wert des nexthours-Hash zurückliefern
|
||||||
|
# Usage:
|
||||||
|
# NexthoursVal ($hash, $hod, $key, $def)
|
||||||
|
#
|
||||||
|
# $hod: nächste Stunde (NextHour00, NextHour01,...)
|
||||||
|
# $key: starttime - Startzeit der abgefragten nächsten Stunde
|
||||||
|
# pvforecast - PV Vorhersage
|
||||||
|
# weatherid - DWD Wetter id
|
||||||
|
# cloudcover - DWD Wolkendichte
|
||||||
|
# rainprob - DWD Regenwahrscheinlichkeit
|
||||||
|
# Rad1h - Globalstrahlung (kJ/m2)
|
||||||
|
# $def: Defaultwert
|
||||||
|
#
|
||||||
|
################################################################
|
||||||
|
sub NexthoursVal {
|
||||||
|
my $hash = shift;
|
||||||
|
my $hod = shift;
|
||||||
|
my $key = shift;
|
||||||
|
my $def = shift;
|
||||||
|
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $type = $hash->{TYPE};
|
||||||
|
|
||||||
|
if(defined($data{$type}{$name}{nexthours}) &&
|
||||||
|
defined($data{$type}{$name}{nexthours}{$hod}) &&
|
||||||
|
defined($data{$type}{$name}{nexthours}{$hod}{$key})) {
|
||||||
|
return $data{$type}{$name}{nexthours}{$hod}{$key};
|
||||||
|
}
|
||||||
|
|
||||||
|
return $def;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
=pod
|
=pod
|
||||||
|
Loading…
x
Reference in New Issue
Block a user