2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

76_SolarForecast: new Attr ctrlNextHoursSoCForecastReadings

git-svn-id: https://svn.fhem.de/fhem/trunk@29507 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2025-01-10 22:09:47 +00:00
parent 31b6988a7f
commit ae3b0e43dc
3 changed files with 231 additions and 127 deletions

View File

@ -1,5 +1,6 @@
# 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: new Attr ctrlNextHoursSoCForecastReadings
- feature: 76_SolarForecast: version 1.42.0 with some new features & fixes - feature: 76_SolarForecast: version 1.42.0 with some new features & fixes
- change: 76_SolarForecast: Attr ctrlStatisticReadings to ctrlSpecialReadings - change: 76_SolarForecast: Attr ctrlStatisticReadings to ctrlSpecialReadings
old 'statistics_.*' readings to 'special_.*', old 'statistics_.*' readings to 'special_.*',

View File

@ -157,6 +157,8 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.43.0" => "10.01.2025 graphicShowNight: add possible Time Sync of chart bar level 1 and the other ".
"_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ",
"1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ". "1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ".
"entryGraphic: enrich hfcg hash, __normDecPlaces: use it from/to battery, ". "entryGraphic: enrich hfcg hash, __normDecPlaces: use it from/to battery, ".
"setupBatteryDevXX : new icon & show key, colour of icon can be changed separately, maxbatteries set to 3 ". "setupBatteryDevXX : new icon & show key, colour of icon can be changed separately, maxbatteries set to 3 ".
@ -527,7 +529,7 @@ my @aconfigs = qw( affectBatteryPreferredCharge affectConsForecastIdentWeekdays
consumerLegend consumerAdviceIcon consumerLink consumerLegend consumerAdviceIcon consumerLink
ctrlAIdataStorageDuration ctrlBackupFilesKeep ctrlAIdataStorageDuration ctrlBackupFilesKeep
ctrlConsRecommendReadings ctrlGenPVdeviation ctrlInterval ctrlConsRecommendReadings ctrlGenPVdeviation ctrlInterval
ctrlLanguage ctrlNextDayForecastReadings ctrlShowLink ctrlSolCastAPImaxReq ctrlLanguage ctrlNextDayForecastReadings ctrlNextHoursSoCForecastReadings ctrlShowLink ctrlSolCastAPImaxReq
ctrlSolCastAPIoptimizeReq ctrlSpecialReadings ctrlUserExitFn ctrlSolCastAPIoptimizeReq ctrlSpecialReadings ctrlUserExitFn
setupWeatherDev1 setupWeatherDev2 setupWeatherDev3 setupWeatherDev1 setupWeatherDev2 setupWeatherDev3
disable disable
@ -1335,6 +1337,7 @@ sub Initialize {
"ctrlInterval ". "ctrlInterval ".
"ctrlLanguage:DE,EN ". "ctrlLanguage:DE,EN ".
"ctrlNextDayForecastReadings:multiple-strict,$hod ". "ctrlNextDayForecastReadings:multiple-strict,$hod ".
"ctrlNextHoursSoCForecastReadings ".
"ctrlShowLink:1,0 ". "ctrlShowLink:1,0 ".
"ctrlSolCastAPImaxReq:selectnumbers,5,5,60,0,lin ". "ctrlSolCastAPImaxReq:selectnumbers,5,5,60,0,lin ".
"ctrlSolCastAPIoptimizeReq:1,0 ". "ctrlSolCastAPIoptimizeReq:1,0 ".
@ -1345,10 +1348,10 @@ sub Initialize {
"graphicBeamHeightLevel1 ". "graphicBeamHeightLevel1 ".
"graphicBeamHeightLevel2 ". "graphicBeamHeightLevel2 ".
"graphicBeamWidth:slider,20,5,100 ". "graphicBeamWidth:slider,20,5,100 ".
"graphicBeam1Content: ". "graphicBeam1Content ".
"graphicBeam2Content: ". "graphicBeam2Content ".
"graphicBeam3Content: ". "graphicBeam3Content ".
"graphicBeam4Content: ". "graphicBeam4Content ".
"graphicBeam1Color:colorpicker,RGB ". "graphicBeam1Color:colorpicker,RGB ".
"graphicBeam2Color:colorpicker,RGB ". "graphicBeam2Color:colorpicker,RGB ".
"graphicBeam3Color:colorpicker,RGB ". "graphicBeam3Color:colorpicker,RGB ".
@ -1369,7 +1372,7 @@ sub Initialize {
"graphicLayoutType:single,double,diff ". "graphicLayoutType:single,double,diff ".
"graphicSelect:both,flow,forecast,none ". "graphicSelect:both,flow,forecast,none ".
"graphicShowDiff:no,top,bottom ". "graphicShowDiff:no,top,bottom ".
"graphicShowNight:1,0 ". "graphicShowNight:1,0,01 ".
"graphicShowWeather:1,0 ". "graphicShowWeather:1,0 ".
"graphicSpaceSize ". "graphicSpaceSize ".
"graphicWeatherColor:colorpicker,RGB ". "graphicWeatherColor:colorpicker,RGB ".
@ -5423,6 +5426,10 @@ sub Attr {
deleteReadingspec ($hash, "Tomorrow_Hour.*"); deleteReadingspec ($hash, "Tomorrow_Hour.*");
} }
if ($aName eq 'ctrlNextHoursSoCForecastReadings') {
deleteReadingspec ($hash, "Battery_NextHour.._SoCforecast_..");
}
if ($aName =~ /ctrlBatSocManagement/xs && $init_done) { if ($aName =~ /ctrlBatSocManagement/xs && $init_done) {
my $bn = (split 'ctrlBatSocManagement', $aName)[1]; my $bn = (split 'ctrlBatSocManagement', $aName)[1];
@ -6146,6 +6153,7 @@ sub _attrBatteryDev { ## no critic "not used"
readingsDelete ($hash, 'Battery_ChargeRecommended_'.$bn); readingsDelete ($hash, 'Battery_ChargeRecommended_'.$bn);
readingsDelete ($hash, 'Battery_ChargeRequest_'.$bn); readingsDelete ($hash, 'Battery_ChargeRequest_'.$bn);
readingsDelete ($hash, 'Battery_OptimumTargetSoC_'.$bn); readingsDelete ($hash, 'Battery_OptimumTargetSoC_'.$bn);
deleteReadingspec ($hash, "NextHour.._Bat_${bn}_SoCforecast");
undef @{$data{$name}{current}{batsocslidereg}}; undef @{$data{$name}{current}{batsocslidereg}};
@ -7293,7 +7301,7 @@ sub _addDynAttr {
## Attributhüllen entfernen ## Attributhüllen entfernen
############################# #############################
my @deva = split " ", $modules{$type}{AttrList}; my @deva = split " ", $modules{$type}{AttrList};
my $atd = 'setupWeatherDev|setupRadiationAPI|graphicBeam*Content'; my $atd = 'setupWeatherDev|setupRadiationAPI|graphicBeam*Content|ctrlNextHoursSoCForecastReadings';
@deva = grep {!/$atd/} @deva; @deva = grep {!/$atd/} @deva;
## Attr setupWeatherDevX / setupRadiationAPI zur Laufzeit hinzufügen ## Attr setupWeatherDevX / setupRadiationAPI zur Laufzeit hinzufügen
@ -7310,16 +7318,20 @@ sub _addDynAttr {
push @deva, "setupRadiationAPI:$rdd "; push @deva, "setupRadiationAPI:$rdd ";
## Attr graphicBeamXContent zur Laufzeit hinzufügen ## Attr graphicBeamXContent, ctrlNextDayForecastReadings zur Laufzeit hinzufügen
##################################################### ##################################################################################
my $gbc = ''; my $gbc;
if (isBatteryUsed ($name)) { if (isBatteryUsed ($name)) {
for my $bn (1..$maxbatteries) { for my $bn (1..$maxbatteries) {
$bn = sprintf "%02d", $bn; $bn = sprintf "%02d", $bn;
$gbc .= 'batsocforecast_'.$bn.','; $gbc .= 'batsocforecast_'.$bn.',';
} }
my $hod = join ",", (map { sprintf "%02d", $_} (0..23));
push @deva, "ctrlNextHoursSoCForecastReadings:multiple-strict,$hod";
} }
$gbc .= ',' if(!$gbc);
$gbc .= 'consumption,consumptionForecast,energycosts,feedincome,gridconsumption,gridfeedin,pvForecast,pvReal'; $gbc .= 'consumption,consumptionForecast,energycosts,feedincome,gridconsumption,gridfeedin,pvForecast,pvReal';
push @deva, "graphicBeam1Content:$gbc"; push @deva, "graphicBeam1Content:$gbc";
@ -7327,7 +7339,6 @@ sub _addDynAttr {
push @deva, "graphicBeam3Content:$gbc"; push @deva, "graphicBeam3Content:$gbc";
push @deva, "graphicBeam4Content:$gbc"; push @deva, "graphicBeam4Content:$gbc";
$hash->{".AttrList"} = join " ", @deva; $hash->{".AttrList"} = join " ", @deva;
return; return;
@ -9861,7 +9872,7 @@ sub _batChargeRecmd {
next if($err); next if($err);
my $batinstcap = BatteryVal ($hash, $bn, 'binstcap', 0); # installierte Batteriekapazität Wh my $batinstcap = BatteryVal ($hash, $bn, 'binstcap', 0); # installierte Batteriekapazität Wh
my $soc = BatteryVal ($hash, $bn, 'bcharge', 0); # aktuelle Ladung in % my $csoc = BatteryVal ($hash, $bn, 'bcharge', 0); # aktuelle Ladung in %
my $batoptsoc = ReadingsNum ($name, 'Battery_OptimumTargetSoC_'.$bn, 0); # aktueller optimierter SoC my $batoptsoc = ReadingsNum ($name, 'Battery_OptimumTargetSoC_'.$bn, 0); # aktueller optimierter SoC
if (!$inplim || !$batinstcap) { if (!$inplim || !$batinstcap) {
@ -9878,8 +9889,7 @@ sub _batChargeRecmd {
debugLog ($paref, 'batteryManagement', "Bat $bn Charge Rcmd - Installed Battery capacity: $batinstcap Wh"); debugLog ($paref, 'batteryManagement', "Bat $bn Charge Rcmd - Installed Battery capacity: $batinstcap Wh");
my $whneed = sprintf "%.0f", ($batinstcap - ($batinstcap * $soc / 100)); # benötigte Energie bis 100% Batteriekapazität Wh my $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
my $sfmargin = $whneed * 0.25; # Sicherheitszuschlag: X% der benötigten Ladeenergie (Wh)
## Auswertung für jede kommende Stunde ## Auswertung für jede kommende Stunde
######################################## ########################################
@ -9906,20 +9916,38 @@ sub _batChargeRecmd {
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang $spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
## SOC-Prognose und Ladeempfehlung ## Ladeempfehlung
#################################### ###################
my $progsoc = sprintf "%.0f", (100 / $batinstcap * ($batinstcap - $whneed)); # Prognose SoC my $whneed = $batinstcap - $socwh;
$progsoc = $progsoc < $batoptsoc ? $batoptsoc : my $sfmargin = $whneed * 0.25; # Sicherheitszuschlag: X% der benötigten Ladeenergie (Wh)
$progsoc < $lowSoc ? $lowSoc :
$progsoc;
if ( $whneed + $sfmargin >= $spday ) {$rcmd = 1} # Ladeempfehlung wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag if ( $whneed + $sfmargin >= $spday ) {$rcmd = 1} # Ladeempfehlung wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag
if ( !$num && $pvCu - $curcon >= $inplim ) {$rcmd = 1} # Ladeempfehlung wenn akt. PV Leistung >= WR-Leistungsbegrenzung if ( !$num && $pvCu - $curcon >= $inplim ) {$rcmd = 1} # Ladeempfehlung wenn akt. PV Leistung >= WR-Leistungsbegrenzung
my $msg = "(SoC forecast: $progsoc, need: $whneed Wh -> Surplus Day: $spday Wh, Curr PV: $pvCu W, Curr Consumption: $curcon W, Limit: $inplim W)"; ## SOC-Prognose
#################
$socwh += $rcmd ? $pvfc - $confc : -$confc; # PV Prognose nur einbeziehen wenn Ladeempfehlung
$socwh = sprintf "%.0f", $socwh;
$socwh = $socwh < 0 ? 0 :
$socwh > $batinstcap ? $batinstcap :
$socwh;
my $progsoc = sprintf "%.1f", (100 * $socwh / $batinstcap); # Prognose SoC
$progsoc = $progsoc < $batoptsoc ? $batoptsoc :
$progsoc < $lowSoc ? $lowSoc :
$progsoc;
__calcReadingsNextHoursSoCFc ( {name => $name,
nhr => $nhr,
bn => $bn,
progsoc => $progsoc
}
); # Readings NextHourXX_Bat_XX_ChargeForecast erstellen
my $msg = "(currsoc: $csoc %, SoCfc: $progsoc %, soc: $socwh Wh, pvfc: $pvfc, confc: $confc, Surp Day: $spday Wh, Curr PV: $pvCu W, Curr Consumption: $curcon W, Limit: $inplim W)";
if ($num) { if ($num) {
$msg = "(SoC forecast: $progsoc, need: $whneed Wh -> Surplus Day: $spday Wh)"; $msg = "(SoCfc: $progsoc %, soc: $socwh Wh, pvfc: $pvfc, confc: $confc, Surp Day: $spday Wh)";
} }
else { else {
storeReading ('Battery_ChargeRecommended_'.$bn, $rcmd); # Reading nur für aktuelle Stunde storeReading ('Battery_ChargeRecommended_'.$bn, $rcmd); # Reading nur für aktuelle Stunde
@ -9928,31 +9956,35 @@ sub _batChargeRecmd {
$data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd; $data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd;
$data{$name}{nexthours}{'NextHour'.$nhr}{'soc'.$bn} = $progsoc; $data{$name}{nexthours}{'NextHour'.$nhr}{'soc'.$bn} = $progsoc;
debugLog ($paref, 'batteryManagement', "Bat $bn Charge activation $stt -> $rcmd $msg"); debugLog ($paref, 'batteryManagement', "Bat $bn doCharge $stt -> $rcmd $msg");
## Fortschreibung der Prognose als Grundlage für die kommende Stunde
######################################################################
if ($pvfc) {
if ($today) { # (Rest) heutiger Tag
$confcss -= $confc;
$confcss = 0 if($confcss < 0);
$rodpvfc -= $pvfc;
}
else { # nächster Tag
$tomconfc -= $confc;
$tomconfc = 0 if($tomconfc < 0);
$tompvfc -= $pvfc;
}
}
$whneed -= sprintf "%.0f", ($rcmd ? $pvfc - $confc : 0); # PV Prognose nur einbeziehen wenn Ladeempfehlung
$whneed = $whneed < 0 ? 0 : $whneed;
} }
} }
return; return;
} }
################################################################
# zusätzliche Readings NextHourXX_Bat_XX_ChargeForecast
# erstellen
################################################################
sub __calcReadingsNextHoursSoCFc {
my $paref = shift;
my $name = $paref->{name};
my $nhr = $paref->{nhr}; # nächste Stunde
my $bn = $paref->{bn}; # Batterienummer
my $progsoc = $paref->{progsoc}; # prognostizierter SoC
my $hods = AttrVal ($name, 'ctrlNextHoursSoCForecastReadings', '');
return if(!$hods);
if (grep { /$nhr/x } split ',', $hods) {
storeReading ('Battery_NextHour'.$nhr.'_SoCforecast_'.$bn, $progsoc.' %');
}
return;
}
################################################################ ################################################################
# Zusammenfassungen erstellen # Zusammenfassungen erstellen
################################################################ ################################################################
@ -12000,16 +12032,15 @@ return;
################################################################ ################################################################
# zusätzliche Readings Tomorrow_HourXX_PVforecast # zusätzliche Readings Tomorrow_HourXX_PVforecast
# berechnen # erstellen
################################################################ ################################################################
sub _calcReadingsTomorrowPVFc { sub _calcReadingsTomorrowPVFc {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $type = $paref->{type};
my $hash = $defs{$name}; my $hash = $defs{$name};
my $h = $data{$name}{nexthours}; my $h = $data{$name}{nexthours};
my $hods = AttrVal($name, 'ctrlNextDayForecastReadings', ''); my $hods = AttrVal ($name, 'ctrlNextDayForecastReadings', '');
return if(!keys %{$h} || !$hods); return if(!keys %{$h} || !$hods);
@ -12755,12 +12786,17 @@ sub entryGraphic {
# Parameter f. Anzeige extrahieren # Parameter f. Anzeige extrahieren
################################### ###################################
my $width = AttrNum ($name, 'graphicBeamWidth', 20); # zu klein ist nicht problematisch my $width = AttrNum ($name, 'graphicBeamWidth', 20); # zu klein ist nicht problematisch
my $maxhours = AttrNum ($name, 'graphicHourCount', 24); my $maxhours = AttrNum ($name, 'graphicHourCount', 24);
my $alias = AttrVal ($name, 'alias', $name); # Linktext als Aliasname oder Devicename setzen my $alias = AttrVal ($name, 'alias', $name); # Linktext als Aliasname oder Devicename setzen
my $w = $width * $maxhours; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
my $offset = -1 * AttrNum ($name, 'graphicHistoryHour', $histhourdef); AttrVal ($name, 'graphicShowNight', 0) =~ /(.)(.)?/xs;
my $dlink = qq{<a href="$::FW_ME$::FW_subdir?detail=$name">$alias</a>}; my $show_night = $1 // 0;
my $layersync = $2 // 0;
my $w = $width * $maxhours; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
my $offset = -1 * AttrNum ($name, 'graphicHistoryHour', $histhourdef);
my $dlink = qq{<a href="$::FW_ME$::FW_subdir?detail=$name">$alias</a>};
if (!$gsel) { if (!$gsel) {
$gsel = AttrVal ($name, 'graphicSelect', 'both'); # Auswahl der anzuzeigenden Grafiken $gsel = AttrVal ($name, 'graphicSelect', 'both'); # Auswahl der anzuzeigenden Grafiken
@ -12795,7 +12831,8 @@ sub entryGraphic {
width => $width, width => $width,
fsize => AttrNum ($name, 'graphicSpaceSize', 24), fsize => AttrNum ($name, 'graphicSpaceSize', 24),
maxVal => AttrNum ($name, 'graphicBeam1MaxVal', 0), # dyn. Anpassung der Balkenhöhe oder statisch ? maxVal => AttrNum ($name, 'graphicBeam1MaxVal', 0), # dyn. Anpassung der Balkenhöhe oder statisch ?
show_night => AttrNum ($name, 'graphicShowNight', 0), # alle Balken (Spalten) anzeigen ? layersync => $layersync, # Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen
show_night => $show_night, # alle Balken (Spalten) anzeigen ?
show_diff => AttrVal ($name, 'graphicShowDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen show_diff => AttrVal ($name, 'graphicShowDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen
weather => AttrNum ($name, 'graphicShowWeather', 1), # Wetter Icons anzeigen weather => AttrNum ($name, 'graphicShowWeather', 1), # Wetter Icons anzeigen
colorw => AttrVal ($name, 'graphicWeatherColor', $wthcolddef), # Wetter Icon Farbe Tag colorw => AttrVal ($name, 'graphicWeatherColor', $wthcolddef), # Wetter Icon Farbe Tag
@ -14551,14 +14588,7 @@ sub _beamGraphic {
my $ii = 0; my $ii = 0;
for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben
if (!$show_night && $hfcg->{$i}{weather} > 99 && next if(__dontNightshowSkipSync ($name, $paref, $i));
!$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}) {
next;
}
if (!$show_night && $hfcg->{$i}{weather} > 99) {
$paref->{barsync}{$i} = 1;
}
$ii++; # wieviele Stunden haben wir bisher angezeigt ? $ii++; # wieviele Stunden haben wir bisher angezeigt ?
last if($ii > $maxhours || $ii > $barcount); # vorzeitiger Abbruch last if($ii > $maxhours || $ii > $barcount); # vorzeitiger Abbruch
@ -14566,9 +14596,9 @@ sub _beamGraphic {
$val = normBeamWidth ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather}); $val = normBeamWidth ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather});
if ($val ne '&nbsp;') { # Forum: https://forum.fhem.de/index.php/topic,117864.msg1166215.html#msg1166215 if ($val ne '&nbsp;') { # Forum: https://forum.fhem.de/index.php/topic,117864.msg1166215.html#msg1166215
$val = $hfcg->{$i}{diff} < 0 ? '<b>'.$val.'<b/>' : $val = $hfcg->{$i}{diff} < 0 ? '<b>'.$val.'<b/>' :
$val > 0 ? '+'.$val : $val > 0 ? '+' .$val :
$val; # negative Zahlen in Fettschrift, 0 aber ohne + $val; # negative Zahlen in Fettschrift, 0 aber ohne +
} }
$ret .= "<td class='solarfc' style='vertical-align:middle; text-align:center;'>$val</td>"; $ret .= "<td class='solarfc' style='vertical-align:middle; text-align:center;'>$val</td>";
@ -14582,14 +14612,7 @@ sub _beamGraphic {
my $ii = 0; my $ii = 0;
for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben
if (!$show_night && $hfcg->{$i}{weather} > 99 && next if(__dontNightshowSkipSync ($name, $paref, $i));
!$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}) {
next;
}
if (!$show_night && $hfcg->{$i}{weather} > 99) {
$paref->{barsync}{$i} = 1;
}
$ii++; $ii++;
last if($ii > $maxhours || $ii > $barcount); last if($ii > $maxhours || $ii > $barcount);
@ -14849,6 +14872,42 @@ sub _beamGraphic {
return $ret; return $ret;
} }
############################################################################################
# liefert Signal ob Werte angezeigt werden sollen obwohl
# die Nachtstunden nicht angezeigt werden sowie die
# bei Synchronisation der nachfolgenden Balkendiagramm-Ebenen
# mit Balkendiagramm-Ebene 1
#
# skip = 0 - Wert soll angezeigt werden
# skip = 1 - Wert soll nicht angezeigt werden
# paref->skip = 1 - Synchronisation Anzeige des Balkens in nächsten Ebenen verhindern
# paref->noSkip = 1 - Synchronisation Anzeige des Balkens in nächsten Ebenen erzwingen
#
############################################################################################
sub __dontNightshowSkipSync {
my $name = shift;
my $paref = shift;
my $i = shift;
my $skip = 0;
if ($paref->{skip}{$i} && !$paref->{noSkip}{$i}) {
$skip = 1 if($paref->{layersync}); # Anwendung bei Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen
}
elsif (!$paref->{show_night} && $paref->{hfcg}{$i}{weather} > 99 &&
!$paref->{hfcg}{$i}{beam1} && !$paref->{hfcg}{beam2} &&
!$paref->{noSkip}{$i}) {
$paref->{skip}{$i} = 1 if($paref->{layersync}); # Anwendung bei Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen
$skip = 1;
}
else {
$paref->{noSkip}{$i} = 1 if($paref->{layersync}); # Anwendung bei Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen
}
return $skip;
}
################################################################ ################################################################
# Wetter Icon Zeile # Wetter Icon Zeile
################################################################ ################################################################
@ -14878,11 +14937,12 @@ sub __weatherOnBeam {
debugLog ($paref, 'graphic', "weather id beam number >$i< (start hour $hfcg->{$i}{time_str}): wid $hfcg->{$i}{weather} / wcc $wcc") if($ii < $maxhours); debugLog ($paref, 'graphic', "weather id beam number >$i< (start hour $hfcg->{$i}{time_str}): wid $hfcg->{$i}{weather} / wcc $wcc") if($ii < $maxhours);
if (!$show_night && $hfcg->{$i}{weather} > 99 && my $skip = __dontNightshowSkipSync ($name, $paref, $i);
!$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}) { # Lässt Nachticons aber noch durch wenn es einen Wert gibt
debugLog ($paref, 'graphic', "Weather position >$i< is skipped (condition no night display)") if($ii < $maxhours); if ($skip) {
debugLog ($paref, 'graphic', "Weather position >$i< is skipped due to don't show night condition") if($ii < $maxhours);
next; next;
}; }
$ii++; # wieviele Stunden Icons haben sind beechnet? $ii++; # wieviele Stunden Icons haben sind beechnet?
last if($ii > $maxhours || $ii > $barcount); last if($ii > $maxhours || $ii > $barcount);
@ -14904,7 +14964,7 @@ sub __weatherOnBeam {
debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer"); debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer");
} }
$icon_name .= $hfcg->{$i}{weather} < 100 ? '@'.$colorw : '@'.$colorwn; $icon_name .= $hfcg->{$i}{weather} < 100 ? '@'.$colorw : '@'.$colorwn;
my $val = FW_makeImage ($icon_name) // q{}; my $val = FW_makeImage ($icon_name) // q{};
if ($val =~ /title="$icon_name"/xs) { # passendes Icon beim User nicht vorhanden ! ( attr web iconPath falsch/prüfen/update ? ) if ($val =~ /title="$icon_name"/xs) { # passendes Icon beim User nicht vorhanden ! ( attr web iconPath falsch/prüfen/update ? )
@ -14986,11 +15046,12 @@ sub __batRcmdOnBeam {
my $ii = 0; my $ii = 0;
for my $i (0..($maxhours * 2) - 1) { for my $i (0..($maxhours * 2) - 1) {
if (!$show_night && $hfcg->{$i}{weather} > 99 && my $skip = __dontNightshowSkipSync ($name, $paref, $i);
!$hfcg->{$i}{beam1} && !$hfcg->{$i}{beam2}) {
if ($skip) {
debugLog ($paref, 'graphic', "Battery $bn recommandation pos >$i< skipped due to don't show night condition") if($ii < $maxhours); debugLog ($paref, 'graphic', "Battery $bn recommandation pos >$i< skipped due to don't show night condition") if($ii < $maxhours);
next; next;
}; }
$ii++; # wieviele Stunden Icons sind bisher beechnet? $ii++; # wieviele Stunden Icons sind bisher beechnet?
last if($ii > $maxhours || $ii > $barcount); last if($ii > $maxhours || $ii > $barcount);
@ -19325,7 +19386,7 @@ return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0);
sub isBatteryUsed { sub isBatteryUsed {
my $name = shift; my $name = shift;
my $valid; my $valid = 0;
for my $bn (1..$maxbatteries) { for my $bn (1..$maxbatteries) {
$bn = sprintf "%02d", $bn; $bn = sprintf "%02d", $bn;
@ -22452,6 +22513,23 @@ to ensure that the system configuration is correct.
</li> </li>
<br> <br>
<a id="SolarForecast-attr-ctrlNextHoursSoCForecastReadings"></a>
<li><b>ctrlNextHoursSoCForecastReadings &lt;00,02,..,23&gt; </b><br>
If set, readings of the form Battery_NextHourXX_SoCforecast_BN are created if a battery is registered
in the SolarForecast device (see <a href="#SolarForecast-attr-setupBatteryDev">attr &lt;name&gt; setupBatteryDevXX </a>). <br>
These readings contain the predicted SoC values (%) for the selected hours. <br>
Where 'XX' is the hour in the future starting from the current hour (00) and 'BN' is the number of the registered battery.
<br><br>
<ul>
<b>Example: </b> <br>
attr &lt;name&gt; ctrlNextHoursSoCForecastReadings 00,03,12,18 <br>
# creates readings for the current hour (00) and the following hours +03, +12 and +18.
</ul>
</li>
<br>
<a id="SolarForecast-attr-ctrlShowLink"></a> <a id="SolarForecast-attr-ctrlShowLink"></a>
<li><b>ctrlShowLink </b><br> <li><b>ctrlShowLink </b><br>
Display of the link to the detailed view of the device above the graphic area. <br> Display of the link to the detailed view of the device above the graphic area. <br>
@ -22922,7 +23000,7 @@ to ensure that the system configuration is correct.
<ul> <ul>
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="15%"> <col width="85%"> </colgroup>
<tr><td> <b>both</b> </td><td>displays the header, consumer legend, energy flow and prediction graph (default) </td></tr> <tr><td> <b>both</b> </td><td>displays the header, consumer legend, energy flow and prediction graph (default) </td></tr>
<tr><td> <b>flow</b> </td><td>displays the header, the consumer legend and energy flow graphic </td></tr> <tr><td> <b>flow</b> </td><td>displays the header, the consumer legend and energy flow graphic </td></tr>
<tr><td> <b>forecast</b> </td><td>displays the header, the consumer legend and the prediction graphic </td></tr> <tr><td> <b>forecast</b> </td><td>displays the header, the consumer legend and the prediction graphic </td></tr>
@ -22942,10 +23020,19 @@ to ensure that the system configuration is correct.
<a id="SolarForecast-attr-graphicShowNight"></a> <a id="SolarForecast-attr-graphicShowNight"></a>
<li><b>graphicShowNight </b><br> <li><b>graphicShowNight </b><br>
Show/hide the night hours without values in the bar chart. <br> Display or hide the night hours in the bar chart.
If the selected bar contents contain a value in the night hours, these bars are also displayed if <br><br>
graphicShowNight=0. <br>
(default: 0 (hide)) <ul>
<table>
<colgroup> <col width="5%"> <col width="95%"> </colgroup>
<tr><td> <b>0</b> </td><td>no display of night hours if no value is to be displayed (default) </td></tr>
<tr><td> </td><td>If the selected content contains a value, these bars are still displayed. </td></tr>
<tr><td> <b>01</b> </td><td>Like 0, but time synchronisation takes place between the level 1 </td></tr>
<tr><td> </td><td>and the subsequent bar chart level. </td></tr>
<tr><td> <b>1</b> </td><td>the night hours are always displayed </td></tr>
</table>
</ul>
</li> </li>
<br> <br>
@ -24927,6 +25014,23 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
</li> </li>
<br> <br>
<a id="SolarForecast-attr-ctrlNextHoursSoCForecastReadings"></a>
<li><b>ctrlNextHoursSoCForecastReadings &lt;00,02,..,23&gt; </b><br>
Wenn gesetzt, werden Readings der Form Battery_NextHourXX_SoCforecast_BN erstellt sofern eine Batterie im
SolarForecast-Device registriert ist (siehe <a href="#SolarForecast-attr-setupBatteryDev">attr &lt;name&gt; setupBatteryDevXX </a>). <br>
Diese Readings enthalten die prognostizierten SoC-Werte (%) der ausgewählten Stunden. <br>
Dabei ist 'XX' die Stunde in der Zukunft ausgehend von der aktuellen Stunde (00) und 'BN' die Nummer der registrierten Batterie.
<br><br>
<ul>
<b>Beispiel: </b> <br>
attr &lt;name&gt; ctrlNextHoursSoCForecastReadings 00,03,12,18 <br>
# erstellt Readings für die aktuelle Stunde (00) sowie die nachfolgenden Stunden +03, +12 und +18.
</ul>
</li>
<br>
<a id="SolarForecast-attr-ctrlShowLink"></a> <a id="SolarForecast-attr-ctrlShowLink"></a>
<li><b>ctrlShowLink </b><br> <li><b>ctrlShowLink </b><br>
Anzeige des Links zur Detailansicht des Device über dem Grafikbereich <br> Anzeige des Links zur Detailansicht des Device über dem Grafikbereich <br>
@ -25395,7 +25499,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<ul> <ul>
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="15%"> <col width="85%"> </colgroup>
<tr><td> <b>both</b> </td><td>zeigt den Header, die Verbraucherlegende, Energiefluß- und Vorhersagegrafik an (default) </td></tr> <tr><td> <b>both</b> </td><td>zeigt den Header, die Verbraucherlegende, Energiefluß- und Vorhersagegrafik an (default) </td></tr>
<tr><td> <b>flow</b> </td><td>zeigt den Header, die Verbraucherlegende und Energieflußgrafik an </td></tr> <tr><td> <b>flow</b> </td><td>zeigt den Header, die Verbraucherlegende und Energieflußgrafik an </td></tr>
<tr><td> <b>forecast</b> </td><td>zeigt den Header, die Verbraucherlegende und die Vorhersagegrafik an </td></tr> <tr><td> <b>forecast</b> </td><td>zeigt den Header, die Verbraucherlegende und die Vorhersagegrafik an </td></tr>
@ -25415,10 +25519,19 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<a id="SolarForecast-attr-graphicShowNight"></a> <a id="SolarForecast-attr-graphicShowNight"></a>
<li><b>graphicShowNight </b><br> <li><b>graphicShowNight </b><br>
Anzeigen/Verbergen der Nachtstunden ohne Werte in der Balkengrafik. <br> Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik.
Sofern die ausgewählten Balkeninhalte in den Nachtstunden einen Wert enthalten, werden diese Balken <br><br>
auch im Fall graphicShowNight=0 dargestellt. <br>
(default: 0 (verbergen)) <ul>
<table>
<colgroup> <col width="5%"> <col width="95%"> </colgroup>
<tr><td> <b>0</b> </td><td>keine Anzeige der Nachtstunden sofern kein Wert anzuzeigen ist (default) </td></tr>
<tr><td> </td><td>Sofern die ausgewählten Inhalte einen Wert enthalten, werden diese Balken dennoch dargestellt. </td></tr>
<tr><td> <b>01</b> </td><td>Wie '0', es findet jedoch eine Zeitsynchronisation zwischen der Ebene 1 </td></tr>
<tr><td> </td><td>und der nachfolgenden Balkengrafikebene statt. </td></tr>
<tr><td> <b>1</b> </td><td>Nachtstunden werden immer angezeigt </td></tr>
</table>
</ul>
</li> </li>
<br> <br>

View File

@ -157,7 +157,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.43.0" => "09.01.2025 graphicShowNight: add possible Time Sync of chart bar level 1 and the other ". "1.43.0" => "10.01.2025 graphicShowNight: add possible Time Sync of chart bar level 1 and the other ".
"_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ", "_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ",
"1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ". "1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ".
"entryGraphic: enrich hfcg hash, __normDecPlaces: use it from/to battery, ". "entryGraphic: enrich hfcg hash, __normDecPlaces: use it from/to battery, ".
@ -9889,7 +9889,7 @@ sub _batChargeRecmd {
debugLog ($paref, 'batteryManagement', "Bat $bn Charge Rcmd - Installed Battery capacity: $batinstcap Wh"); debugLog ($paref, 'batteryManagement', "Bat $bn Charge Rcmd - Installed Battery capacity: $batinstcap Wh");
my $whneed = sprintf "%.0f", ($batinstcap - ($batinstcap * $csoc / 100)); # benötigte Energie bis 100% Batteriekapazität Wh my $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
## Auswertung für jede kommende Stunde ## Auswertung für jede kommende Stunde
######################################## ########################################
@ -9916,11 +9916,24 @@ sub _batChargeRecmd {
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang $spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
## SOC-Prognose und Ladeempfehlung ## Ladeempfehlung
#################################### ###################
my $progsoc = sprintf "%.0f", (100 / $batinstcap * ($batinstcap - $whneed)); # Prognose SoC my $whneed = $batinstcap - $socwh;
$progsoc = !$num ? $csoc : # Stunde 00 (aktuelle) -> $progsoc = $csoc my $sfmargin = $whneed * 0.25; # Sicherheitszuschlag: X% der benötigten Ladeenergie (Wh)
$progsoc < $batoptsoc ? $batoptsoc :
if ( $whneed + $sfmargin >= $spday ) {$rcmd = 1} # Ladeempfehlung wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag
if ( !$num && $pvCu - $curcon >= $inplim ) {$rcmd = 1} # Ladeempfehlung wenn akt. PV Leistung >= WR-Leistungsbegrenzung
## SOC-Prognose
#################
$socwh += $rcmd ? $pvfc - $confc : -$confc; # PV Prognose nur einbeziehen wenn Ladeempfehlung
$socwh = sprintf "%.0f", $socwh;
$socwh = $socwh < 0 ? 0 :
$socwh > $batinstcap ? $batinstcap :
$socwh;
my $progsoc = sprintf "%.1f", (100 * $socwh / $batinstcap); # Prognose SoC
$progsoc = $progsoc < $batoptsoc ? $batoptsoc :
$progsoc < $lowSoc ? $lowSoc : $progsoc < $lowSoc ? $lowSoc :
$progsoc; $progsoc;
@ -9931,15 +9944,10 @@ sub _batChargeRecmd {
} }
); # Readings NextHourXX_Bat_XX_ChargeForecast erstellen ); # Readings NextHourXX_Bat_XX_ChargeForecast erstellen
my $sfmargin = $whneed * 0.25; # Sicherheitszuschlag: X% der benötigten Ladeenergie (Wh) my $msg = "(currsoc: $csoc %, SoCfc: $progsoc %, soc: $socwh Wh, pvfc: $pvfc, confc: $confc, Surp Day: $spday Wh, Curr PV: $pvCu W, Curr Consumption: $curcon W, Limit: $inplim W)";
if ( $whneed + $sfmargin >= $spday ) {$rcmd = 1} # Ladeempfehlung wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag
if ( !$num && $pvCu - $curcon >= $inplim ) {$rcmd = 1} # Ladeempfehlung wenn akt. PV Leistung >= WR-Leistungsbegrenzung
my $msg = "(SoC forecast: $progsoc, need: $whneed Wh -> Surplus Day: $spday Wh, Curr PV: $pvCu W, Curr Consumption: $curcon W, Limit: $inplim W)";
if ($num) { if ($num) {
$msg = "(SoC forecast: $progsoc, need: $whneed Wh -> Surplus Day: $spday Wh)"; $msg = "(SoCfc: $progsoc %, soc: $socwh Wh, pvfc: $pvfc, confc: $confc, Surp Day: $spday Wh)";
} }
else { else {
storeReading ('Battery_ChargeRecommended_'.$bn, $rcmd); # Reading nur für aktuelle Stunde storeReading ('Battery_ChargeRecommended_'.$bn, $rcmd); # Reading nur für aktuelle Stunde
@ -9948,25 +9956,7 @@ sub _batChargeRecmd {
$data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd; $data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd;
$data{$name}{nexthours}{'NextHour'.$nhr}{'soc'.$bn} = $progsoc; $data{$name}{nexthours}{'NextHour'.$nhr}{'soc'.$bn} = $progsoc;
debugLog ($paref, 'batteryManagement', "Bat $bn Charge activation $stt -> $rcmd $msg"); debugLog ($paref, 'batteryManagement', "Bat $bn doCharge $stt -> $rcmd $msg");
## Fortschreibung der Prognose als Grundlage für die kommende Stunde
######################################################################
if ($pvfc) {
if ($today) { # (Rest) heutiger Tag
$confcss -= $confc;
$confcss = 0 if($confcss < 0);
$rodpvfc -= $pvfc;
}
else { # nächster Tag
$tomconfc -= $confc;
$tomconfc = 0 if($tomconfc < 0);
$tompvfc -= $pvfc;
}
}
$whneed -= sprintf "%.0f", ($rcmd ? $pvfc - $confc : 0); # PV Prognose nur einbeziehen wenn Ladeempfehlung
$whneed = $whneed < 0 ? 0 : $whneed;
} }
} }