76_SolarForecast: fix interruptable key and some minor fixes
git-svn-id: https://svn.fhem.de/fhem/trunk@29510 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -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
|
||||||
|
- bugfix: 76_SolarForecast: fix interruptable key and some minor fixes
|
||||||
|
Forum: ?topic=137058.msg1330100#msg1330100
|
||||||
- feature: 76_SolarForecast: new Attr ctrlNextHoursSoCForecastReadings
|
- 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
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.43.1" => "11.01.2025 _batChargeRecmd: bugfix PV daily surplus update, _collectAllRegConsumers: fix interruptable hysteresis ".
|
||||||
|
"__batRcmdOnBeam: show soc forecast for hour 00 and fix english translation ",
|
||||||
"1.43.0" => "10.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 ".
|
||||||
@@ -911,6 +913,10 @@ my %htitles = (
|
|||||||
DE => qq{Batterie} },
|
DE => qq{Batterie} },
|
||||||
socofbat => { EN => qq{State of Charge battery},
|
socofbat => { EN => qq{State of Charge battery},
|
||||||
DE => qq{Ladung Batterie} },
|
DE => qq{Ladung Batterie} },
|
||||||
|
socbacur => { EN => qq{SoC current},
|
||||||
|
DE => qq{SoC aktuell} },
|
||||||
|
socbatfc => { EN => qq{SoC forecast},
|
||||||
|
DE => qq{SoC Prognose} },
|
||||||
bcharrcd => { EN => qq{Charging recommendation (activate release for charging the battery if necessary)},
|
bcharrcd => { EN => qq{Charging recommendation (activate release for charging the battery if necessary)},
|
||||||
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
||||||
bncharcd => { EN => qq{No charging recommendation (possibly deactivate release for charging the battery)},
|
bncharcd => { EN => qq{No charging recommendation (possibly deactivate release for charging the battery)},
|
||||||
@@ -5604,10 +5610,10 @@ sub _attrconsumer { ## no critic "not used"
|
|||||||
my (undef,undef,$regex,$hyst) = split ":", $h->{interruptable};
|
my (undef,undef,$regex,$hyst) = split ":", $h->{interruptable};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "interruptable: $err" if($err);
|
||||||
|
|
||||||
if ($hyst && !isNumeric ($hyst)) {
|
if ($hyst && !isNumeric ($hyst)) {
|
||||||
return qq{The hysteresis of key "interruptable" must be a numeric value like "0.5" or "2"};
|
return qq{The hysteresis of key "interruptable" must be a numeric value};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5615,24 +5621,24 @@ sub _attrconsumer { ## no critic "not used"
|
|||||||
my (undef,undef,$regex) = split ":", $h->{swoncond};
|
my (undef,undef,$regex) = split ":", $h->{swoncond};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "swoncond: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{swoffcond}) { # Check Regex
|
if (exists $h->{swoffcond}) { # Check Regex
|
||||||
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "swoffcond: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{swstate}) { # Check Regex
|
if (exists $h->{swstate}) { # Check Regex
|
||||||
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
||||||
|
|
||||||
$err = checkRegex ($onregex);
|
$err = checkRegex ($onregex);
|
||||||
return $err if($err);
|
return "swstate on-Regex: $err" if($err);
|
||||||
|
|
||||||
$err = checkRegex ($offregex);
|
$err = checkRegex ($offregex);
|
||||||
return $err if($err);
|
return "swstate off-Regex: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{mintime}) { # Check Regex
|
if (exists $h->{mintime}) { # Check Regex
|
||||||
@@ -7814,10 +7820,16 @@ sub _collectAllRegConsumers {
|
|||||||
my $interruptable = 0;
|
my $interruptable = 0;
|
||||||
my $hyst;
|
my $hyst;
|
||||||
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
||||||
$interruptable = $hc->{interruptable};
|
$interruptable = $hc->{interruptable};
|
||||||
($interruptable,$hyst) = $interruptable =~ /(.*):(.*)$/xs if($interruptable ne '1');
|
|
||||||
|
if ($interruptable ne '1') {
|
||||||
|
(my $dv, my $rd, my $reg, $hyst) = split ':', $interruptable;
|
||||||
|
$interruptable = "$dv:$rd:$reg";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hyst = $defhyst if(!$hyst);
|
||||||
|
|
||||||
my ($riseshift, $setshift);
|
my ($riseshift, $setshift);
|
||||||
|
|
||||||
if (exists $hc->{mintime}) { # Check Regex
|
if (exists $hc->{mintime}) { # Check Regex
|
||||||
@@ -7879,7 +7891,7 @@ sub _collectAllRegConsumers {
|
|||||||
$data{$name}{consumers}{$c}{rigncond} = $rigncond // q{}; # Reading liefert Ignore Bedingung
|
$data{$name}{consumers}{$c}{rigncond} = $rigncond // q{}; # Reading liefert Ignore Bedingung
|
||||||
$data{$name}{consumers}{$c}{spignorecondregex} = $spignorecondregex // q{}; # Regex der Ignore Bedingung
|
$data{$name}{consumers}{$c}{spignorecondregex} = $spignorecondregex // q{}; # Regex der Ignore Bedingung
|
||||||
$data{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar
|
$data{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar
|
||||||
$data{$name}{consumers}{$c}{hysteresis} = $hyst // $defhyst; # Hysterese
|
$data{$name}{consumers}{$c}{hysteresis} = $hyst; # Hysterese
|
||||||
$data{$name}{consumers}{$c}{sunriseshift} = $riseshift if(defined $riseshift); # Verschiebung (Sekunden) Sonnenaufgang bei SunPath Verwendung
|
$data{$name}{consumers}{$c}{sunriseshift} = $riseshift if(defined $riseshift); # Verschiebung (Sekunden) Sonnenaufgang bei SunPath Verwendung
|
||||||
$data{$name}{consumers}{$c}{sunsetshift} = $setshift if(defined $setshift); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
$data{$name}{consumers}{$c}{sunsetshift} = $setshift if(defined $setshift); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
||||||
$data{$name}{consumers}{$c}{icon} = $hc->{icon} if(defined $hc->{icon}); # Icon für den Verbraucher
|
$data{$name}{consumers}{$c}{icon} = $hc->{icon} if(defined $hc->{icon}); # Icon für den Verbraucher
|
||||||
@@ -9889,7 +9901,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 $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
|
my $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
|
||||||
|
|
||||||
## Auswertung für jede kommende Stunde
|
## Auswertung für jede kommende Stunde
|
||||||
########################################
|
########################################
|
||||||
@@ -9902,16 +9914,26 @@ sub _batChargeRecmd {
|
|||||||
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
||||||
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
||||||
my $stt = NexthoursVal ($hash, 'NextHour'.$nhr, 'starttime', '');
|
my $stt = NexthoursVal ($hash, 'NextHour'.$nhr, 'starttime', '');
|
||||||
$stt = (split '-', $stt)[2] if($stt);
|
$stt = (split /[-:]/, $stt)[2] if($stt);
|
||||||
|
|
||||||
my $rcmd = 0; # Ladeempfehlung 0 per Default
|
my $rcmd = 0; # Ladeempfehlung 0 per Default
|
||||||
my $spday = 0;
|
my $spday = 0;
|
||||||
|
|
||||||
if ($today) {
|
## (Rest) PV-Überschuß für den Tag
|
||||||
$spday = $rodpvfc - $confcss; # PV-Überschußprognose (Rest) heutiger Tag
|
####################################
|
||||||
}
|
if ($pvfc) {
|
||||||
else { # PV-Überschußprognose nächster Tag
|
if ($today) { # heutiger Tag
|
||||||
$spday = $tompvfc - $tomconfc;
|
$confcss -= $confc; # Verbrauch bis Sonnenuntergang - Verbrauch Fc aktuelle Stunde
|
||||||
|
$confcss = 0 if($confcss < 0);
|
||||||
|
$rodpvfc -= $pvfc;
|
||||||
|
$spday = $rodpvfc - $confcss; # PV-Überschußprognose (Rest) heutiger Tag
|
||||||
|
}
|
||||||
|
else { # nächster Tag
|
||||||
|
$tomconfc -= $confc;
|
||||||
|
$tomconfc = 0 if($tomconfc < 0);
|
||||||
|
$tompvfc -= $pvfc;
|
||||||
|
$spday = $tompvfc - $tomconfc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
|
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
|
||||||
@@ -9956,7 +9978,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 doCharge $stt -> $rcmd $msg");
|
debugLog ($paref, 'batteryManagement', "Bat $bn relLoad $stt -> $rcmd $msg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15065,14 +15087,14 @@ sub __batRcmdOnBeam {
|
|||||||
my $time_str = $hfcg->{$i}{time_str};
|
my $time_str = $hfcg->{$i}{time_str};
|
||||||
my $soc = $hfcg->{$i}{'soc'.$bn};
|
my $soc = $hfcg->{$i}{'soc'.$bn};
|
||||||
|
|
||||||
my ($bpower);
|
my ($bpower, $currsoc);
|
||||||
|
|
||||||
if ($day_str eq $day && $time_str eq $chour) { # akt. Leistung nur für aktuelle Stunde
|
if ($day_str eq $day && $time_str eq $chour) { # akt. Leistung nur für aktuelle Stunde
|
||||||
$bpower = $bpowerin ? $bpowerin :
|
$bpower = $bpowerin ? $bpowerin :
|
||||||
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
||||||
0;
|
0;
|
||||||
|
|
||||||
$soc = BatteryVal ($name, $bn, 'bcharge', 0);
|
$currsoc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($bicon, $title) = __substituteIcon ( { name => $name, # Icon / Status des Batterie Devices
|
my ($bicon, $title) = __substituteIcon ( { name => $name, # Icon / Status des Batterie Devices
|
||||||
@@ -15086,6 +15108,8 @@ sub __batRcmdOnBeam {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$title .= defined $currsoc ? "\n".$htitles{socbacur}{$lang}.": ".$currsoc." %" : '';
|
||||||
|
|
||||||
debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef').
|
debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef').
|
||||||
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
||||||
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
||||||
@@ -15844,8 +15868,7 @@ sub __substituteIcon {
|
|||||||
my $socicon;
|
my $socicon;
|
||||||
|
|
||||||
if (defined $soc) {
|
if (defined $soc) {
|
||||||
$soctxt = defined $pcurr ? "\nSoC: ".$soc." %" :
|
$soctxt = "\n".$htitles{socbatfc}{$lang}.": ".$soc." %"; # Text 'SoC Prognose'
|
||||||
"\nSoC Prognose: ".$soc." %"; # defined pcurr? -> aktuelle Stunde
|
|
||||||
|
|
||||||
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
||||||
$soc >= 60 ? 'measure_battery_75' :
|
$soc >= 60 ? 'measure_battery_75' :
|
||||||
@@ -19891,7 +19914,9 @@ return $ps;
|
|||||||
# Prüfung eines übergebenen Regex
|
# Prüfung eines übergebenen Regex
|
||||||
################################################################
|
################################################################
|
||||||
sub checkRegex {
|
sub checkRegex {
|
||||||
my $regexp = shift // return;
|
my $regexp = shift;
|
||||||
|
|
||||||
|
return 'no Regex is provided' if(!$regexp);
|
||||||
|
|
||||||
eval { "Hallo" =~ m/^$regexp$/;
|
eval { "Hallo" =~ m/^$regexp$/;
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.43.1" => "11.01.2025 _batChargeRecmd: bugfix PV daily surplus update, _collectAllRegConsumers: fix interruptable hysteresis ".
|
||||||
|
"__batRcmdOnBeam: show soc forecast for hour 00 and fix english translation ",
|
||||||
"1.43.0" => "10.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 ".
|
||||||
@@ -911,6 +913,10 @@ my %htitles = (
|
|||||||
DE => qq{Batterie} },
|
DE => qq{Batterie} },
|
||||||
socofbat => { EN => qq{State of Charge battery},
|
socofbat => { EN => qq{State of Charge battery},
|
||||||
DE => qq{Ladung Batterie} },
|
DE => qq{Ladung Batterie} },
|
||||||
|
socbacur => { EN => qq{SoC current},
|
||||||
|
DE => qq{SoC aktuell} },
|
||||||
|
socbatfc => { EN => qq{SoC forecast},
|
||||||
|
DE => qq{SoC Prognose} },
|
||||||
bcharrcd => { EN => qq{Charging recommendation (activate release for charging the battery if necessary)},
|
bcharrcd => { EN => qq{Charging recommendation (activate release for charging the battery if necessary)},
|
||||||
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
||||||
bncharcd => { EN => qq{No charging recommendation (possibly deactivate release for charging the battery)},
|
bncharcd => { EN => qq{No charging recommendation (possibly deactivate release for charging the battery)},
|
||||||
@@ -5604,10 +5610,10 @@ sub _attrconsumer { ## no critic "not used"
|
|||||||
my (undef,undef,$regex,$hyst) = split ":", $h->{interruptable};
|
my (undef,undef,$regex,$hyst) = split ":", $h->{interruptable};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "interruptable: $err" if($err);
|
||||||
|
|
||||||
if ($hyst && !isNumeric ($hyst)) {
|
if ($hyst && !isNumeric ($hyst)) {
|
||||||
return qq{The hysteresis of key "interruptable" must be a numeric value like "0.5" or "2"};
|
return qq{The hysteresis of key "interruptable" must be a numeric value};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5615,24 +5621,24 @@ sub _attrconsumer { ## no critic "not used"
|
|||||||
my (undef,undef,$regex) = split ":", $h->{swoncond};
|
my (undef,undef,$regex) = split ":", $h->{swoncond};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "swoncond: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{swoffcond}) { # Check Regex
|
if (exists $h->{swoffcond}) { # Check Regex
|
||||||
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
||||||
|
|
||||||
$err = checkRegex ($regex);
|
$err = checkRegex ($regex);
|
||||||
return $err if($err);
|
return "swoffcond: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{swstate}) { # Check Regex
|
if (exists $h->{swstate}) { # Check Regex
|
||||||
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
||||||
|
|
||||||
$err = checkRegex ($onregex);
|
$err = checkRegex ($onregex);
|
||||||
return $err if($err);
|
return "swstate on-Regex: $err" if($err);
|
||||||
|
|
||||||
$err = checkRegex ($offregex);
|
$err = checkRegex ($offregex);
|
||||||
return $err if($err);
|
return "swstate off-Regex: $err" if($err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists $h->{mintime}) { # Check Regex
|
if (exists $h->{mintime}) { # Check Regex
|
||||||
@@ -7814,10 +7820,16 @@ sub _collectAllRegConsumers {
|
|||||||
my $interruptable = 0;
|
my $interruptable = 0;
|
||||||
my $hyst;
|
my $hyst;
|
||||||
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
||||||
$interruptable = $hc->{interruptable};
|
$interruptable = $hc->{interruptable};
|
||||||
($interruptable,$hyst) = $interruptable =~ /(.*):(.*)$/xs if($interruptable ne '1');
|
|
||||||
|
if ($interruptable ne '1') {
|
||||||
|
(my $dv, my $rd, my $reg, $hyst) = split ':', $interruptable;
|
||||||
|
$interruptable = "$dv:$rd:$reg";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hyst = $defhyst if(!$hyst);
|
||||||
|
|
||||||
my ($riseshift, $setshift);
|
my ($riseshift, $setshift);
|
||||||
|
|
||||||
if (exists $hc->{mintime}) { # Check Regex
|
if (exists $hc->{mintime}) { # Check Regex
|
||||||
@@ -7879,7 +7891,7 @@ sub _collectAllRegConsumers {
|
|||||||
$data{$name}{consumers}{$c}{rigncond} = $rigncond // q{}; # Reading liefert Ignore Bedingung
|
$data{$name}{consumers}{$c}{rigncond} = $rigncond // q{}; # Reading liefert Ignore Bedingung
|
||||||
$data{$name}{consumers}{$c}{spignorecondregex} = $spignorecondregex // q{}; # Regex der Ignore Bedingung
|
$data{$name}{consumers}{$c}{spignorecondregex} = $spignorecondregex // q{}; # Regex der Ignore Bedingung
|
||||||
$data{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar
|
$data{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar
|
||||||
$data{$name}{consumers}{$c}{hysteresis} = $hyst // $defhyst; # Hysterese
|
$data{$name}{consumers}{$c}{hysteresis} = $hyst; # Hysterese
|
||||||
$data{$name}{consumers}{$c}{sunriseshift} = $riseshift if(defined $riseshift); # Verschiebung (Sekunden) Sonnenaufgang bei SunPath Verwendung
|
$data{$name}{consumers}{$c}{sunriseshift} = $riseshift if(defined $riseshift); # Verschiebung (Sekunden) Sonnenaufgang bei SunPath Verwendung
|
||||||
$data{$name}{consumers}{$c}{sunsetshift} = $setshift if(defined $setshift); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
$data{$name}{consumers}{$c}{sunsetshift} = $setshift if(defined $setshift); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
||||||
$data{$name}{consumers}{$c}{icon} = $hc->{icon} if(defined $hc->{icon}); # Icon für den Verbraucher
|
$data{$name}{consumers}{$c}{icon} = $hc->{icon} if(defined $hc->{icon}); # Icon für den Verbraucher
|
||||||
@@ -9889,7 +9901,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 $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
|
my $socwh = sprintf "%.0f", ($batinstcap * $csoc / 100); # aktueller SoC in Wh
|
||||||
|
|
||||||
## Auswertung für jede kommende Stunde
|
## Auswertung für jede kommende Stunde
|
||||||
########################################
|
########################################
|
||||||
@@ -9902,16 +9914,26 @@ sub _batChargeRecmd {
|
|||||||
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
||||||
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
||||||
my $stt = NexthoursVal ($hash, 'NextHour'.$nhr, 'starttime', '');
|
my $stt = NexthoursVal ($hash, 'NextHour'.$nhr, 'starttime', '');
|
||||||
$stt = (split '-', $stt)[2] if($stt);
|
$stt = (split /[-:]/, $stt)[2] if($stt);
|
||||||
|
|
||||||
my $rcmd = 0; # Ladeempfehlung 0 per Default
|
my $rcmd = 0; # Ladeempfehlung 0 per Default
|
||||||
my $spday = 0;
|
my $spday = 0;
|
||||||
|
|
||||||
if ($today) {
|
## (Rest) PV-Überschuß für den Tag
|
||||||
$spday = $rodpvfc - $confcss; # PV-Überschußprognose (Rest) heutiger Tag
|
####################################
|
||||||
}
|
if ($pvfc) {
|
||||||
else { # PV-Überschußprognose nächster Tag
|
if ($today) { # heutiger Tag
|
||||||
$spday = $tompvfc - $tomconfc;
|
$confcss -= $confc; # Verbrauch bis Sonnenuntergang - Verbrauch Fc aktuelle Stunde
|
||||||
|
$confcss = 0 if($confcss < 0);
|
||||||
|
$rodpvfc -= $pvfc;
|
||||||
|
$spday = $rodpvfc - $confcss; # PV-Überschußprognose (Rest) heutiger Tag
|
||||||
|
}
|
||||||
|
else { # nächster Tag
|
||||||
|
$tomconfc -= $confc;
|
||||||
|
$tomconfc = 0 if($tomconfc < 0);
|
||||||
|
$tompvfc -= $pvfc;
|
||||||
|
$spday = $tompvfc - $tomconfc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
|
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
|
||||||
@@ -9956,7 +9978,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 doCharge $stt -> $rcmd $msg");
|
debugLog ($paref, 'batteryManagement', "Bat $bn relLoad $stt -> $rcmd $msg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15065,14 +15087,14 @@ sub __batRcmdOnBeam {
|
|||||||
my $time_str = $hfcg->{$i}{time_str};
|
my $time_str = $hfcg->{$i}{time_str};
|
||||||
my $soc = $hfcg->{$i}{'soc'.$bn};
|
my $soc = $hfcg->{$i}{'soc'.$bn};
|
||||||
|
|
||||||
my ($bpower);
|
my ($bpower, $currsoc);
|
||||||
|
|
||||||
if ($day_str eq $day && $time_str eq $chour) { # akt. Leistung nur für aktuelle Stunde
|
if ($day_str eq $day && $time_str eq $chour) { # akt. Leistung nur für aktuelle Stunde
|
||||||
$bpower = $bpowerin ? $bpowerin :
|
$bpower = $bpowerin ? $bpowerin :
|
||||||
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
||||||
0;
|
0;
|
||||||
|
|
||||||
$soc = BatteryVal ($name, $bn, 'bcharge', 0);
|
$currsoc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($bicon, $title) = __substituteIcon ( { name => $name, # Icon / Status des Batterie Devices
|
my ($bicon, $title) = __substituteIcon ( { name => $name, # Icon / Status des Batterie Devices
|
||||||
@@ -15086,6 +15108,8 @@ sub __batRcmdOnBeam {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$title .= defined $currsoc ? "\n".$htitles{socbacur}{$lang}.": ".$currsoc." %" : '';
|
||||||
|
|
||||||
debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef').
|
debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef').
|
||||||
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
||||||
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
||||||
@@ -15844,8 +15868,7 @@ sub __substituteIcon {
|
|||||||
my $socicon;
|
my $socicon;
|
||||||
|
|
||||||
if (defined $soc) {
|
if (defined $soc) {
|
||||||
$soctxt = defined $pcurr ? "\nSoC: ".$soc." %" :
|
$soctxt = "\n".$htitles{socbatfc}{$lang}.": ".$soc." %"; # Text 'SoC Prognose'
|
||||||
"\nSoC Prognose: ".$soc." %"; # defined pcurr? -> aktuelle Stunde
|
|
||||||
|
|
||||||
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
||||||
$soc >= 60 ? 'measure_battery_75' :
|
$soc >= 60 ? 'measure_battery_75' :
|
||||||
@@ -19891,7 +19914,9 @@ return $ps;
|
|||||||
# Prüfung eines übergebenen Regex
|
# Prüfung eines übergebenen Regex
|
||||||
################################################################
|
################################################################
|
||||||
sub checkRegex {
|
sub checkRegex {
|
||||||
my $regexp = shift // return;
|
my $regexp = shift;
|
||||||
|
|
||||||
|
return 'no Regex is provided' if(!$regexp);
|
||||||
|
|
||||||
eval { "Hallo" =~ m/^$regexp$/;
|
eval { "Hallo" =~ m/^$regexp$/;
|
||||||
1;
|
1;
|
||||||
@@ -22517,7 +22542,7 @@ to ensure that the system configuration is correct.
|
|||||||
<li><b>ctrlNextHoursSoCForecastReadings <00,02,..,23> </b><br>
|
<li><b>ctrlNextHoursSoCForecastReadings <00,02,..,23> </b><br>
|
||||||
If set, readings of the form Battery_NextHourXX_SoCforecast_BN are created if a battery is registered
|
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 <name> setupBatteryDevXX </a>). <br>
|
in the SolarForecast device (see <a href="#SolarForecast-attr-setupBatteryDev">attr <name> setupBatteryDevXX </a>). <br>
|
||||||
These readings contain the predicted SoC values (%) for the selected hours. <br>
|
These readings contain the predicted SoC value (%) at the end of the selected hour. <br>
|
||||||
Where 'XX' is the hour in the future starting from the current hour (00) and 'BN' is the number of the registered battery.
|
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>
|
<br><br>
|
||||||
|
|
||||||
@@ -25018,7 +25043,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<li><b>ctrlNextHoursSoCForecastReadings <00,02,..,23> </b><br>
|
<li><b>ctrlNextHoursSoCForecastReadings <00,02,..,23> </b><br>
|
||||||
Wenn gesetzt, werden Readings der Form Battery_NextHourXX_SoCforecast_BN erstellt sofern eine Batterie im
|
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 <name> setupBatteryDevXX </a>). <br>
|
SolarForecast-Device registriert ist (siehe <a href="#SolarForecast-attr-setupBatteryDev">attr <name> setupBatteryDevXX </a>). <br>
|
||||||
Diese Readings enthalten die prognostizierten SoC-Werte (%) der ausgewählten Stunden. <br>
|
Diese Readings enthalten den prognostizierten SoC-Wert (%) zum Ende der ausgewählten Stunde. <br>
|
||||||
Dabei ist 'XX' die Stunde in der Zukunft ausgehend von der aktuellen Stunde (00) und 'BN' die Nummer der registrierten Batterie.
|
Dabei ist 'XX' die Stunde in der Zukunft ausgehend von der aktuellen Stunde (00) und 'BN' die Nummer der registrierten Batterie.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user