mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 03:06:37 +00:00
76_SolarForecast.pm: contrib 0.35.0
git-svn-id: https://svn.fhem.de/fhem/trunk@24227 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
ee642d57b9
commit
ceeafaeac1
@ -38,6 +38,7 @@ eval "use JSON;1;" or my $jsonabs = "JSON"; ## no critic 'eval' #
|
|||||||
|
|
||||||
use FHEM::SynoModules::SMUtils qw( evaljson
|
use FHEM::SynoModules::SMUtils qw( evaljson
|
||||||
moduleVersion
|
moduleVersion
|
||||||
|
addCHANGED
|
||||||
trim
|
trim
|
||||||
); # Hilfsroutinen Modul
|
); # Hilfsroutinen Modul
|
||||||
|
|
||||||
@ -117,6 +118,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"0.35.0" => "12.04.2021 create additional PVforecast events - PV forecast until the end of the coming day ",
|
||||||
"0.34.1" => "11.04.2021 further improvement of cloud dependent calculation autocorrection ",
|
"0.34.1" => "11.04.2021 further improvement of cloud dependent calculation autocorrection ",
|
||||||
"0.34.0" => "10.04.2021 only hours with the same cloud cover range are considered for pvCorrection, some fixes ",
|
"0.34.0" => "10.04.2021 only hours with the same cloud cover range are considered for pvCorrection, some fixes ",
|
||||||
"0.33.0" => "09.04.2021 new setter currentBatteryDev, bugfix in _transferMeterValues ",
|
"0.33.0" => "09.04.2021 new setter currentBatteryDev, bugfix in _transferMeterValues ",
|
||||||
@ -348,7 +350,7 @@ my $defslidenum = 3;
|
|||||||
my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_"; # Filename-Fragment für PV History (wird mit Devicename ergänzt)
|
my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_"; # Filename-Fragment für PV History (wird mit Devicename ergänzt)
|
||||||
my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt)
|
my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt)
|
||||||
|
|
||||||
my $calcmaxd = 21; # Anzahl Tage (default) für Durchschnittermittlung zur Vorhersagekorrektur
|
my $calcmaxd = 21; # Anzahl Tage (default) für Berechnung Vorhersagekorrektur
|
||||||
my @dwdattrmust = qw(Rad1h TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des DWD_Opendata Devices mindestens gesetzt sein müssen
|
my @dwdattrmust = qw(Rad1h TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||||
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
|
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
|
||||||
|
|
||||||
@ -1525,9 +1527,10 @@ sub _additionalActivities {
|
|||||||
my $name = $paref->{name};
|
my $name = $paref->{name};
|
||||||
my $chour = $paref->{chour};
|
my $chour = $paref->{chour};
|
||||||
my $daref = $paref->{daref};
|
my $daref = $paref->{daref};
|
||||||
my $t = $paref->{t}; # Epoche Zeit
|
my $t = $paref->{t}; # Epoche Zeit
|
||||||
|
|
||||||
my $date = strftime "%Y-%m-%d", localtime($t); # aktuelles Datum
|
my $type = $hash->{TYPE};
|
||||||
|
my $date = strftime "%Y-%m-%d", localtime($t); # aktuelles Datum
|
||||||
|
|
||||||
my ($ts,$ts1,$pvfc,$pvrl,$gcon);
|
my ($ts,$ts1,$pvfc,$pvrl,$gcon);
|
||||||
|
|
||||||
@ -1542,24 +1545,40 @@ sub _additionalActivities {
|
|||||||
$gcon = ReadingsNum($name, "Today_Hour".sprintf("%02d",$chour)."_GridConsumption", 0);
|
$gcon = ReadingsNum($name, "Today_Hour".sprintf("%02d",$chour)."_GridConsumption", 0);
|
||||||
push @$daref, "LastHourGridconsumptionReal<>".$gcon." Wh<>".$ts1;
|
push @$daref, "LastHourGridconsumptionReal<>".$gcon." Wh<>".$ts1;
|
||||||
|
|
||||||
my $tlim = "00"; # bestimmte Aktionen
|
## zusätzliche Events erzeugen - PV Vorhersage bis Ende des kommenden Tages
|
||||||
|
#############################################################################
|
||||||
|
for my $idx (sort keys %{$data{$type}{$name}{nexthours}}) {
|
||||||
|
my $nhts = NexthoursVal ($hash, $idx, "starttime", undef);
|
||||||
|
my $nhfc = NexthoursVal ($hash, $idx, "pvforecast", undef);
|
||||||
|
next if(!defined $nhts || !defined $nhfc);
|
||||||
|
|
||||||
|
my ($dt, $h) = $nhts =~ /([\w-]+)\s(\d{2})/xs;
|
||||||
|
addCHANGED ($hash, "PVforecast: ".$nhfc, $dt." ".$h.":59:59");
|
||||||
|
}
|
||||||
|
|
||||||
|
DoTrigger($name, undef, 1);
|
||||||
|
|
||||||
|
## bestimmte einmalige Aktionen
|
||||||
|
##################################
|
||||||
|
my $tlim = "00";
|
||||||
if($chour =~ /^($tlim)$/x) {
|
if($chour =~ /^($tlim)$/x) {
|
||||||
if(!exists $hash->{HELPER}{H00DONE}) {
|
if(!exists $hash->{HELPER}{H00DONE}) {
|
||||||
$date = strftime "%Y-%m-%d", localtime($t-7200); # Vortag (2 h Differenz reichen aus)
|
$date = strftime "%Y-%m-%d", localtime($t-7200); # Vortag (2 h Differenz reichen aus)
|
||||||
$ts = $date." 23:59:59";
|
$ts = $date." 23:59:59";
|
||||||
|
|
||||||
$pvfc = ReadingsNum($name, "Today_Hour24_PVforecast", 0);
|
$pvfc = ReadingsNum($name, "Today_Hour24_PVforecast", 0);
|
||||||
push @$daref, "LastHourPVforecast<>".$pvfc."<>".$ts1;
|
push @$daref, "LastHourPVforecast<>".$pvfc."<>".$ts;
|
||||||
|
|
||||||
$pvrl = ReadingsNum($name, "Today_Hour24_PVreal", 0);
|
$pvrl = ReadingsNum($name, "Today_Hour24_PVreal", 0);
|
||||||
push @$daref, "LastHourPVreal<>".$pvrl."<>".$ts1;
|
push @$daref, "LastHourPVreal<>".$pvrl."<>".$ts;
|
||||||
|
|
||||||
$gcon = ReadingsNum($name, "Today_Hour24_GridConsumption", 0);
|
$gcon = ReadingsNum($name, "Today_Hour24_GridConsumption", 0);
|
||||||
push @$daref, "LastHourGridconsumptionReal<>".$gcon."<>".$ts1;
|
push @$daref, "LastHourGridconsumptionReal<>".$gcon."<>".$ts;
|
||||||
|
|
||||||
deleteReadingspec ($hash, "Today_Hour.*_Grid.*");
|
deleteReadingspec ($hash, "Today_Hour.*_Grid.*");
|
||||||
deleteReadingspec ($hash, "Today_Hour.*_PV.*");
|
deleteReadingspec ($hash, "Today_Hour.*_PV.*");
|
||||||
deleteReadingspec ($hash, "powerTrigger_.*");
|
deleteReadingspec ($hash, "powerTrigger_.*");
|
||||||
|
deleteReadingspec ($hash, "pvCorrectionFactor_.*_autocalc");
|
||||||
|
|
||||||
delete $hash->{HELPER}{INITETOTAL};
|
delete $hash->{HELPER}{INITETOTAL};
|
||||||
delete $hash->{HELPER}{INITCONTOTAL};
|
delete $hash->{HELPER}{INITCONTOTAL};
|
||||||
@ -1625,15 +1644,12 @@ sub _transferDWDForecastValues {
|
|||||||
|
|
||||||
my $calcpv = calcPVforecast ($params); # Vorhersage gewichtet kalkulieren
|
my $calcpv = calcPVforecast ($params); # Vorhersage gewichtet kalkulieren
|
||||||
|
|
||||||
$time_str = "NextHour".sprintf "%02d", $num;
|
$time_str = "NextHour".sprintf "%02d", $num;
|
||||||
$epoche = $t + (3600*$num);
|
$epoche = $t + (3600*$num);
|
||||||
my ($ta,$realts) = TimeAdjust ($epoche);
|
my ($ta,$tsdef,$realts) = TimeAdjust ($epoche);
|
||||||
|
|
||||||
# push @$daref, "CurrentHourPVforecast<>".$calcpv." Wh<>".$realts if($num == 0);
|
|
||||||
#push @$daref, "${time_str}_Time<>" .$ta;
|
|
||||||
|
|
||||||
$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} = $tsdef;
|
||||||
$data{$type}{$name}{nexthours}{$time_str}{Rad1h} = $rad; # nur Info: original Vorhersage Strahlungsdaten
|
$data{$type}{$name}{nexthours}{$time_str}{Rad1h} = $rad; # nur Info: original Vorhersage Strahlungsdaten
|
||||||
|
|
||||||
if($num < 23 && $fh < 24) { # Ringspeicher PV forecast Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
if($num < 23 && $fh < 24) { # Ringspeicher PV forecast Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||||
@ -2640,16 +2656,10 @@ sub forecastGraphic {
|
|||||||
##########################
|
##########################
|
||||||
# Werte aktuelle Stunde
|
# Werte aktuelle Stunde
|
||||||
##########################
|
##########################
|
||||||
|
|
||||||
my $thishour;
|
|
||||||
my $month;
|
|
||||||
my $year;
|
|
||||||
my $day_str;
|
|
||||||
my $day;
|
my $day;
|
||||||
|
|
||||||
my $t = NexthoursVal ($hash, "NextHour00", "starttime", AttrVal('global', 'language', '') eq 'DE' ? '00.00.0000 24' : '0000-00-00 24');
|
my $t = NexthoursVal ($hash, "NextHour00", "starttime", '0000-00-00 24');
|
||||||
($year,$month,$day_str,$thishour) = $t =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x;
|
my ($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');
|
|
||||||
|
|
||||||
$thishour++;
|
$thishour++;
|
||||||
|
|
||||||
@ -3266,16 +3276,17 @@ sub TimeAdjust {
|
|||||||
my ($sec,$min,$hour,$day,$mon,$year) = (localtime(time))[0,1,2,3,4,5]; # Standard f. z.B. Readingstimstamp
|
my ($sec,$min,$hour,$day,$mon,$year) = (localtime(time))[0,1,2,3,4,5]; # Standard f. z.B. Readingstimstamp
|
||||||
$year += 1900;
|
$year += 1900;
|
||||||
$mon++;
|
$mon++;
|
||||||
my $realts = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year,$mon,$day,$hour,$min,$sec);
|
my $realts = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year,$mon,$day,$hour,$min,$sec);
|
||||||
|
my $tsdef = sprintf("%04d-%02d-%02d %02d:%s", $lyear,$lmonth,$lday,$lhour,"00:00"); # engl. Variante für Logging-Timestamps etc.
|
||||||
|
|
||||||
if(AttrVal("global","language","EN") eq "DE") {
|
if(AttrVal("global","language","EN") eq "DE") {
|
||||||
$ts = sprintf("%02d.%02d.%04d %02d:%s", $lday,$lmonth,$lyear,$lhour,"00:00");
|
$ts = sprintf("%02d.%02d.%04d %02d:%s", $lday,$lmonth,$lyear,$lhour,"00:00");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ts = sprintf("%04d-%02d-%02d %02d:%s", $lyear,$lmonth,$lday,$lhour,"00:00");
|
$ts = $tsdef;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($ts,$realts);
|
return ($ts,$tsdef,$realts);
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
@ -3370,7 +3381,9 @@ sub calcPVforecast {
|
|||||||
$hcfound = "no - use raw correction factor";
|
$hcfound = "no - use raw correction factor";
|
||||||
$hc = $pvcorr; # nutze RAW-Korrekturfaktor
|
$hc = $pvcorr; # nutze RAW-Korrekturfaktor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{pvcorrf} = $hc;
|
||||||
|
|
||||||
my $pvsum = 0;
|
my $pvsum = 0;
|
||||||
|
|
||||||
@ -3440,12 +3453,6 @@ sub calcVariance {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $tlim = "00"; # Stunde 00 -> löschen aller Autocalc Statusreadings des Tages
|
|
||||||
|
|
||||||
if($chour =~ /^($tlim)$/x) {
|
|
||||||
deleteReadingspec ($hash, "pvCorrectionFactor_.*_autocalc");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $idts = ReadingsTimestamp($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice
|
my $idts = ReadingsTimestamp($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice
|
||||||
return if(!$idts);
|
return if(!$idts);
|
||||||
|
|
||||||
@ -3796,14 +3803,15 @@ 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 = NexthoursVal ($hash, $idx, "starttime", "-");
|
my $nhts = NexthoursVal ($hash, $idx, "starttime", "-");
|
||||||
my $nhfc = NexthoursVal ($hash, $idx, "pvforecast", "-");
|
my $nhfc = NexthoursVal ($hash, $idx, "pvforecast", "-");
|
||||||
my $wid = NexthoursVal ($hash, $idx, "weatherid", "-");
|
my $wid = NexthoursVal ($hash, $idx, "weatherid", "-");
|
||||||
my $neff = NexthoursVal ($hash, $idx, "cloudcover", "-");
|
my $neff = NexthoursVal ($hash, $idx, "cloudcover", "-");
|
||||||
my $r101 = NexthoursVal ($hash, $idx, "rainprob", "-");
|
my $r101 = NexthoursVal ($hash, $idx, "rainprob", "-");
|
||||||
my $rad1h = NexthoursVal ($hash, $idx, "Rad1h", "-");
|
my $rad1h = NexthoursVal ($hash, $idx, "Rad1h", "-");
|
||||||
$sq .= "\n" if($sq);
|
my $pvcorrf = NexthoursVal ($hash, $idx, "pvcorrf", "-");
|
||||||
$sq .= $idx." => starttime: $nhts, pvforecast: $nhfc, weatherid: $wid, cloudcover: $neff, rainprob: $r101, Rad1h: $rad1h";
|
$sq .= "\n" if($sq);
|
||||||
|
$sq .= $idx." => starttime: $nhts, pvfc: $nhfc, wid: $wid, wcc: $neff, correff: $pvcorrf, wrp: $r101, Rad1h: $rad1h";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4196,7 +4204,7 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
|
|||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
Ein SolarForecast Device wird einfach erstellt mit: <br><br>
|
Ein SolarForecast Device wird erstellt mit: <br><br>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<b>define <name> SolarForecast </b>
|
<b>define <name> SolarForecast </b>
|
||||||
@ -4204,7 +4212,7 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
Nach der Definition des Devices ist zwingend ein Vorhersage-Device des Typs DWD_OpenData zuzuordnen sowie weitere
|
Nach der Definition des Devices ist zwingend ein Vorhersage-Device des Typs DWD_OpenData zuzuordnen sowie weitere
|
||||||
anlagenspezifische Angaben mit dem entsprechenden set-Kommando vorzunehmen. <br>
|
anlagenspezifische Angaben mit den entsprechenden set-Kommandos vorzunehmen. <br>
|
||||||
Mit nachfolgenden set-Kommandos werden die Quellendevices und Quellenreadings für maßgebliche Informationen
|
Mit nachfolgenden set-Kommandos werden die Quellendevices und Quellenreadings für maßgebliche Informationen
|
||||||
hinterlegt: <br><br>
|
hinterlegt: <br><br>
|
||||||
|
|
||||||
@ -4220,8 +4228,10 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
Um eine Anpassung an die persönliche Anlage zu ermöglichen, können Korrekturfaktoren manuell
|
Um eine Anpassung an die persönliche Anlage zu ermöglichen, können Korrekturfaktoren manuell
|
||||||
(set <name> pvCorrectionFactor_XX) bzw. automatisiert (set <name> pvCorrectionFactor_Auto) eingefügt
|
(set <name> pvCorrectionFactor_XX) bzw. automatisiert (set <name> pvCorrectionFactor_Auto on) bestimmt
|
||||||
werden.
|
werden. <br>
|
||||||
|
Es wird empfohlen die automatische Vorhersagekorrektur unmittelbar einzuschalten, da das SolarForecast Device etliche Tage
|
||||||
|
benötigt um eine Optimierung der Korrekturfaktoren zu erreichen.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
</ul>
|
</ul>
|
||||||
@ -4489,11 +4499,12 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
|
|||||||
|
|
||||||
Schaltet die automatische Vorhersagekorrektur ein/aus. <br>
|
Schaltet die automatische Vorhersagekorrektur ein/aus. <br>
|
||||||
Ist die Automatik eingeschaltet, wird nach einer Mindestlaufzeit von FHEM bzw. des Moduls von 24 Stunden für jede Stunde
|
Ist die Automatik eingeschaltet, wird nach einer Mindestlaufzeit von FHEM bzw. des Moduls von 24 Stunden für jede Stunde
|
||||||
ein Korrekturfaktor der Solarvorhersage berechnet und auf die Erwartung des kommenden Tages angewendet.
|
ein Korrekturfaktor der Solarvorhersage berechnet und intern dauerhaft gespeichert.
|
||||||
Dazu wird die tatsächliche Energierzeugung mit dem vorhergesagten Wert des aktuellen Tages und Stunde verglichen,
|
Dazu wird die tatsächliche Energieerzeugung mit dem vorhergesagten Wert des aktuellen Tages und Stunde verglichen,
|
||||||
die Korrekturwerte historischer Tage unter Berücksichtigung der Bewölkung einbezogen und daraus ein neuer Korrekturfaktor
|
die Korrekturwerte historischer Tage unter Berücksichtigung der Bewölkung einbezogen und daraus ein neuer Korrekturfaktor
|
||||||
abgeleitet. Es werden nur historische Daten mit gleicher Bewölkungsrange einbezogen. <br>
|
abgeleitet. Es werden nur historische Daten mit gleicher Bewölkungsrange einbezogen. <br>
|
||||||
<b>Die automatische Vorhersagekorrektur ist lernend und benötigt etliche Tage um die Korrekturwerte zu optimieren.
|
Zukünftig erwartete PV Erzeugungen werden mit den gespeicherten Korrekturfaktoren optimiert. <br>
|
||||||
|
<b>Die automatische Vorhersagekorrektur ist lernend und benötigt einige Tage um die Korrekturwerte zu optimieren.
|
||||||
Nach der Aktivierung sind nicht sofort optimale Vorhersagen zu erwarten !</b> <br>
|
Nach der Aktivierung sind nicht sofort optimale Vorhersagen zu erwarten !</b> <br>
|
||||||
(default: off)
|
(default: off)
|
||||||
</li>
|
</li>
|
||||||
@ -4555,7 +4566,19 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
|
|||||||
<ul>
|
<ul>
|
||||||
<a name="nextHours"></a>
|
<a name="nextHours"></a>
|
||||||
<li><b>nextHours </b> <br>
|
<li><b>nextHours </b> <br>
|
||||||
Listet die erwarteten Werte der nächsten Stunden auf.
|
Listet die erwarteten Werte der kommenden Stunden auf. <br><br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<table>
|
||||||
|
<colgroup> <col width=10%> <col width=90%> </colgroup>
|
||||||
|
<tr><td> <b>pvfc</b> </td><td>erwartete PV Erzeugung </td></tr>
|
||||||
|
<tr><td> <b>wid</b> </td><td>ID des vorhergesagten Wetters </td></tr>
|
||||||
|
<tr><td> <b>wcc</b> </td><td>vorhergesagter Grad der Bewölkung </td></tr>
|
||||||
|
<tr><td> <b>correff</b> </td><td>effektiv verwendeter Korrekturfaktor abhängig vom vorhergesagten Grad der Bewölkung </td></tr>
|
||||||
|
<tr><td> <b>wrp</b> </td><td>vorhergesagter Grad der Regenwahrscheinlichkeit </td></tr>
|
||||||
|
<tr><td> <b>Rad1h</b> </td><td>vorhergesagte Globalstrahlung </td></tr>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user