diff --git a/fhem/CHANGED b/fhem/CHANGED
index fbd7eee67..d9c49d2be 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,6 @@
# 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
+ - change: 76_SolarForecast: consumption fc calc switch from average to median
- change: 76_SolarForecast: Attr graphicBeam1MaxVal, ctrlAreaFactorUsage are
obsolete
- bugfix: 76_SolarForecast: fix interruptable key and some minor fixes
diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm
index 82f94da12..27cee9224 100644
--- a/fhem/FHEM/76_SolarForecast.pm
+++ b/fhem/FHEM/76_SolarForecast.pm
@@ -157,6 +157,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.43.3" => "13.01.2025 add Wiki icon in graphic header, _calcConsumptionForecast: switch calc from average to median, edit comref ",
"1.43.2" => "12.01.2025 _batChargeRecmd: bugfix calc socwh, Attr graphicBeam1MaxVal, (experimental) ctrlAreaFactorUsage are obsolete ".
"trackFlex now default in DWD Model, replace title Charging recommendation by Charging release ".
"_saveEnergyConsumption: add dowrite flag, edit comref ",
@@ -254,7 +255,7 @@ my %vNotesIntern = (
"1.33.0" => "26.09.2024 substitute area factor hash by ___areaFactorFix function ",
"1.32.0" => "02.09.2024 new attr setupOtherProducerXX, report calculation and storage of negative consumption values ".
"Forum: https://forum.fhem.de/index.php?msg=1319083 ".
- "bugfix in _estConsumptionForecast, new ctrlDebug consumption_long ",
+ "bugfix in _calcConsumptionForecast, new ctrlDebug consumption_long ",
"1.31.0" => "20.08.2024 rename attributes ctrlWeatherDevX to setupWeatherDevX ",
"1.30.0" => "18.08.2024 new attribute flowGraphicShift, Forum:https://forum.fhem.de/index.php?msg=1318597 ",
"1.29.4" => "03.08.2024 delete writeCacheToFile from _getRoofTopData, _specialActivities: avoid loop caused by \@widgetreadings ",
@@ -487,15 +488,15 @@ my $cfile = 'controls_solarforecast.txt';
# initiale Hashes für Stunden Consumption Forecast inkl. und exkl. Verbraucher
-my $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
+#my $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
+# "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
+# "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
+# };
-my $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
+#my $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
+# "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
+# "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
+# };
# mögliche Debug-Module
my @dd = qw( aiProcess
aiData
@@ -942,6 +943,8 @@ my %htitles = (
DE => qq{Konfigurationsprüfung der Anlage} },
jtsfft => { EN => qq{Open the SolarForecast Forum},
DE => qq{Öffne das SolarForecast Forum} },
+ opwiki => { EN => qq{Open the Wiki (German language)},
+ DE => qq{Öffne das Wiki} },
scaresps => { EN => qq{API request successful},
DE => qq{API Abfrage erfolgreich} },
dwfcrsu => { EN => qq{Weather data are up to date according to used DWD model},
@@ -7555,7 +7558,7 @@ sub centralTask {
_batSocTarget ($centpars); # Batterie Optimum Ziel SOC berechnen
_batChargeRecmd ($centpars); # Batterie Ladefreigabe berechnen und erstellen
_manageConsumerData ($centpars); # Consumer Daten sammeln und Zeiten planen
- _estConsumptionForecast ($centpars); # Verbrauchsprognose erstellen
+ _calcConsumptionForecast ($centpars); # Verbrauchsprognose erstellen
_evaluateThresholds ($centpars); # Schwellenwerte bewerten und signalisieren
_calcReadingsTomorrowPVFc ($centpars); # zusätzliche Readings Tomorrow_HourXX_PVforecast berechnen
_calcTodayPVdeviation ($centpars); # Vorhersageabweichung erstellen (nach Sonnenuntergang)
@@ -11812,7 +11815,7 @@ return ($simpCstat, $starttime, $stoptime, $supplmnt);
################################################################
# Energieverbrauch Vorhersage kalkulieren
################################################################
-sub _estConsumptionForecast {
+sub _calcConsumptionForecast {
my $paref = shift;
my $name = $paref->{name};
my $type = $paref->{type};
@@ -11840,10 +11843,7 @@ sub _estConsumptionForecast {
## Verbrauchsvorhersage für den kommenden Tag
##############################################
my $tomorrow = strftime "%a", localtime($t+86400); # Wochentagsname kommender Tag
- my $totcon = 0;
- my $dnum = 0;
-
- my ($exconfc, $csme);
+ my (@cona, $exconfc, $csme);
debugLog ($paref, 'consumption|consumption_long', "################### Consumption forecast for the next day ###################");
debugLog ($paref, 'consumption|consumption_long', "Date(s) to take note: ".join ',', @dtn) if(@dtn);
@@ -11882,15 +11882,16 @@ sub _estConsumptionForecast {
debugLog ($paref, 'consumption|consumption_long', "History Consumption day >$n< considering possible exclusions: $dcon");
- $totcon += $dcon;
- $dnum++;
+ push @cona, $dcon;
}
+ my $dnum = scalar @cona;
+
if ($dnum) {
- my $tomavg = int ($totcon / $dnum);
- $data{$name}{current}{tomorrowconsumption} = $tomavg; # prognostizierter Durchschnittsverbrauch aller (gleicher) Wochentage
+ my $tomcon = sprintf "%.0f", medianArray (\@cona);
+ $data{$name}{current}{tomorrowconsumption} = $tomcon; # prognostizierter Verbrauch (Median) aller (gleicher) Wochentage
- debugLog ($paref, 'consumption|consumption_long', "estimated Consumption for tomorrow: $tomavg, days for avg: $dnum");
+ debugLog ($paref, 'consumption|consumption_long', "estimated Consumption for tomorrow: $tomcon, days for avg: $dnum");
}
else {
my $lang = $paref->{lang};
@@ -11906,22 +11907,14 @@ sub _estConsumptionForecast {
my $nhtime = NexthoursVal ($hash, $k, "starttime", undef); # Startzeit
next if(!$nhtime);
- $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
-
- $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
-
$dnum = 0;
my $consumerco = 0;
my $utime = timestringToTimestamp ($nhtime);
my $nhday = strftime "%a", localtime($utime); # Wochentagsname des NextHours Key
my $nhhr = sprintf("%02d", (int (strftime "%H", localtime($utime))) + 1); # Stunde des Tages vom NextHours Key (01,02,...24)
+ my ($conhfc, $conhfcex);
+
for my $m (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) {
next if($m eq $day); # next wenn gleicher Tag (Datum) wie heute
@@ -11966,18 +11959,19 @@ sub _estConsumptionForecast {
}
}
- $conhfcex->{$nhhr} += ($hcon - $consumerco) if($hcon >= $consumerco); # prognostizierter Verbrauch Ex registrierter Verbraucher
- $conhfc->{$nhhr} += $hcon;
+ push @{$conhfcex->{"$nhhr"}}, ($hcon - $consumerco) if($hcon >= $consumerco); # prognostizierter Verbrauch (Median) Ex registrierter Verbraucher
+ push @{$conhfc->{"$nhhr"}}, $hcon;
+
$dnum++;
}
if ($dnum) {
- my $conavgex = int ($conhfcex->{$nhhr} / $dnum);
+ my $conavgex = sprintf "%.0f", medianArray (\@{$conhfcex->{$nhhr}}) if(scalar @{$conhfcex->{$nhhr}});
$data{$name}{nexthours}{$k}{confcEx} = $conavgex;
- my $conavg = int ($conhfc->{$nhhr} / $dnum);
- $data{$name}{nexthours}{$k}{confc} = $conavg; # Durchschnittsverbrauch aller gleicher Wochentage pro Stunde
+ my $conavg = sprintf "%.0f", medianArray (\@{$conhfc->{$nhhr}}) if(scalar @{$conhfc->{$nhhr}});
+ $data{$name}{nexthours}{$k}{confc} = $conavg; # prognostizierter Verbrauch (Median) auf Grundlage aller gleicher Wochentage pro Stunde
- if (NexthoursVal ($hash, $k, 'today', 0)) { # nur Werte des aktuellen Tag speichern
+ if (NexthoursVal ($hash, $k, 'today', 0)) { # nur Werte des aktuellen Tag speichern
$data{$name}{circular}{sprintf("%02d",$nhhr)}{confc} = $conavg;
writeToHistory ( { paref => $paref, key => 'confc', val => $conavg, hour => $nhhr } );
}
@@ -13283,6 +13277,12 @@ sub _graphicHeader {
$img = FW_makeImage('time_note@grey');
my $fthicon = "$img";
my $fthtitle = $htitles{jtsfft}{$lang};
+
+ ## Wiki-Icon
+ ##############
+ $img = FW_makeImage ('edit_copy@grey');
+ my $wikicon = "$img";
+ my $wiktitle = $htitles{opwiki}{$lang};
## Update-Icon
################
@@ -13494,13 +13494,14 @@ sub _graphicHeader {
#######################
my $alias = AttrVal ($name, "alias", $name ); # Linktext als Aliasname
my $dlink = qq{$alias};
-
+ my $space = ' ';
+ my $disti = qq{ $chkicon $space $fthicon $space $wikicon };
+
$header .= qq{
};
- $header .= qq{ $dlink | };
- $header .= qq{ $chkicon | };
- $header .= qq{ $fthicon | };
- $header .= qq{ $lupt $lup $upicon | };
- $header .= qq{ $api | };
+ $header .= qq{ $dlink | };
+ $header .= qq{ $disti | };
+ $header .= qq{ $lupt $lup $upicon | };
+ $header .= qq{ $api | };
$header .= qq{
};
$header .= qq{};
$header .= qq{ $sriseimg $srisetxt $ssetimg $ssettxt $waicon | };
@@ -22418,14 +22419,15 @@ to ensure that the system configuration is correct.
- lowSoc | lower minimum SoC, the battery is not discharged lower than this value (> 0) |
- upSoC | upper minimum SoC, the usual value of the optimum SoC is between 'lowSoC' |
- | and this value. |
- maxSoC | Maximum minimum SoC, SoC value that must be reached at least every 'careCycle' days |
- | in order to balance the charge in the storage network. |
- | The specification is optional (<= 100, default: 95) |
- careCycle | Maximum interval in days that may occur between two states of charge |
- | of at least 'maxSoC'. The specification is optional (default: 20) |
+ lowSoc | lower minimum SoC - The battery is not discharged lower than this value (> 0) |
+ upSoC | upper minimum SoC - The usual value of the optimum SoC tends to be |
+ | between 'lowSoC' and 'upSoC' in periods with a high PV surplus |
+ | and between 'upSoC' and 'maxSoC' in periods with a low PV surplus |
+ maxSoC | Maximum minimum SoC - SoC value that must be reached at least every 'careCycle' days |
+ | in order to balance the charge in the storage network. |
+ | The specification is optional (<= 100, default: 95) |
+ careCycle | Maximum interval in days that may occur between two states of charge |
+ | of at least 'maxSoC'. The specification is optional (default: 20) |
@@ -24886,14 +24888,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- lowSoc | unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (> 0) |
- upSoC | oberer Mindest-SoC, der übliche Wert des optimalen SoC bewegt sich zwischen 'lowSoC' |
- | und diesem Wert. |
- maxSoC | maximaler Mindest-SoC, SoC Wert der mindestens im Abstand von 'careCycle' Tagen erreicht |
- | werden muß um den Ladungsausgleich im Speicherverbund auszuführen. |
- | Die Angabe ist optional (<= 100, default: 95) |
- careCycle | maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' |
- | auftreten darf. Die Angabe ist optional (default: 20) |
+ lowSoc | unterer Mindest-SoC - Die Batterie wird nicht tiefer als dieser Wert entladen (> 0) |
+ upSoC | oberer Mindest-SoC - Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen |
+ | PV-Überschuß tendenziell zwischen 'lowSoC' und 'upSoC', in Perioden mit geringem PV-Überschuß |
+ | tendenziell zwischen 'upSoC' und 'maxSoC' |
+ maxSoC | maximaler Mindest-SoC - SoC Wert der mindestens im Abstand von 'careCycle' Tagen erreicht |
+ | werden muß um den Ladungsausgleich im Speicherverbund auszuführen. |
+ | Die Angabe ist optional (<= 100, default: 95) |
+ careCycle | maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' |
+ | auftreten darf. Die Angabe ist optional (default: 20) |
diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index 3ecfa7466..27cee9224 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -157,6 +157,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.43.3" => "13.01.2025 add Wiki icon in graphic header, _calcConsumptionForecast: switch calc from average to median, edit comref ",
"1.43.2" => "12.01.2025 _batChargeRecmd: bugfix calc socwh, Attr graphicBeam1MaxVal, (experimental) ctrlAreaFactorUsage are obsolete ".
"trackFlex now default in DWD Model, replace title Charging recommendation by Charging release ".
"_saveEnergyConsumption: add dowrite flag, edit comref ",
@@ -254,7 +255,7 @@ my %vNotesIntern = (
"1.33.0" => "26.09.2024 substitute area factor hash by ___areaFactorFix function ",
"1.32.0" => "02.09.2024 new attr setupOtherProducerXX, report calculation and storage of negative consumption values ".
"Forum: https://forum.fhem.de/index.php?msg=1319083 ".
- "bugfix in _estConsumptionForecast, new ctrlDebug consumption_long ",
+ "bugfix in _calcConsumptionForecast, new ctrlDebug consumption_long ",
"1.31.0" => "20.08.2024 rename attributes ctrlWeatherDevX to setupWeatherDevX ",
"1.30.0" => "18.08.2024 new attribute flowGraphicShift, Forum:https://forum.fhem.de/index.php?msg=1318597 ",
"1.29.4" => "03.08.2024 delete writeCacheToFile from _getRoofTopData, _specialActivities: avoid loop caused by \@widgetreadings ",
@@ -487,15 +488,15 @@ my $cfile = 'controls_solarforecast.txt';
# initiale Hashes für Stunden Consumption Forecast inkl. und exkl. Verbraucher
-my $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
+#my $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
+# "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
+# "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
+# };
-my $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
+#my $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
+# "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
+# "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
+# };
# mögliche Debug-Module
my @dd = qw( aiProcess
aiData
@@ -942,6 +943,8 @@ my %htitles = (
DE => qq{Konfigurationsprüfung der Anlage} },
jtsfft => { EN => qq{Open the SolarForecast Forum},
DE => qq{Öffne das SolarForecast Forum} },
+ opwiki => { EN => qq{Open the Wiki (German language)},
+ DE => qq{Öffne das Wiki} },
scaresps => { EN => qq{API request successful},
DE => qq{API Abfrage erfolgreich} },
dwfcrsu => { EN => qq{Weather data are up to date according to used DWD model},
@@ -7555,7 +7558,7 @@ sub centralTask {
_batSocTarget ($centpars); # Batterie Optimum Ziel SOC berechnen
_batChargeRecmd ($centpars); # Batterie Ladefreigabe berechnen und erstellen
_manageConsumerData ($centpars); # Consumer Daten sammeln und Zeiten planen
- _estConsumptionForecast ($centpars); # Verbrauchsprognose erstellen
+ _calcConsumptionForecast ($centpars); # Verbrauchsprognose erstellen
_evaluateThresholds ($centpars); # Schwellenwerte bewerten und signalisieren
_calcReadingsTomorrowPVFc ($centpars); # zusätzliche Readings Tomorrow_HourXX_PVforecast berechnen
_calcTodayPVdeviation ($centpars); # Vorhersageabweichung erstellen (nach Sonnenuntergang)
@@ -11812,7 +11815,7 @@ return ($simpCstat, $starttime, $stoptime, $supplmnt);
################################################################
# Energieverbrauch Vorhersage kalkulieren
################################################################
-sub _estConsumptionForecast {
+sub _calcConsumptionForecast {
my $paref = shift;
my $name = $paref->{name};
my $type = $paref->{type};
@@ -11840,10 +11843,7 @@ sub _estConsumptionForecast {
## Verbrauchsvorhersage für den kommenden Tag
##############################################
my $tomorrow = strftime "%a", localtime($t+86400); # Wochentagsname kommender Tag
- my $totcon = 0;
- my $dnum = 0;
-
- my ($exconfc, $csme);
+ my (@cona, $exconfc, $csme);
debugLog ($paref, 'consumption|consumption_long', "################### Consumption forecast for the next day ###################");
debugLog ($paref, 'consumption|consumption_long', "Date(s) to take note: ".join ',', @dtn) if(@dtn);
@@ -11882,15 +11882,16 @@ sub _estConsumptionForecast {
debugLog ($paref, 'consumption|consumption_long', "History Consumption day >$n< considering possible exclusions: $dcon");
- $totcon += $dcon;
- $dnum++;
+ push @cona, $dcon;
}
+ my $dnum = scalar @cona;
+
if ($dnum) {
- my $tomavg = int ($totcon / $dnum);
- $data{$name}{current}{tomorrowconsumption} = $tomavg; # prognostizierter Durchschnittsverbrauch aller (gleicher) Wochentage
+ my $tomcon = sprintf "%.0f", medianArray (\@cona);
+ $data{$name}{current}{tomorrowconsumption} = $tomcon; # prognostizierter Verbrauch (Median) aller (gleicher) Wochentage
- debugLog ($paref, 'consumption|consumption_long', "estimated Consumption for tomorrow: $tomavg, days for avg: $dnum");
+ debugLog ($paref, 'consumption|consumption_long', "estimated Consumption for tomorrow: $tomcon, days for avg: $dnum");
}
else {
my $lang = $paref->{lang};
@@ -11906,22 +11907,14 @@ sub _estConsumptionForecast {
my $nhtime = NexthoursVal ($hash, $k, "starttime", undef); # Startzeit
next if(!$nhtime);
- $conhfc = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
-
- $conhfcex = { "01" => 0, "02" => 0, "03" => 0, "04" => 0, "05" => 0, "06" => 0, "07" => 0, "08" => 0,
- "09" => 0, "10" => 0, "11" => 0, "12" => 0, "13" => 0, "14" => 0, "15" => 0, "16" => 0,
- "17" => 0, "18" => 0, "19" => 0, "20" => 0, "21" => 0, "22" => 0, "23" => 0, "24" => 0,
- };
-
$dnum = 0;
my $consumerco = 0;
my $utime = timestringToTimestamp ($nhtime);
my $nhday = strftime "%a", localtime($utime); # Wochentagsname des NextHours Key
my $nhhr = sprintf("%02d", (int (strftime "%H", localtime($utime))) + 1); # Stunde des Tages vom NextHours Key (01,02,...24)
+ my ($conhfc, $conhfcex);
+
for my $m (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) {
next if($m eq $day); # next wenn gleicher Tag (Datum) wie heute
@@ -11966,18 +11959,19 @@ sub _estConsumptionForecast {
}
}
- $conhfcex->{$nhhr} += ($hcon - $consumerco) if($hcon >= $consumerco); # prognostizierter Verbrauch Ex registrierter Verbraucher
- $conhfc->{$nhhr} += $hcon;
+ push @{$conhfcex->{"$nhhr"}}, ($hcon - $consumerco) if($hcon >= $consumerco); # prognostizierter Verbrauch (Median) Ex registrierter Verbraucher
+ push @{$conhfc->{"$nhhr"}}, $hcon;
+
$dnum++;
}
if ($dnum) {
- my $conavgex = int ($conhfcex->{$nhhr} / $dnum);
+ my $conavgex = sprintf "%.0f", medianArray (\@{$conhfcex->{$nhhr}}) if(scalar @{$conhfcex->{$nhhr}});
$data{$name}{nexthours}{$k}{confcEx} = $conavgex;
- my $conavg = int ($conhfc->{$nhhr} / $dnum);
- $data{$name}{nexthours}{$k}{confc} = $conavg; # Durchschnittsverbrauch aller gleicher Wochentage pro Stunde
+ my $conavg = sprintf "%.0f", medianArray (\@{$conhfc->{$nhhr}}) if(scalar @{$conhfc->{$nhhr}});
+ $data{$name}{nexthours}{$k}{confc} = $conavg; # prognostizierter Verbrauch (Median) auf Grundlage aller gleicher Wochentage pro Stunde
- if (NexthoursVal ($hash, $k, 'today', 0)) { # nur Werte des aktuellen Tag speichern
+ if (NexthoursVal ($hash, $k, 'today', 0)) { # nur Werte des aktuellen Tag speichern
$data{$name}{circular}{sprintf("%02d",$nhhr)}{confc} = $conavg;
writeToHistory ( { paref => $paref, key => 'confc', val => $conavg, hour => $nhhr } );
}
@@ -13283,6 +13277,12 @@ sub _graphicHeader {
$img = FW_makeImage('time_note@grey');
my $fthicon = "$img";
my $fthtitle = $htitles{jtsfft}{$lang};
+
+ ## Wiki-Icon
+ ##############
+ $img = FW_makeImage ('edit_copy@grey');
+ my $wikicon = "$img";
+ my $wiktitle = $htitles{opwiki}{$lang};
## Update-Icon
################
@@ -13494,13 +13494,14 @@ sub _graphicHeader {
#######################
my $alias = AttrVal ($name, "alias", $name ); # Linktext als Aliasname
my $dlink = qq{$alias};
-
+ my $space = ' ';
+ my $disti = qq{ $chkicon $space $fthicon $space $wikicon };
+
$header .= qq{
};
- $header .= qq{ $dlink | };
- $header .= qq{ $chkicon | };
- $header .= qq{ $fthicon | };
- $header .= qq{ $lupt $lup $upicon | };
- $header .= qq{ $api | };
+ $header .= qq{ $dlink | };
+ $header .= qq{ $disti | };
+ $header .= qq{ $lupt $lup $upicon | };
+ $header .= qq{ $api | };
$header .= qq{
};
$header .= qq{};
$header .= qq{ $sriseimg $srisetxt $ssetimg $ssettxt $waicon | };
@@ -15459,7 +15460,7 @@ END0
$cc_dummy -= $currentPower;
$cicon = FW_makeImage ($cicon, '');
- ($scale, $cicon) = __normIconScale ($cicon, $name);
+ ($scale, $cicon) = __normIconScale ($name, $cicon);
$ret .= qq{};
$ret .= "$calias".$cicon;
@@ -15488,7 +15489,7 @@ END1
## Home Icon
##############
my $hicon = FW_makeImage ($homeicondef, '');
- ($scale, $hicon) = __normIconScale ($hicon, $name);
+ ($scale, $hicon) = __normIconScale ($name, $hicon);
$ret .= qq{}; # translate(X-Koordinate,Y-Koordinate), scale()-> Koordinaten ändern sich bei Größenänderung
$ret .= "Home".$hicon;
@@ -15500,7 +15501,7 @@ END1
my $dumtxt = $htitles{dumtxt}{$lang};
my $dumcol = $cc_dummy <= 0 ? '@grey' : q{}; # Einfärbung Consumer Dummy
my $dicon = FW_makeImage ($cicondef.$dumcol, '');
- ($scale, $dicon) = __normIconScale ($dicon, $name);
+ ($scale, $dicon) = __normIconScale ($name, $dicon);
$ret .= qq{};
$ret .= "$dumtxt".$dicon;
@@ -15810,7 +15811,7 @@ sub __addProducerIcon {
);
$picon = FW_makeImage ($picon, '');
- ($scale, $picon) = __normIconScale ($picon, $name);
+ ($scale, $picon) = __normIconScale ($name, $picon);
$ret .= qq{};
$ret .= "$ptxt".$picon;
@@ -15847,7 +15848,7 @@ sub __addNodeIcon {
);
$nicon = FW_makeImage ($nicon, '');
- ($scale, $nicon) = __normIconScale ($nicon, $name);
+ ($scale, $nicon) = __normIconScale ($name, $nicon);
my $ret = qq{}; # translate(X-Koordinate,Y-Koordinate), scale()-> Koordinaten ändern sich bei Größenänderung
$ret .= "$ntxt".$nicon;
@@ -16034,8 +16035,9 @@ return $p;
# scale: 0.10 Normativ $fgscaledef
################################################################
sub __normIconScale {
- my $icon = shift;
my $name = shift;
+ my $icon = shift;
+ my $dim = shift // 470; # Dimension
my $hscale = $fgscaledef; # Scale Normativ
my $wscale = $fgscaledef;
@@ -16044,27 +16046,27 @@ sub __normIconScale {
return ($hscale, $icon) if(!$width || !$height);
- $wscale = $hunit eq 'pt' ? 470 * $wscale / $width :
- $hunit eq 'px' ? 470 * $wscale / $width * 0.96 :
- $hunit eq 'in' ? 470 * $wscale / $width * 0.0138889 :
- $hunit eq 'mm' ? 470 * $wscale / $width * 0.352778 :
- $hunit eq 'cm' ? 470 * $wscale / $width * 0.0352778 :
- $hunit eq 'pc' ? 470 * $wscale / $width * 0.0833333 :
+ $wscale = $hunit eq 'pt' ? $dim * $wscale / $width :
+ $hunit eq 'px' ? $dim * $wscale / $width * 0.96 :
+ $hunit eq 'in' ? $dim * $wscale / $width * 0.0138889 :
+ $hunit eq 'mm' ? $dim * $wscale / $width * 0.352778 :
+ $hunit eq 'cm' ? $dim * $wscale / $width * 0.0352778 :
+ $hunit eq 'pc' ? $dim * $wscale / $width * 0.0833333 :
$wscale;
- $hscale = $hunit eq 'pt' ? 470 * $hscale / $height :
- $hunit eq 'px' ? 470 * $hscale / $height * 0.96 :
- $hunit eq 'in' ? 470 * $hscale / $height * 0.0138889 :
- $hunit eq 'mm' ? 470 * $hscale / $height * 0.352778 :
- $hunit eq 'cm' ? 470 * $hscale / $height * 0.0352778 :
- $hunit eq 'pc' ? 470 * $hscale / $height * 0.0833333 :
+ $hscale = $hunit eq 'pt' ? $dim * $hscale / $height :
+ $hunit eq 'px' ? $dim * $hscale / $height * 0.96 :
+ $hunit eq 'in' ? $dim * $hscale / $height * 0.0138889 :
+ $hunit eq 'mm' ? $dim * $hscale / $height * 0.352778 :
+ $hunit eq 'cm' ? $dim * $hscale / $height * 0.0352778 :
+ $hunit eq 'pc' ? $dim * $hscale / $height * 0.0833333 :
$hscale;
$wscale = sprintf "%.2f", $wscale;
$hscale = sprintf "%.2f", $hscale;
- my $widthnormpt = (sprintf "%.0f", (470 * (1 + $wscale))).'pt'; # Breite auf Normativ in pt skaliert
- my $heightnormpt = (sprintf "%.0f", (470 * (1 + $hscale))).'pt'; # Höhe auf Normativ in pt skaliert
+ my $widthnormpt = (sprintf "%.0f", ($dim * (1 + $wscale))).'pt'; # Breite auf Normativ in pt skaliert
+ my $heightnormpt = (sprintf "%.0f", ($dim * (1 + $hscale))).'pt'; # Höhe auf Normativ in pt skaliert
$icon =~ s/width="(.*?)"/width="$widthnormpt"/;
$icon =~ s/height="(.*?)"/height="$heightnormpt"/;
@@ -22417,14 +22419,15 @@ to ensure that the system configuration is correct.
- lowSoc | lower minimum SoC, the battery is not discharged lower than this value (> 0) |
- upSoC | upper minimum SoC, the usual value of the optimum SoC is between 'lowSoC' |
- | and this value. |
- maxSoC | Maximum minimum SoC, SoC value that must be reached at least every 'careCycle' days |
- | in order to balance the charge in the storage network. |
- | The specification is optional (<= 100, default: 95) |
- careCycle | Maximum interval in days that may occur between two states of charge |
- | of at least 'maxSoC'. The specification is optional (default: 20) |
+ lowSoc | lower minimum SoC - The battery is not discharged lower than this value (> 0) |
+ upSoC | upper minimum SoC - The usual value of the optimum SoC tends to be |
+ | between 'lowSoC' and 'upSoC' in periods with a high PV surplus |
+ | and between 'upSoC' and 'maxSoC' in periods with a low PV surplus |
+ maxSoC | Maximum minimum SoC - SoC value that must be reached at least every 'careCycle' days |
+ | in order to balance the charge in the storage network. |
+ | The specification is optional (<= 100, default: 95) |
+ careCycle | Maximum interval in days that may occur between two states of charge |
+ | of at least 'maxSoC'. The specification is optional (default: 20) |
@@ -24885,14 +24888,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- lowSoc | unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (> 0) |
- upSoC | oberer Mindest-SoC, der übliche Wert des optimalen SoC bewegt sich zwischen 'lowSoC' |
- | und diesem Wert. |
- maxSoC | maximaler Mindest-SoC, SoC Wert der mindestens im Abstand von 'careCycle' Tagen erreicht |
- | werden muß um den Ladungsausgleich im Speicherverbund auszuführen. |
- | Die Angabe ist optional (<= 100, default: 95) |
- careCycle | maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' |
- | auftreten darf. Die Angabe ist optional (default: 20) |
+ lowSoc | unterer Mindest-SoC - Die Batterie wird nicht tiefer als dieser Wert entladen (> 0) |
+ upSoC | oberer Mindest-SoC - Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen |
+ | PV-Überschuß tendenziell zwischen 'lowSoC' und 'upSoC', in Perioden mit geringem PV-Überschuß |
+ | tendenziell zwischen 'upSoC' und 'maxSoC' |
+ maxSoC | maximaler Mindest-SoC - SoC Wert der mindestens im Abstand von 'careCycle' Tagen erreicht |
+ | werden muß um den Ladungsausgleich im Speicherverbund auszuführen. |
+ | Die Angabe ist optional (<= 100, default: 95) |
+ careCycle | maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' |
+ | auftreten darf. Die Angabe ist optional (default: 20) |