2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-27 20:34:52 +00:00

76_SolarForecast: possible export pvHistory to CSV, making attr affectMaxDayVariance obsolete

git-svn-id: https://svn.fhem.de/fhem/trunk@28780 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2024-04-10 20:47:23 +00:00
parent beb811c602
commit bbdd3c8afc
2 changed files with 127 additions and 58 deletions

@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it # Do not insert empty lines here, update check depends on it
- feature: 76_SolarForecast: possible export pvHistory to CSV,
making attr affectMaxDayVariance obsolete
- feature: 72_FRITZBOX: attr <name> lanDeviceReading <mac|ip> - feature: 72_FRITZBOX: attr <name> lanDeviceReading <mac|ip>
Legt fest, ob der Reading Name aus der IP-Adresse mit Präfix Legt fest, ob der Reading Name aus der IP-Adresse mit Präfix
ip_ oder der MAC-Adresse mit Präfix mac_ für Netzwerk Geräte ip_ oder der MAC-Adresse mit Präfix mac_ für Netzwerk Geräte

@ -158,6 +158,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.17.7" => "09.04.2024 export pvHistory to CSV, making attr affectMaxDayVariance obsolete ",
"1.17.6" => "07.04.2024 new sub writeToHistory with many internal changes in pvHistory write process ". "1.17.6" => "07.04.2024 new sub writeToHistory with many internal changes in pvHistory write process ".
"_transferInverterValues: react on inverter etotal behavior ", "_transferInverterValues: react on inverter etotal behavior ",
"1.17.5" => "04.04.2024 currentInverterDev: check syntax of key capacity if set, change defmaxvar back from 0.8 to 0.5 ". "1.17.5" => "04.04.2024 currentInverterDev: check syntax of key capacity if set, change defmaxvar back from 0.8 to 0.5 ".
@ -361,8 +362,9 @@ my $csmcache = $root."/FHEM/FhemUtils/PVCsm_SolarForecast_";
my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt) my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt)
my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt) my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt)
my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten
my $dwdcatalog = $root."/FHEM/FhemUtils/DWDcat_SolarForecast"; # Filename-Fragment für DWD Stationskatalog my $dwdcatalog = $root."/FHEM/FhemUtils/DWDcat_SolarForecast"; # Filename für DWD Stationskatalog
my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Filename-Fragment für DWD Stationskatalog my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Export Filename für DWD Stationskatalog im gpx-Format
my $pvhexprtcsv = $root."/FHEM/FhemUtils/PVH_Export_SolarForecast_"; # Filename-Fragment für PV History Exportfile (wird mit Devicename ergänzt)
my $aitrblto = 7200; # KI Training BlockingCall Timeout my $aitrblto = 7200; # KI Training BlockingCall Timeout
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
@ -478,7 +480,7 @@ my @rconfigs = qw( pvCorrectionFactor_Auto
); );
# Anlagenkonfiguration: maßgebliche Attribute # Anlagenkonfiguration: maßgebliche Attribute
my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsForecastIdentWeekdays my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsForecastIdentWeekdays
affectConsForecastInPlanning affectMaxDayVariance affectSolCastPercentile affectConsForecastInPlanning affectSolCastPercentile
consumerLegend consumerAdviceIcon consumerLink consumerLegend consumerAdviceIcon consumerLink
ctrlAIdataStorageDuration ctrlAutoRefresh ctrlAutoRefreshFW ctrlBackupFilesKeep ctrlAIdataStorageDuration ctrlAutoRefresh ctrlAutoRefreshFW ctrlBackupFilesKeep
ctrlBatSocManagement ctrlConsRecommendReadings ctrlGenPVdeviation ctrlInterval ctrlBatSocManagement ctrlConsRecommendReadings ctrlGenPVdeviation ctrlInterval
@ -1089,7 +1091,7 @@ sub Initialize {
"affectBatteryPreferredCharge:slider,0,1,100 ". "affectBatteryPreferredCharge:slider,0,1,100 ".
"affectConsForecastIdentWeekdays:1,0 ". "affectConsForecastIdentWeekdays:1,0 ".
"affectConsForecastInPlanning:1,0 ". "affectConsForecastInPlanning:1,0 ".
"affectMaxDayVariance ". "affectMaxDayVariance:obsolete ".
"affectSolCastPercentile:select,10,50,90 ". "affectSolCastPercentile:select,10,50,90 ".
"consumerLegend:none,icon_top,icon_bottom,text_top,text_bottom ". "consumerLegend:none,icon_top,icon_bottom,text_top,text_bottom ".
"consumerAdviceIcon ". "consumerAdviceIcon ".
@ -2652,7 +2654,7 @@ sub Get {
"html:$hol ". "html:$hol ".
"nextHours:noArg ". "nextHours:noArg ".
"pvCircular:noArg ". "pvCircular:noArg ".
"pvHistory:#,$pvl ". "pvHistory:#,exportToCsv,$pvl ".
"rooftopData:noArg ". "rooftopData:noArg ".
"solApiData:noArg ". "solApiData:noArg ".
"valCurrent:noArg " "valCurrent:noArg "
@ -5299,14 +5301,14 @@ sub Attr {
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !! ### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
###################################################################################################################### ######################################################################################################################
#if ($cmd eq 'set' && $aName eq 'affectNumHistDays') { if ($cmd eq 'set' && $aName eq 'affectMaxDayVariance') {
# if (!$init_done) { 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.}; return qq{Device "$name" -> The attribute '$aName' is obsolete and will be deleted soon. Please press "save config" when restart is finished.};
# } }
# else { else {
# return qq{The attribute '$aName' is obsolete and will be deleted soon.}; return qq{The attribute '$aName' is obsolete and will be deleted soon.};
# } }
#} }
###################################################################################################################### ######################################################################################################################
if ($aName eq 'disable') { if ($aName eq 'disable') {
@ -5374,12 +5376,6 @@ sub Attr {
} }
} }
if ($aName eq 'affectMaxDayVariance') {
unless ($aVal =~ /^[0-9.]+$/x) {
return qq{The value for $aName is not valid. Use only numbers with optional decimal places !};
}
}
if ($init_done == 1 && $aName eq "ctrlSolCastAPIoptimizeReq") { if ($init_done == 1 && $aName eq "ctrlSolCastAPIoptimizeReq") {
if (!isSolCastUsed ($hash)) { if (!isSolCastUsed ($hash)) {
return qq{The attribute $aName is only valid for device model "SolCastAPI".}; return qq{The attribute $aName is only valid for device model "SolCastAPI".};
@ -10455,12 +10451,11 @@ sub __calcNewFactor {
$factor = sprintf "%.2f", ($pvrl / $pvfc); $factor = sprintf "%.2f", ($pvrl / $pvfc);
} }
my $maxvar = AttrVal ($name, 'affectMaxDayVariance', $defmaxvar); # max. Korrekturvarianz $factor = 1.00 if(1 * $factor == 0); # 0.00-Werte ignorieren (Schleifengefahr)
$factor = 1.00 if(1 * $factor == 0); # 0.00-Werte ignorieren (Schleifengefahr)
if (abs($factor - $oldfac) > $maxvar) { if (abs($factor - $oldfac) > $defmaxvar) {
$factor = sprintf "%.2f", ($factor > $oldfac ? $oldfac + $maxvar : $oldfac - $maxvar); $factor = sprintf "%.2f", ($factor > $oldfac ? $oldfac + $defmaxvar : $oldfac - $defmaxvar);
Log3 ($name, 3, "$name - new $calc correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h"); Log3 ($name, 3, "$name - new $calc correction factor calculated (limited by maximum Day Variance): $factor (old: $oldfac) for hour: $h");
} }
else { else {
Log3 ($name, 3, "$name - new $calc correction factor for hour $h calculated: $factor (old: $oldfac)"); Log3 ($name, 3, "$name - new $calc correction factor for hour $h calculated: $factor (old: $oldfac)");
@ -14371,11 +14366,17 @@ sub listDataPool {
my $hash = shift; my $hash = shift;
my $htol = shift; my $htol = shift;
my $par = shift // q{}; my $par = shift // q{};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $type = $hash->{TYPE}; my $type = $hash->{TYPE};
my ($sq,$h); my ($sq, $h, $hexp);
my $export = q{};
if ($par eq 'exportToCsv') {
$export = 'csv';
$par = q{};
}
my $sub = sub { my $sub = sub {
my $day = shift; my $day = shift;
@ -14405,7 +14406,35 @@ sub listDataPool {
my $sunaz = HistoryVal ($hash, $day, $key, 'sunaz', '-'); my $sunaz = HistoryVal ($hash, $day, $key, 'sunaz', '-');
my $sunalt = HistoryVal ($hash, $day, $key, 'sunalt', '-'); my $sunalt = HistoryVal ($hash, $day, $key, 'sunalt', '-');
my $don = HistoryVal ($hash, $day, $key, 'DoN', '-'); my $don = HistoryVal ($hash, $day, $key, 'DoN', '-');
if ($export eq 'csv') {
$hexp->{$day}{$key}{PVreal} = $pvrl;
$hexp->{$day}{$key}{PVrealValid} = $pvrlvd;
$hexp->{$day}{$key}{PVforecast} = $pvfc;
$hexp->{$day}{$key}{GridConsumption} = $gcons;
$hexp->{$day}{$key}{Consumption} = $con;
$hexp->{$day}{$key}{confc} = $confc;
$hexp->{$day}{$key}{GridFeedIn} = $gfeedin;
$hexp->{$day}{$key}{WeatherId} = $wid;
$hexp->{$day}{$key}{CoudCover} = $wcc;
$hexp->{$day}{$key}{TotalPrecipitation} = $rr1c;
$hexp->{$day}{$key}{Temperature} = $temp // '';
$hexp->{$day}{$key}{PVCorrectionFactor} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[0];
$hexp->{$day}{$key}{Quality} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[1];
$hexp->{$day}{$key}{DayName} = $dayname // '';
$hexp->{$day}{$key}{Etotal} = $etotal;
$hexp->{$day}{$key}{BatteryInTotal} = $btotin;
$hexp->{$day}{$key}{BatteryIn} = $batin;
$hexp->{$day}{$key}{BatteryOutTotal} = $btotout;
$hexp->{$day}{$key}{BatteryOut} = $batout;
$hexp->{$day}{$key}{BatteryMaxSoc} = $batmsoc;
$hexp->{$day}{$key}{BatterySetSoc} = $batssoc;
$hexp->{$day}{$key}{GlobalRadiation } = $rad1h;
$hexp->{$day}{$key}{SunAzimuth} = $sunaz;
$hexp->{$day}{$key}{SunAltitude} = $sunalt;
$hexp->{$day}{$key}{DayOrNight} = $don;
}
$ret .= "\n " if($ret); $ret .= "\n " if($ret);
$ret .= $key." => "; $ret .= $key." => ";
$ret .= "etotal: $etotal, pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h"; $ret .= "etotal: $etotal, pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h";
@ -14434,6 +14463,14 @@ sub listDataPool {
my $csme = HistoryVal ($hash, $day, $key, "csme${c}", undef); my $csme = HistoryVal ($hash, $day, $key, "csme${c}", undef);
my $csmm = HistoryVal ($hash, $day, $key, "minutescsm${c}", undef); my $csmm = HistoryVal ($hash, $day, $key, "minutescsm${c}", undef);
my $csmh = HistoryVal ($hash, $day, $key, "hourscsme${c}", undef); my $csmh = HistoryVal ($hash, $day, $key, "hourscsme${c}", undef);
if ($export eq 'csv') {
$hexp->{$day}{$key}{"CyclesCsm${c}"} = $csmc if(defined $csmc);
$hexp->{$day}{$key}{"Csmt${c}"} = $csmt if(defined $csmt);
$hexp->{$day}{$key}{"Csme${c}"} = $csme if(defined $csme);
$hexp->{$day}{$key}{"MinutesCsm${c}"} = $csmm if(defined $csmm);
$hexp->{$day}{$key}{"HoursCsme${c}"} = $csmh if(defined $csmh);
}
if (defined $csmc) { if (defined $csmc) {
$csm .= "cyclescsm${c}: $csmc"; $csm .= "cyclescsm${c}: $csmc";
@ -14493,6 +14530,10 @@ sub listDataPool {
next if($par && $idx ne $par); next if($par && $idx ne $par);
$sq .= $idx." => ".$sub->($idx)."\n"; $sq .= $idx." => ".$sub->($idx)."\n";
} }
if ($export eq 'csv') {
return _writeAsCsv ($hash, $hexp, $pvhexprtcsv.$name.'.csv');
}
} }
if ($htol eq "consumer") { if ($htol eq "consumer") {
@ -14829,6 +14870,53 @@ sub _ldpspaces {
return $spn; return $spn;
} }
################################################################
# Export Speicherstruktur in CSV-Datei
################################################################
sub _writeAsCsv {
my $hash = shift;
my $hexp = shift;
my $outfile = shift // return "No file specified for writing data";
my @data;
## Header schreiben
#####################
my @head = qw (Day Hour);
for my $hexd (sort{$a<=>$b} keys %{$hexp}) {
for my $hexh (sort{$a<=>$b} keys %{$hexp->{$hexd}}) {
for my $hk (sort keys %{$hexp->{$hexd}{$hexh}}) {
push @head, $hk;
}
last;
}
last;
}
push @data, join(',', map { s{"}{""}g; qq{"$_"};} @head);
## Daten schreiben
####################
for my $exd (sort{$a<=>$b} keys %{$hexp}) {
for my $exh (sort{$a<=>$b} keys %{$hexp->{$exd}}) {
push my @aexp, ($exd, $exh);
for my $k (sort keys %{$hexp->{$exd}{$exh}}) {
my $val = $hexp->{$exd}{$exh}{$k};
$val =~ s/\./,/xs;
push @aexp, $val;
}
push @data, join(',', map { s{"}{""}g; qq{"$_"};} @aexp);
}
}
my $err = FileWrite ($outfile, @data);
return $err if($err);
return "The memory structure was written to the file $outfile";
}
################################################################ ################################################################
# validiert die aktuelle Anlagenkonfiguration # validiert die aktuelle Anlagenkonfiguration
################################################################ ################################################################
@ -18190,9 +18278,7 @@ to ensure that the system configuration is correct.
<li><b>pvCorrectionFactor_Auto </b> <br><br> <li><b>pvCorrectionFactor_Auto </b> <br><br>
Switches the automatic prediction correction on/off. Switches the automatic prediction correction on/off.
The mode of operation differs depending on the selected method. The mode of operation differs depending on the selected method. <br>
The correction behaviour can be influenced with the
<a href="#SolarForecast-attr-affectMaxDayVariance">affectMaxDayVariance</a> attribute. <br>
(default: off) (default: off)
<br><br> <br><br>
@ -18543,9 +18629,11 @@ to ensure that the system configuration is correct.
<ul> <ul>
<a id="SolarForecast-get-pvHistory"></a> <a id="SolarForecast-get-pvHistory"></a>
<li><b>pvHistory </b> <br><br> <li><b>pvHistory </b> <br><br>
Shows the content of the pvHistory data memory sorted by date and hour. The selection list can be used to jump to a Displays or exports the contents of the pvHistory data memory sorted by date and hour. <br>
specific day. The drop-down list contains the days currently available in the memory. The selection list can be used to jump to a specific day. The drop-down list contains the days currently
available in the memory.
Without an argument, the entire data storage is listed. Without an argument, the entire data storage is listed.
The 'exportToCsv' specification exports the entire content of the pvHistory to a CSV file. <br>
The hour specifications refer to the respective hour of the day, e.g. the hour 09 refers to the time from The hour specifications refer to the respective hour of the day, e.g. the hour 09 refers to the time from
08 o'clock to 09 o'clock. <br><br> 08 o'clock to 09 o'clock. <br><br>
@ -18771,16 +18859,6 @@ to ensure that the system configuration is correct.
</li> </li>
<br> <br>
<a id="SolarForecast-attr-affectMaxDayVariance"></a>
<li><b>affectMaxDayVariance &lt;Zahl&gt; </b><br>
Maximum adjustment of the PV prediction factor (Reading pvCorrectionFactor_XX) that can be made
in relation to one hour per day. <br>
This setting has no influence on the learning and forecasting behavior of any AI support used
(<a href="#SolarForecast-set-pvCorrectionFactor_Auto">pvCorrectionFactor_Auto</a>). <br>
(default: 0.8)
</li>
<br>
<a id="SolarForecast-attr-affectSolCastPercentile"></a> <a id="SolarForecast-attr-affectSolCastPercentile"></a>
<li><b>affectSolCastPercentile &lt;10 | 50 | 90&gt; </b><br> <li><b>affectSolCastPercentile &lt;10 | 50 | 90&gt; </b><br>
(only when using Model SolCastAPI) <br><br> (only when using Model SolCastAPI) <br><br>
@ -20432,8 +20510,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
Schaltet die automatische Vorhersagekorrektur ein/aus. Schaltet die automatische Vorhersagekorrektur ein/aus.
Die Wirkungsweise unterscheidet sich je nach gewählter Methode. <br> Die Wirkungsweise unterscheidet sich je nach gewählter Methode. <br>
Das Korrekturverhalten kann mit dem Attribut
<a href="#SolarForecast-attr-affectMaxDayVariance">affectMaxDayVariance</a> beeinflusst werden. <br>
(default: off) (default: off)
<br><br> <br><br>
@ -20792,9 +20868,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<ul> <ul>
<a id="SolarForecast-get-pvHistory"></a> <a id="SolarForecast-get-pvHistory"></a>
<li><b>pvHistory </b> <br><br> <li><b>pvHistory </b> <br><br>
Zeigt den Inhalt des pvHistory Datenspeichers sortiert nach dem Tagesdatum und Stunde. Mit der Auswahlliste kann ein Zeigt oder exportiert den Inhalt des pvHistory Datenspeichers sortiert nach dem Tagesdatum und Stunde. <br>
bestimmter Tag angesprungen werden. Die Drop-Down Liste enthält die aktuell im Speicher verfügbaren Tage. Mit der Auswahlliste kann ein bestimmter Tag angesprungen werden. Die Drop-Down Liste enthält die aktuell
Ohne Argument wird der gesamte Datenspeicher gelistet. im Speicher verfügbaren Tage.
Ohne Argument wird der gesamte Datenspeicher gelistet.
Die Angabe 'exportToCsv' exportiert den gesamten Inhalt der pvHistory in eine CSV-Datei. <br>
Die Stundenangaben beziehen sich auf die jeweilige Stunde des Tages, z.B. bezieht sich die Stunde 09 auf die Zeit Die Stundenangaben beziehen sich auf die jeweilige Stunde des Tages, z.B. bezieht sich die Stunde 09 auf die Zeit
von 08 Uhr bis 09 Uhr. <br><br> von 08 Uhr bis 09 Uhr. <br><br>
@ -21020,17 +21098,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
</li> </li>
<br> <br>
<a id="SolarForecast-attr-affectMaxDayVariance"></a>
<li><b>affectMaxDayVariance &lt;Zahl&gt; </b><br>
Maximale Anpassung des PV Vorhersagefaktors (Reading pvCorrectionFactor_XX) die bezogen auf eine
Stunde pro Tag vorgenommen werden kann. <br>
Auf das Lern- und Prognoseverhalten einer eventuell verwendeten KI-Unterstützung
(<a href="#SolarForecast-set-pvCorrectionFactor_Auto">pvCorrectionFactor_Auto</a>) hat diese Einstellung keinen
Einfluß. <br>
(default: 0.8)
</li>
<br>
<a id="SolarForecast-attr-affectSolCastPercentile"></a> <a id="SolarForecast-attr-affectSolCastPercentile"></a>
<li><b>affectSolCastPercentile &lt;10 | 50 | 90&gt; </b><br> <li><b>affectSolCastPercentile &lt;10 | 50 | 90&gt; </b><br>
(nur bei Verwendung Model SolCastAPI) <br><br> (nur bei Verwendung Model SolCastAPI) <br><br>