diff --git a/fhem/CHANGED b/fhem/CHANGED index ebf76f1a0..d984bde2c 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # 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 + - feature: 76_SolarForecast: in setupStringDeclination integers between + 0 and 90 can now be freely specified - feature: 98_vitoconnect.pm: introduced set clearMappedErrors - bugfix: 98_vitoconnect.pm: fixed undef warning thanks cnkru - feature: 76_SolarForecast: new Version 1.46.0, diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 98b2f5add..1f89876ce 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -159,6 +159,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.46.1" => "18.02.2025 improve temp2bin, correct Log output to consumptionHistory, set setupStringDeclination can be free integer between 0..90 ", "1.46.0" => "17.02.2025 Notification System: print out last/next file pull if no messages are present, improvements and activation of ". "_calcConsForecast_circular, checkPlantConfig: add Data Memory check pvHistory 'con' ". "sunalt2bin/cloud2bin: classification of values improved, affectConsForecastLastDays: max to 180 ". @@ -1970,9 +1971,6 @@ sub _setstringDeclination { ## no critic "not used" my $name = $paref->{name}; my $arg = $paref->{arg} // return qq{no tilt angle was provided}; - # my $tilt = join "|", sort keys %hff; - my $atilt = '0|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90'; - my ($a,$h) = parseParams ($arg); if (!keys %$h) { @@ -1980,7 +1978,7 @@ sub _setstringDeclination { ## no critic "not used" } while (my ($key, $value) = each %$h) { - if ($value !~ /^(?:$atilt)$/x) { + if ($value !~ /^(?:[0-9]{1,2})$/x || $value > 90) { return qq{The inclination angle of "$key" is incorrect}; } } @@ -7711,7 +7709,6 @@ sub centralTask { _batSocTarget ($centpars); # Batterie Optimum Ziel SOC berechnen _batChargeRecmd ($centpars); # Batterie Ladefreigabe berechnen und erstellen _manageConsumerData ($centpars); # Consumer Daten sammeln und Zeiten planen - # _calcConsumptionForecast ($centpars); # Verbrauchsprognose erstellen _calcConsForecast_circular ($centpars); # neue Verbrauchsprognose über pvCircular @@ -11997,177 +11994,6 @@ sub __getPlanningStateAndTimes { return ($simpCstat, $starttime, $stoptime, $supplmnt); } -################################################################ -# Energieverbrauch Vorhersage kalkulieren -################################################################ -sub _calcConsumptionForecast { - my $paref = shift; - my $name = $paref->{name}; - my $type = $paref->{type}; - my $chour = $paref->{chour}; - my $t = $paref->{t}; - my $day = $paref->{day}; # aktuelles Tagdatum (01...31) - my $dayname = $paref->{dayname}; # aktueller Tagname - - my $hash = $defs{$name}; - my $acref = $data{$name}{consumers}; - my $swdfcfc = AttrVal ($name, 'affectConsForecastIdentWeekdays', 0); # nutze nur gleiche Wochentage (Mo...So) für Verbrauchsvorhersage - - ## Beachtung der letzten X Tage falls gesetzt - ############################################### - my $acld = AttrVal ($name, 'affectConsForecastLastDays', 0); - my @dtn; # Array der zu beachtenden Tage - - if ($acld) { - for my $l (1..$acld) { - my $dday = strftime "%d", localtime($t - $l * 86400); # resultierender Tag (range 01..) - push @dtn, $dday; - } - } - - ## Verbrauchsvorhersage für den kommenden Tag - ############################################## - my $tomorrow = strftime "%a", localtime($t+86400); # Wochentagsname kommender Tag - 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); - - for my $n (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) { - next if ($n eq $day); # aktuellen (unvollständigen) Tag nicht berücksichtigen - - if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen - my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef); - next if(!$hdn || $hdn ne $tomorrow); - } - - if (@dtn) { - if (!grep /^$n$/, @dtn) { - debugLog ($paref, 'consumption|consumption_long', "Day >$n< should not be observed, ignore it."); - next; - } - } - - my $dcon = HistoryVal ($hash, $n, 99, 'con', 0); - - if (!$dcon) { - debugLog ($paref, 'consumption|consumption_long', "Day >$n< has no registered consumption, ignore it."); - next; - } - - for my $c (sort{$a<=>$b} keys %{$acref}) { # historischer Verbrauch aller registrierten Verbraucher aufaddieren - $exconfc = ConsumerVal ($hash, $c, 'exconfc', 0); # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen - $csme = HistoryVal ($hash, $n, 99, "csme${c}", 0); - - if ($exconfc) { - $dcon -= $csme; - debugLog ($paref, 'consumption|consumption_long', "Consumer '$c' values excluded from forecast calc by 'exconfc' - day: $n, csme: $csme"); - } - } - - debugLog ($paref, 'consumption|consumption_long', "History Consumption day >$n< considering possible exclusions: $dcon"); - - push @cona, $dcon; - } - - my $dnum = scalar @cona; - - if ($dnum) { - 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: $tomcon, days for median: $dnum"); - } - else { - my $lang = $paref->{lang}; - $data{$name}{current}{tomorrowconsumption} = $hqtxt{wfmdcf}{$lang}; - } - - ## Verbrauchsvorhersage für die kommenden Stunden - ################################################## - debugLog ($paref, 'consumption|consumption_long', "################### Consumption forecast for the next hours ###################"); - debugLog ($paref, 'consumption|consumption_long', "Date(s) to take note: ".join ',', @dtn) if(@dtn); - - for my $k (sort keys %{$data{$name}{nexthours}}) { - my $nhtime = NexthoursVal ($hash, $k, "starttime", undef); # Startzeit - next if(!$nhtime); - - $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 - - if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen - my $hdn = HistoryVal ($hash, $m, 99, 'dayname', undef); - next if(!$hdn || $hdn ne $nhday); - } - - if (@dtn) { - if (!grep /^$m$/, @dtn) { - debugLog ($paref, 'consumption|consumption_long', "Day >$m< should not be observed, ignore it."); - next; - } - } - - my $hcon = HistoryVal ($hash, $m, $nhhr, 'con', 0); # historische Verbrauchswerte - next if(!$hcon); - - debugLog ($paref, 'consumption_long', " historical Consumption added for $nhday -> date: $m, hod: $nhhr -> $hcon Wh"); - - if ($hcon < 0) { # V1.32.0 - my $vl = 3; - my $pre = '- WARNING -'; - - if ($paref->{debug} =~ /consumption/xs) { - $vl = 1; - $pre = 'DEBUG> - WARNING -'; - } - - Log3 ($name, $vl, "$name $pre The stored Energy consumption of day/hour $m/$nhhr is negative. This appears to be an error. The incorrect value can be deleted with 'set $name reset consumption $m $nhhr'."); - } - - for my $c (sort{$a<=>$b} keys %{$acref}) { # historischen Verbrauch aller registrierten Verbraucher aufaddieren - $exconfc = ConsumerVal ($hash, $c, 'exconfc', 0); # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen - $csme = HistoryVal ($hash, $m, $nhhr, "csme${c}", 0); - $consumerco += $csme; - - if ($exconfc) { - debugLog ($paref, 'consumption_long', "Consumer '$c' values excluded from forecast calc by 'exconfc' - day: $m, hour: $nhhr, csme: $csme"); - $consumerco -= $csme; # V1.32.0 - $hcon -= $csme; # V1.32.0, excludierte Verbraucherconsumption von Forecast ausschließen - } - } - - push @conhfcex, ($hcon - $consumerco) if($hcon >= $consumerco); # prognostizierter Verbrauch (Median) Ex registrierter Verbraucher - push @conhfc, $hcon; - - $dnum++; - } - - if ($dnum) { - my $conavgex = sprintf "%.0f", medianArray (\@conhfcex) if(scalar @conhfcex); - $data{$name}{nexthours}{$k}{confcEx} = $conavgex; - my $conavg = sprintf "%.0f", medianArray (\@conhfc) if(scalar @conhfc); - $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 - $data{$name}{circular}{sprintf("%02d",$nhhr)}{confc} = $conavg; - writeToHistory ( { paref => $paref, key => 'confc', val => $conavg, hour => $nhhr } ); - } - - debugLog ($paref, 'consumption|consumption_long', "estimated Consumption for $nhday -> starttime: $nhtime, confc: $conavg, days for avg: $dnum, hist. consumption registered consumers: ".sprintf "%.2f", $consumerco); - } - } - -return; -} - ################################################################ # Energieverbrauch Vorhersage kalkulieren (Median) ################################################################ @@ -19365,7 +19191,7 @@ sub checkPlantConfig { if ($hcon < 0) { # V1.45.7 $confault++; - Log3 ($name, 1, "$name - WARNING - The stored Energy consumption of day/hour $dy/$hh is negative. This appears to be an error. The incorrect value can be deleted with 'set $name reset consumption $dy $hh'."); + Log3 ($name, 1, "$name - WARNING - The stored Energy consumption of day/hour $dy/$hh is negative. This appears to be an error. The incorrect value can be deleted with 'set $name reset consumptionHistory $dy $hh'."); } } } @@ -21216,28 +21042,28 @@ return ($rapi, $wapi); sub temp2bin { my $val = shift; - my $bin = $val > 35 ? 35 : - $val > 32 ? 35 : - $val > 30 ? 30 : - $val > 27 ? 30 : - $val > 25 ? 25 : - $val > 22 ? 25 : - $val > 20 ? 20 : - $val > 17 ? 20 : - $val > 15 ? 15 : - $val > 12 ? 15 : - $val > 10 ? 10 : - $val > 7 ? 10 : - $val > 5 ? 5 : - $val > 2 ? 5 : - $val > 0 ? 0 : - $val > -2 ? 0 : - $val > -5 ? -5 : - $val > -7 ? -5 : - $val > -10 ? -10 : - $val > -12 ? -10 : - $val > -15 ? -15 : - $val > -17 ? -15 : + my $bin = $val >= 35 ? 35 : + $val > 32 ? 35 : + $val >= 30 ? 30 : + $val > 27 ? 30 : + $val >= 25 ? 25 : + $val > 22 ? 25 : + $val >= 20 ? 20 : + $val > 17 ? 20 : + $val >= 15 ? 15 : + $val > 12 ? 15 : + $val >= 10 ? 10 : + $val > 7 ? 10 : + $val >= 5 ? 5 : + $val > 2 ? 5 : + $val >= 0 ? 0 : + $val > -2 ? 0 : + $val >= -5 ? -5 : + $val > - 7 ? -5 : + $val >= -10 ? -10 : + $val > -12 ? -10 : + $val >= -15 ? -15 : + $val > -17 ? -15 : -20; return $bin; @@ -22510,8 +22336,7 @@ to ensure that the system configuration is correct.
  • setupStringDeclination <Stringname1>=<Angle> [<Stringname2>=<Angle> <Stringname3>=<Angle> ...]

    Tilt angle of the solar modules. The string name is a key value of the attribute setupInverterStrings.
    - Possible angles of inclination are: 0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90 - (0 = horizontal, 90 = vertical).

    + Integers between 0 and 90 can be specified as the angle of inclination. (0 = horizontal, 90 = vertical).