mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
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:
parent
dc6ed12988
commit
4a368f5b0f
@ -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
|
||||
- bugfix: 76_SolarForecast: fix interruptable key and some minor fixes
|
||||
Forum: ?topic=137058.msg1330100#msg1330100
|
||||
- feature: 76_SolarForecast: new Attr ctrlNextHoursSoCForecastReadings
|
||||
- feature: 76_SolarForecast: version 1.42.0 with some new features & fixes
|
||||
- change: 76_SolarForecast: Attr ctrlStatisticReadings to ctrlSpecialReadings
|
||||
|
@ -157,6 +157,8 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
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 ".
|
||||
"_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ",
|
||||
"1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ".
|
||||
@ -911,6 +913,10 @@ my %htitles = (
|
||||
DE => qq{Batterie} },
|
||||
socofbat => { EN => qq{State of Charge battery},
|
||||
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)},
|
||||
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
||||
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};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "interruptable: $err" if($err);
|
||||
|
||||
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};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "swoncond: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{swoffcond}) { # Check Regex
|
||||
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "swoffcond: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{swstate}) { # Check Regex
|
||||
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
||||
|
||||
$err = checkRegex ($onregex);
|
||||
return $err if($err);
|
||||
return "swstate on-Regex: $err" if($err);
|
||||
|
||||
$err = checkRegex ($offregex);
|
||||
return $err if($err);
|
||||
return "swstate off-Regex: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{mintime}) { # Check Regex
|
||||
@ -7815,8 +7821,14 @@ sub _collectAllRegConsumers {
|
||||
my $hyst;
|
||||
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
||||
$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);
|
||||
|
||||
@ -7879,7 +7891,7 @@ sub _collectAllRegConsumers {
|
||||
$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}{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}{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
|
||||
@ -9902,17 +9914,27 @@ sub _batChargeRecmd {
|
||||
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
||||
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
||||
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 $spday = 0;
|
||||
|
||||
if ($today) {
|
||||
## (Rest) PV-Überschuß für den Tag
|
||||
####################################
|
||||
if ($pvfc) {
|
||||
if ($today) { # heutiger Tag
|
||||
$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 { # PV-Überschußprognose nächster 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
|
||||
|
||||
@ -9956,7 +9978,7 @@ sub _batChargeRecmd {
|
||||
$data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd;
|
||||
$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 $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
|
||||
$bpower = $bpowerin ? $bpowerin :
|
||||
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
||||
0;
|
||||
|
||||
$soc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||
$currsoc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||
}
|
||||
|
||||
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').
|
||||
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
||||
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
||||
@ -15844,8 +15868,7 @@ sub __substituteIcon {
|
||||
my $socicon;
|
||||
|
||||
if (defined $soc) {
|
||||
$soctxt = defined $pcurr ? "\nSoC: ".$soc." %" :
|
||||
"\nSoC Prognose: ".$soc." %"; # defined pcurr? -> aktuelle Stunde
|
||||
$soctxt = "\n".$htitles{socbatfc}{$lang}.": ".$soc." %"; # Text 'SoC Prognose'
|
||||
|
||||
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
||||
$soc >= 60 ? 'measure_battery_75' :
|
||||
@ -19891,7 +19914,9 @@ return $ps;
|
||||
# Prüfung eines übergebenen Regex
|
||||
################################################################
|
||||
sub checkRegex {
|
||||
my $regexp = shift // return;
|
||||
my $regexp = shift;
|
||||
|
||||
return 'no Regex is provided' if(!$regexp);
|
||||
|
||||
eval { "Hallo" =~ m/^$regexp$/;
|
||||
1;
|
||||
|
@ -157,6 +157,8 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
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 ".
|
||||
"_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ",
|
||||
"1.42.0" => "07.01.2025 change socslidereg to batsocslidereg, _batChargeRecmd: add value to nexthours ".
|
||||
@ -911,6 +913,10 @@ my %htitles = (
|
||||
DE => qq{Batterie} },
|
||||
socofbat => { EN => qq{State of Charge battery},
|
||||
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)},
|
||||
DE => qq{Ladeempfehlung (evtl. Freigabe zum Laden der Batterie aktivieren)} },
|
||||
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};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "interruptable: $err" if($err);
|
||||
|
||||
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};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "swoncond: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{swoffcond}) { # Check Regex
|
||||
my (undef,undef,$regex) = split ":", $h->{swoffcond};
|
||||
|
||||
$err = checkRegex ($regex);
|
||||
return $err if($err);
|
||||
return "swoffcond: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{swstate}) { # Check Regex
|
||||
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
|
||||
|
||||
$err = checkRegex ($onregex);
|
||||
return $err if($err);
|
||||
return "swstate on-Regex: $err" if($err);
|
||||
|
||||
$err = checkRegex ($offregex);
|
||||
return $err if($err);
|
||||
return "swstate off-Regex: $err" if($err);
|
||||
}
|
||||
|
||||
if (exists $h->{mintime}) { # Check Regex
|
||||
@ -7815,8 +7821,14 @@ sub _collectAllRegConsumers {
|
||||
my $hyst;
|
||||
if (exists $hc->{interruptable} && $hc->{interruptable} ne '0') {
|
||||
$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);
|
||||
|
||||
@ -7879,7 +7891,7 @@ sub _collectAllRegConsumers {
|
||||
$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}{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}{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
|
||||
@ -9902,17 +9914,27 @@ sub _batChargeRecmd {
|
||||
my $confc = NexthoursVal ($hash, 'NextHour'.$nhr, 'confc', 0);
|
||||
my $pvfc = NexthoursVal ($hash, 'NextHour'.$nhr, 'pvfc', 0);
|
||||
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 $spday = 0;
|
||||
|
||||
if ($today) {
|
||||
## (Rest) PV-Überschuß für den Tag
|
||||
####################################
|
||||
if ($pvfc) {
|
||||
if ($today) { # heutiger Tag
|
||||
$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 { # PV-Überschußprognose nächster 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
|
||||
|
||||
@ -9956,7 +9978,7 @@ sub _batChargeRecmd {
|
||||
$data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $rcmd;
|
||||
$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 $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
|
||||
$bpower = $bpowerin ? $bpowerin :
|
||||
$bpowerout ? 0 - $bpowerout : # __substituteIcon: bpowerout als NEGATIVEN Wert übergeben!
|
||||
0;
|
||||
|
||||
$soc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||
$currsoc = BatteryVal ($name, $bn, 'bcharge', 0);
|
||||
}
|
||||
|
||||
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').
|
||||
" W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef').
|
||||
", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %");
|
||||
@ -15844,8 +15868,7 @@ sub __substituteIcon {
|
||||
my $socicon;
|
||||
|
||||
if (defined $soc) {
|
||||
$soctxt = defined $pcurr ? "\nSoC: ".$soc." %" :
|
||||
"\nSoC Prognose: ".$soc." %"; # defined pcurr? -> aktuelle Stunde
|
||||
$soctxt = "\n".$htitles{socbatfc}{$lang}.": ".$soc." %"; # Text 'SoC Prognose'
|
||||
|
||||
$socicon = $soc >= 80 ? 'measure_battery_100' :
|
||||
$soc >= 60 ? 'measure_battery_75' :
|
||||
@ -19891,7 +19914,9 @@ return $ps;
|
||||
# Prüfung eines übergebenen Regex
|
||||
################################################################
|
||||
sub checkRegex {
|
||||
my $regexp = shift // return;
|
||||
my $regexp = shift;
|
||||
|
||||
return 'no Regex is provided' if(!$regexp);
|
||||
|
||||
eval { "Hallo" =~ m/^$regexp$/;
|
||||
1;
|
||||
@ -22517,7 +22542,7 @@ to ensure that the system configuration is correct.
|
||||
<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
|
||||
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.
|
||||
<br><br>
|
||||
|
||||
@ -25018,7 +25043,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<li><b>ctrlNextHoursSoCForecastReadings <00,02,..,23> </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 <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.
|
||||
<br><br>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user