mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
76_SolarForecast: change Attr setupBatteryDev to setupBatteryDev01, new getter valBattery
git-svn-id: https://svn.fhem.de/fhem/trunk@29457 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5c8b3acd67
commit
0a9935680e
@ -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: change Attr setupBatteryDev to setupBatteryDev01,
|
||||
new getter valBattery
|
||||
- bugfix: 88_HMCCU: Role STATUS_INDICATOR
|
||||
- feature: 76_SolarForecast: consumer key surpmeth - various surplus variants
|
||||
- change: 76_SolarForecast: improve Bat careSoC management when dark doldrums
|
||||
|
@ -158,7 +158,8 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.40.0" => "21.12.2024 new consumer key 'surpmeth' to calculate surplus in various variants for cunsumer switching ",
|
||||
"1.41.0" => "28.12.2024 _batSocTarget: minor code change, change setupBatteryDev to setupBatteryDev01, getter valBattery ",
|
||||
"1.40.0" => "21.12.2024 new consumer key 'surpmeth' to calculate surplus in various variants for consumer switching ",
|
||||
"1.39.8" => "21.12.2024 prepare of new consumer key 'surpmeth', _batSocTarget: improve care SoC management when dark doldrums ",
|
||||
"1.39.7" => "18.12.2024 ConsumptionRecommended calc method medianArray, change local owndata to global data ",
|
||||
"1.39.6" => "17.12.2024 replace global data-store by local owndata-store, remove sub _composeRemoteObj, delHashRefDeep removed ".
|
||||
@ -404,6 +405,7 @@ my $tempcoeffdef = -0.45;
|
||||
my $tempmodinc = 25; # default Temperaturerhöhung an Solarzellen gegenüber Umgebungstemperatur bei wolkenlosem Himmel
|
||||
my $tempbasedef = 25; # Temperatur Module bei Nominalleistung
|
||||
|
||||
my $maxbatteries = 1; # maximale Anzahl der möglichen Batterien
|
||||
my $maxconsumer = 16; # maximale Anzahl der möglichen Consumer (Attribut)
|
||||
my $maxproducer = 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
||||
my $maxinverter = 3; # maximale Anzahl der möglichen Inverter
|
||||
@ -515,7 +517,7 @@ my @aconfigs = qw( affectBatteryPreferredCharge affectConsForecastIdentWeekdays
|
||||
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
|
||||
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
|
||||
graphicSpaceSize graphicWeatherColor graphicWeatherColorNight
|
||||
setupMeterDev setupBatteryDev setupInverterStrings setupRadiationAPI setupStringPeak
|
||||
setupMeterDev setupInverterStrings setupRadiationAPI setupStringPeak
|
||||
setupRoofTops
|
||||
);
|
||||
|
||||
@ -525,6 +527,11 @@ for my $cn (1..$maxconsumer) {
|
||||
push @dd, "consumerSwitching${cn}"; # ctrlDebug: add specific Consumer
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
push @aconfigs, "setupBatteryDev${bn}"; # Anlagenkonfiguration: add Battery Attribute
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
push @aconfigs, "setupInverterDev${in}"; # Anlagenkonfiguration: add Inverter Attribute
|
||||
@ -580,6 +587,7 @@ my %hget = ( # Ha
|
||||
data => { fn => \&_getdata, needcred => 0 },
|
||||
html => { fn => \&_gethtml, needcred => 0 },
|
||||
ftui => { fn => \&_getftui, needcred => 0 },
|
||||
valBattery => { fn => \&_getlistvalBattery, needcred => 0 },
|
||||
valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
|
||||
valInverter => { fn => \&_getlistvalInverter, needcred => 0 },
|
||||
valProducer => { fn => \&_getlistvalProducer, needcred => 0 },
|
||||
@ -608,8 +616,6 @@ my %hattr = ( # H
|
||||
setupWeatherDev2 => { fn => \&_attrWeatherDev },
|
||||
setupWeatherDev3 => { fn => \&_attrWeatherDev },
|
||||
setupMeterDev => { fn => \&_attrMeterDev },
|
||||
setupBatteryDev => { fn => \&_attrBatteryDev },
|
||||
setupInverterDev => { fn => \&_attrInverterDev },
|
||||
setupInverterStrings => { fn => \&_attrInverterStrings },
|
||||
setupRadiationAPI => { fn => \&_attrRadiationAPI },
|
||||
setupStringPeak => { fn => \&_attrStringPeak },
|
||||
@ -617,6 +623,11 @@ my %hattr = ( # H
|
||||
flowGraphicControl => { fn => \&_attrflowGraphicControl },
|
||||
);
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$hattr{'setupBatteryDev'.$bn}{fn} = \&_attrBatteryDev;
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
$hattr{'setupInverterDev'.$in}{fn} = \&_attrInverterDev;
|
||||
@ -1179,13 +1190,18 @@ sub Initialize {
|
||||
my $srd = join ",", sort keys (%hcsr);
|
||||
my $gbc = 'pvReal,pvForecast,consumption,consumptionForecast,gridconsumption,energycosts,gridfeedin,feedincome';
|
||||
|
||||
my ($consumer, $setupprod, $setupinv, @allc);
|
||||
my ($consumer, $setupbat, $setupprod, $setupinv, @allc);
|
||||
for my $c (1..$maxconsumer) {
|
||||
$c = sprintf "%02d", $c;
|
||||
$consumer .= "consumer${c}:textField-long ";
|
||||
push @allc, $c;
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$setupbat .= "setupBatteryDev${bn}:textField-long ";
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
$setupinv .= "setupInverterDev${in}:textField-long ";
|
||||
@ -1276,9 +1292,9 @@ sub Initialize {
|
||||
"setupWeatherDev2 ".
|
||||
"setupWeatherDev3 ".
|
||||
"setupRoofTops ".
|
||||
"setupBatteryDev:textField-long ".
|
||||
"setupRadiationAPI ".
|
||||
"setupStringPeak ".
|
||||
$setupbat.
|
||||
$setupinv.
|
||||
$setupprod.
|
||||
$consumer.
|
||||
@ -1295,10 +1311,7 @@ sub Initialize {
|
||||
# $hash->{FW_addDetailToSummary} = 1;
|
||||
# $hash->{FW_atPageEnd} = 1; # wenn 1 -> kein Longpoll ohne informid in HTML-Tag
|
||||
|
||||
$hash->{AttrRenameMap} = { "graphicBeamHeight" => "graphicBeamHeightLevel1", # 07.05.24
|
||||
"ctrlWeatherDev1" => "setupWeatherDev1", # 20.08.24
|
||||
"ctrlWeatherDev2" => "setupWeatherDev2",
|
||||
"ctrlWeatherDev3" => "setupWeatherDev3",
|
||||
$hash->{AttrRenameMap} = { "setupBatteryDev" => "setupBatteryDev01", # 28.12.24
|
||||
"setupInverterDev" => "setupInverterDev01", # 11.10.24
|
||||
};
|
||||
|
||||
@ -2318,6 +2331,7 @@ sub Get {
|
||||
|
||||
my @pha = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{pvhist}};
|
||||
my @vcm = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{consumers}};
|
||||
my @vba = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{batteries}};
|
||||
my @vin = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{inverters}};
|
||||
my @vpn = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{producers}};
|
||||
my @vst = sort keys %{$data{$name}{strings}};
|
||||
@ -2325,11 +2339,13 @@ sub Get {
|
||||
my $hol = join ",", @ho;
|
||||
my $pvl = join ",", @pha;
|
||||
my $cml = join ",", @vcm;
|
||||
my $bal = join ",", @vba;
|
||||
my $inl = join ",", @vin;
|
||||
my $pnl = join ",", @vpn;
|
||||
my $str = join ",", @vst;
|
||||
|
||||
my $getlist = "Unknown argument $opt, choose one of ".
|
||||
"valBattery:#,$bal ".
|
||||
"valConsumerMaster:#,$cml ".
|
||||
"valInverter:#,$inl ".
|
||||
"valProducer:#,$pnl ".
|
||||
@ -4518,6 +4534,21 @@ sub _getlistCurrent {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
###############################################################
|
||||
# Getter valBattery
|
||||
###############################################################
|
||||
sub _getlistvalBattery {
|
||||
my $paref = shift;
|
||||
my $name = $paref->{name};
|
||||
my $arg = $paref->{arg};
|
||||
my $hash = $defs{$name};
|
||||
|
||||
my $ret = listDataPool ($hash, 'batteries', $arg);
|
||||
$ret .= lineFromSpaces ($ret, 30);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
###############################################################
|
||||
# Getter valConsumerMaster
|
||||
###############################################################
|
||||
@ -5302,8 +5333,8 @@ sub Attr {
|
||||
|
||||
if ($aName eq 'ctrlBatSocManagement' && $init_done) {
|
||||
if ($cmd eq 'set') {
|
||||
return qq{Define the key 'cap' with "attr $name setupBatteryDev" before this attribute in the correct form.}
|
||||
if(!CurrentVal($hash, 'batinstcap', 0)); # https://forum.fhem.de/index.php?msg=1310930
|
||||
return qq{Define the key 'cap' with "attr $name setupBatteryDev01" before this attribute in the correct form.}
|
||||
if(!BatteryVal ($hash, '01', 'binstcap', 0)); # https://forum.fhem.de/index.php?msg=1310930
|
||||
|
||||
my ($lowSoc, $upSoc, $maxsoc, $careCycle) = __parseAttrBatSoc ($name, $aVal);
|
||||
|
||||
@ -5836,9 +5867,7 @@ sub _attrInverterDev { ## no critic "not used"
|
||||
delete $data{$name}{inverters}{$in}{ifeed};
|
||||
}
|
||||
elsif ($paref->{cmd} eq 'del') {
|
||||
for my $k (keys %{$data{$name}{inverters}}) {
|
||||
delete $data{$name}{inverters}{$k} if($k eq $in);
|
||||
}
|
||||
delete $data{$name}{inverters}{$in};
|
||||
|
||||
readingsDelete ($hash, 'Current_PV');
|
||||
undef @{$data{$name}{current}{genslidereg}};
|
||||
@ -5993,6 +6022,7 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
return if(!$init_done);
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $bn = (split 'setupBatteryDev', $aName)[1];
|
||||
|
||||
if ($paref->{cmd} eq 'set') {
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
|
||||
@ -6010,6 +6040,8 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
if ($h->{pin} eq "-pout" && $h->{pout} eq "-pin") {
|
||||
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
|
||||
}
|
||||
|
||||
delete $data{$name}{batteries}{$bn}{basynchron};
|
||||
}
|
||||
elsif ($paref->{cmd} eq 'del') {
|
||||
readingsDelete ($hash, 'Current_PowerBatIn');
|
||||
@ -6025,11 +6057,7 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
delete $data{$name}{circular}{99}{batintot};
|
||||
delete $data{$name}{circular}{99}{batouttot};
|
||||
|
||||
delete $data{$name}{current}{powerbatout};
|
||||
delete $data{$name}{current}{powerbatin};
|
||||
delete $data{$name}{current}{batcharge};
|
||||
delete $data{$name}{current}{batinstcap};
|
||||
delete $data{$name}{current}{batasynchron};
|
||||
delete $data{$name}{batteries}{$bn};
|
||||
}
|
||||
|
||||
InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
|
||||
@ -6210,7 +6238,7 @@ sub Notify {
|
||||
|
||||
my $debug = getDebug ($myHash); # Debug Mode
|
||||
|
||||
my ($err, $medev, $badev, $h, $async);
|
||||
my ($err, $medev, $bname, $iname, $h, $async);
|
||||
|
||||
## Meter Event?
|
||||
#################
|
||||
@ -6241,11 +6269,12 @@ sub Notify {
|
||||
|
||||
## Battery Event?
|
||||
###################
|
||||
($err, $badev, $h) = isDeviceValid ( { name => $myName, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$bname = BatteryVal ($myHash, $bn, 'bname', '');
|
||||
|
||||
if (!$err) {
|
||||
if ($devName eq $badev) {
|
||||
$async = $h->{asynchron} // 0;
|
||||
if ($devName eq $bname) {
|
||||
$async = BatteryVal ($myHash, $bn, 'basynchron', 0);
|
||||
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Battery device >$devName< received - asynchronous mode: $async});
|
||||
@ -6264,22 +6293,23 @@ sub Notify {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
## Inverter Event?
|
||||
####################
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
my $iname = InverterVal ($myHash, $in, 'iname', '');
|
||||
$iname = InverterVal ($myHash, $in, 'iname', '');
|
||||
|
||||
if ($devName eq $iname) {
|
||||
my $iasync = InverterVal ($myHash, $in, 'iasynchron', 0);
|
||||
$async = InverterVal ($myHash, $in, 'iasynchron', 0);
|
||||
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Inverter device >$devName< received - asynchronous mode: $iasync});
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Inverter device >$devName< received - asynchronous mode: $async});
|
||||
}
|
||||
|
||||
if ($iasync) {
|
||||
if ($async) {
|
||||
if (CurrentVal ($myHash, 'ctrunning', 0)) {
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - central task was called from NOTIFY when it is already running ... end this call});
|
||||
@ -6302,7 +6332,6 @@ sub Notify {
|
||||
|
||||
if (@consumers && grep /^$devName$/, @consumers) {
|
||||
my ($cname, $cindex, $dswname);
|
||||
my $type = $myHash->{TYPE};
|
||||
|
||||
for my $c (sort{$a<=>$b} keys %{$data{$myName}{consumers}}) {
|
||||
($err, $cname, $dswname) = getCDnames ($myHash, $c);
|
||||
@ -7287,6 +7316,9 @@ sub centralTask {
|
||||
return;
|
||||
}
|
||||
|
||||
$data{$name}{current}{ctrunning} = 1; # Central Task running Statusbit
|
||||
InternalTimer (gettimeofday() + 1.2, "FHEM::SolarForecast::releaseCentralTask", $hash, 0); # Freigabe centralTask
|
||||
|
||||
my $t = time; # aktuelle Unix-Zeit
|
||||
my $date = strftime "%Y-%m-%d", localtime($t); # aktuelles Datum
|
||||
my $chour = strftime "%H", localtime($t); # aktuelle Stunde in 24h format (00-23)
|
||||
@ -7295,10 +7327,6 @@ sub centralTask {
|
||||
my $dayname = strftime "%a", localtime($t); # aktueller Wochentagsname
|
||||
my $debug = getDebug ($hash); # Debug Module
|
||||
|
||||
$data{$name}{current}{ctrunning} = 1; # Central Task running Statusbit
|
||||
|
||||
InternalTimer (gettimeofday() + 1.2, "FHEM::SolarForecast::releaseCentralTask", $hash, 0); # Freigabe centralTask
|
||||
|
||||
my $centpars = {
|
||||
name => $name,
|
||||
type => $type,
|
||||
@ -9198,10 +9226,16 @@ sub _transferBatteryValues {
|
||||
my $day = $paref->{day};
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
return if($err);
|
||||
my $num = 0;
|
||||
my $socsum;
|
||||
|
||||
my $type = $paref->{type};
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
||||
next if($err);
|
||||
|
||||
$num++;
|
||||
|
||||
my ($pin,$piunit) = split ":", $h->{pin}; # Readingname/Unit für aktuelle Batterieladung
|
||||
my ($pou,$pounit) = split ":", $h->{pout}; # Readingname/Unit für aktuelle Batterieentladung
|
||||
@ -9236,10 +9270,10 @@ sub _transferBatteryValues {
|
||||
$instcap = $instcap * ($bcapunit =~ /^kWh$/xi ? 1000 : 1);
|
||||
}
|
||||
|
||||
$data{$name}{current}{batinstcap} = $instcap; # installierte Batteriekapazität
|
||||
$data{$name}{batteries}{$bn}{binstcap} = $instcap; # installierte Batteriekapazität
|
||||
}
|
||||
else {
|
||||
delete $data{$name}{current}{batinstcap};
|
||||
delete $data{$name}{batteries}{$bn}{binstcap};
|
||||
}
|
||||
|
||||
my $debug = $paref->{debug};
|
||||
@ -9270,8 +9304,8 @@ sub _transferBatteryValues {
|
||||
($pbi,$pbo) = substSpecialCases ($params);
|
||||
}
|
||||
|
||||
# Batterielade-, enladeenergie in Circular speichern
|
||||
######################################################
|
||||
# Batterielade, -entladeenergie in Circular speichern
|
||||
#######################################################
|
||||
if (!defined CircularVal ($hash, 99, 'initdaybatintot', undef)) {
|
||||
$data{$name}{circular}{99}{initdaybatintot} = $btotin; # total Batterieladung zu Tagbeginn (Wh)
|
||||
}
|
||||
@ -9285,6 +9319,7 @@ sub _transferBatteryValues {
|
||||
|
||||
my $nhour = $chour+1;
|
||||
|
||||
|
||||
# Batterieladung aktuelle Stunde in pvHistory speichern
|
||||
#########################################################
|
||||
my $histbatintot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), "batintotal", undef); # totale Batterieladung zu Beginn einer Stunde
|
||||
@ -9305,6 +9340,7 @@ sub _transferBatteryValues {
|
||||
$data{$name}{circular}{sprintf("%02d",$nhour)}{batin} = $batinthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||
writeToHistory ( { paref => $paref, key => 'batinthishour', val => $batinthishour, hour => $nhour } );
|
||||
|
||||
|
||||
# Batterieentladung aktuelle Stunde in pvHistory speichern
|
||||
############################################################
|
||||
my $histbatouttot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), 'batouttotal', undef); # totale Betterieladung zu Beginn einer Stunde
|
||||
@ -9325,6 +9361,7 @@ sub _transferBatteryValues {
|
||||
$data{$name}{circular}{sprintf("%02d",$nhour)}{batout} = $batoutthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||
writeToHistory ( { paref => $paref, key => 'batoutthishour', val => $batoutthishour, hour => $nhour } );
|
||||
|
||||
|
||||
# täglichen max. SOC in pvHistory speichern
|
||||
#############################################
|
||||
my $batmaxsoc = HistoryVal ($hash, $day, 99, 'batmaxsoc', 0); # gespeicherter max. SOC des Tages
|
||||
@ -9341,13 +9378,20 @@ sub _transferBatteryValues {
|
||||
storeReading ('Current_PowerBatOut', (int $pbo).' W');
|
||||
storeReading ('Current_BatCharge', $soc.' %');
|
||||
|
||||
$data{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung
|
||||
$data{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung
|
||||
$data{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung
|
||||
$data{$name}{current}{batasynchron} = $h->{asynchron} if($h->{asynchron}); # asynchroner Modus = X
|
||||
$data{$name}{batteries}{$bn}{bname} = $badev; # Batterie Devicename
|
||||
$data{$name}{batteries}{$bn}{balias} = AttrVal ($badev, 'alias', $badev); # Alias Batterie Device
|
||||
$data{$name}{batteries}{$bn}{bpowerin} = int $pbi; # momentane Batterieladung
|
||||
$data{$name}{batteries}{$bn}{bpowerout} = int $pbo; # momentane Batterieentladung
|
||||
$data{$name}{batteries}{$bn}{bcharge} = $soc; # aktuelle Batterieladung
|
||||
$data{$name}{batteries}{$bn}{basynchron} = $h->{asynchron} // 0; # asynchroner Modus = X
|
||||
|
||||
push @{$data{$name}{current}{socslidereg}}, $soc; # Schieberegister Batterie SOC
|
||||
$socsum += $soc;
|
||||
}
|
||||
|
||||
if ($num) {
|
||||
push @{$data{$name}{current}{socslidereg}}, $socsum / $num; # Schieberegister average SOC aller Batterien
|
||||
limitArray ($data{$name}{current}{socslidereg}, $slidenummax);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -9358,7 +9402,6 @@ return;
|
||||
sub _batSocTarget {
|
||||
my $paref = shift;
|
||||
my $name = $paref->{name};
|
||||
my $type = $paref->{type};
|
||||
my $t = $paref->{t}; # aktuelle Zeit
|
||||
|
||||
return if(!isBatteryUsed ($name));
|
||||
@ -9366,8 +9409,8 @@ sub _batSocTarget {
|
||||
my $hash = $defs{$name};
|
||||
my $oldd2care = CircularVal ($hash, 99, 'days2care', 0);
|
||||
my $ltsmsr = CircularVal ($hash, 99, 'lastTsMaxSocRchd', undef);
|
||||
my $batcharge = CurrentVal ($hash, 'batcharge', 0); # aktuelle Ladung in %
|
||||
my $batinstcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $batcharge = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in %
|
||||
my $batinstcap = BatteryVal ($hash, '01', 'binstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $cgbt = AttrVal ($name, 'ctrlBatSocManagement', undef);
|
||||
|
||||
if ($cgbt && !$batinstcap) {
|
||||
@ -9484,7 +9527,8 @@ sub _batSocTarget {
|
||||
$target < $lowSoc ? $lowSoc :
|
||||
$target;
|
||||
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - observe low/up limits -> docare: $docare, Target: $target %");
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - basics -> docare: $docare, lowSoc: $lowSoc %, upSoc: $upSoc %");
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - observe low/up limits -> Target: $target %");
|
||||
|
||||
## auf 5er Schritte anpassen (40,45,50,...)
|
||||
#############################################
|
||||
@ -9569,8 +9613,8 @@ sub _batChargeRecmd {
|
||||
my $tomconfc = ReadingsNum ($name, 'Tomorrow_ConsumptionForecast', 0);
|
||||
|
||||
my $pvCu = ReadingsNum ($name, 'Current_PV', 0); # aktuelle PV Erzeugung
|
||||
my $batcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $soc = CurrentVal ($hash, 'batcharge', 0); # aktueller SOC (%)
|
||||
my $batcap = BatteryVal ($hash, '01', 'binstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $soc = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in % # aktueller SOC (%)
|
||||
my $curcon = ReadingsNum ($name, 'Current_Consumption', 0); # aktueller Verbrauch
|
||||
|
||||
my $inpmax = 0;
|
||||
@ -9756,8 +9800,8 @@ sub _createSummaries {
|
||||
my $gcon = CurrentVal ($hash, 'gridconsumption', 0); # aktueller Netzbezug
|
||||
my $tconsum = CurrentVal ($hash, 'tomorrowconsumption', undef); # Verbrauchsprognose für folgenden Tag
|
||||
my $gfeedin = CurrentVal ($hash, 'gridfeedin', 0);
|
||||
my $batin = CurrentVal ($hash, 'powerbatin', 0); # aktuelle Batterieladung
|
||||
my $batout = CurrentVal ($hash, 'powerbatout', 0); # aktuelle Batterieentladung
|
||||
my $batin = BatteryVal ($hash, '01', 'bpowerin', 0); # momentane Batterieladung
|
||||
my $batout = BatteryVal ($hash, '01', 'bpowerout', 0); # momentane Batterieentladung
|
||||
|
||||
my $pvgen = 0;
|
||||
my $pv2grid = 0; # PV-Erzeugung zu Grid-only
|
||||
@ -11400,8 +11444,8 @@ sub ___enableSwitchByBatPrioCharge {
|
||||
|
||||
return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert
|
||||
|
||||
my $cbcharge = CurrentVal ($hash, "batcharge", 0); # aktuelle Batterieladung
|
||||
$ena = 0 if($cbcharge < $pcb); # keine Freigabe wenn Batterieladung kleiner Soll-Ladung
|
||||
my $bcharge = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in %
|
||||
$ena = 0 if($bcharge < $pcb); # keine Freigabe wenn Batterieladung kleiner Soll-Ladung
|
||||
|
||||
return $ena;
|
||||
}
|
||||
@ -16611,11 +16655,12 @@ sub listDataPool {
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol =~ /consumers|inverters|producers|strings/xs) {
|
||||
if ($htol =~ /consumers|inverters|producers|strings|batteries/xs) {
|
||||
my $sub = $htol eq 'consumers' ? \&ConsumerVal :
|
||||
$htol eq 'inverters' ? \&InverterVal :
|
||||
$htol eq 'producers' ? \&ProducerVal :
|
||||
$htol eq 'strings' ? \&StringVal :
|
||||
$htol eq 'batteries' ? \&BatteryVal :
|
||||
'';
|
||||
|
||||
$h = $data{$name}{$htol};
|
||||
@ -16637,6 +16682,11 @@ sub listDataPool {
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
|
||||
for my $ckey (sort keys %{$h->{$idx}}) {
|
||||
if (ref $h->{$idx}{$ckey} eq 'ARRAY') {
|
||||
my $aser = join " ",@{$h->{$idx}{$ckey}};
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ".$aser."\n";
|
||||
}
|
||||
|
||||
if (ref $h->{$idx}{$ckey} eq 'HASH') {
|
||||
my $hk = qq{};
|
||||
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{$ckey}}) {
|
||||
@ -16648,6 +16698,7 @@ sub listDataPool {
|
||||
else {
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ". &{$sub} ($hash, $idx, $ckey, "")."\n";
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
}
|
||||
$sq .= $idx." => ".$cret."\n";
|
||||
@ -18050,11 +18101,6 @@ sub createAssociatedWith {
|
||||
$medev = $ame->[0] // '';
|
||||
push @cd, $medev;
|
||||
|
||||
my $badev = AttrVal ($name, 'setupBatteryDev', ''); # Battery Device
|
||||
($aba,$h) = parseParams ($badev);
|
||||
$badev = $aba->[0] // '';
|
||||
push @cd, $badev;
|
||||
|
||||
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices
|
||||
my $consumer = AttrVal ($name, "consumer${c}", "");
|
||||
my ($ac,$hc) = parseParams ($consumer);
|
||||
@ -18064,9 +18110,16 @@ sub createAssociatedWith {
|
||||
push @cd, $dswitch if($dswitch);
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) { # Battery Devices
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my $badev = AttrVal ($name, "setupBatteryDev${bn}", '');
|
||||
my ($aba) = parseParams ($badev);
|
||||
push @cd, $aba->[0] if($aba->[0]);
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) { # Inverter Devices
|
||||
$in = sprintf "%02d", $in;
|
||||
my $inc = AttrVal ($name, "setupInverterDev${in}", "");
|
||||
my $inc = AttrVal ($name, "setupInverterDev${in}", '');
|
||||
my ($ind) = parseParams ($inc);
|
||||
push @cd, $ind->[0] if($ind->[0]);
|
||||
}
|
||||
@ -18078,7 +18131,6 @@ sub createAssociatedWith {
|
||||
push @nd, $fcdev3 if($fcdev3 && $fcdev3 !~ /-API/xs);
|
||||
push @nd, $radev if($radev && $radev !~ /-API/xs);
|
||||
push @nd, $medev;
|
||||
push @nd, $badev;
|
||||
|
||||
for my $prn (1..$maxproducer) { # Producer Devices
|
||||
$prn = sprintf "%02d", $prn;
|
||||
@ -18624,10 +18676,17 @@ return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0);
|
||||
sub isBatteryUsed {
|
||||
my $name = shift;
|
||||
|
||||
my ($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
return if($err);
|
||||
my $valid;
|
||||
|
||||
return 1;
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my ($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
||||
next if($err);
|
||||
|
||||
$valid = 1;
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
################################################################
|
||||
@ -19809,8 +19868,6 @@ return $def;
|
||||
# $key: aiinitstate - Initialisierungsstatus der KI
|
||||
# aitrainstate - Traisningsstatus der KI
|
||||
# aiaddistate - Add Instanz Status der KI
|
||||
# batcharge - Bat SOC in %
|
||||
# batinstcap - installierte Batteriekapazität in Wh
|
||||
# ctrunning - aktueller Ausführungsstatus des Central Task
|
||||
# dwdRad1hAge - Alter des Rad1h Wertes als Datumstring
|
||||
# dwdRad1hAgeTS - Alter des Rad1h Wertes als Unix Timestamp
|
||||
@ -19823,8 +19880,6 @@ return $def;
|
||||
# consumerdevs - alle registrierten Consumerdevices (Array)
|
||||
# consumerCollected - Statusbit Consumer Attr gesammelt und ausgewertet
|
||||
# gridconsumption - aktueller Netzbezug
|
||||
# powerbatin - Batterie Ladeleistung
|
||||
# powerbatout - Batterie Entladeleistung
|
||||
# temp - aktuelle Außentemperatur
|
||||
# surplus - aktueller PV Überschuß
|
||||
# tomorrowconsumption - Verbrauch des kommenden Tages
|
||||
@ -20032,6 +20087,42 @@ sub ConsumerVal {
|
||||
return $def;
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Wert des Batterie-Hash zurückliefern
|
||||
# Usage:
|
||||
# BatteryVal ($hash or $name, $bn, $key, $def)
|
||||
#
|
||||
# $bn: Batterie Nummer (01,02,03,...)
|
||||
# $key: balias - Alias des Batterie Devices
|
||||
# bname - Name des Batterie Devices
|
||||
# basynchron - Asynchron Modus
|
||||
# bcharge - Bat SOC in %
|
||||
# binstcap - installierte Batteriekapazität in Wh
|
||||
# bpowerin - Batterie momentane Ladeleistung
|
||||
# bpowerout - Batterie momentane Entladeleistung
|
||||
#
|
||||
# $def: Defaultwert
|
||||
#
|
||||
###################################################################################################
|
||||
sub BatteryVal {
|
||||
my $name = shift;
|
||||
my $bn = shift;
|
||||
my $key = shift;
|
||||
my $def = shift;
|
||||
|
||||
if (ref $name eq 'HASH') {
|
||||
$name = $name->{NAME};
|
||||
}
|
||||
|
||||
if (defined $data{$name}{batteries} &&
|
||||
defined $data{$name}{batteries}{$bn} &&
|
||||
defined $data{$name}{batteries}{$bn}{$key}) {
|
||||
return $data{$name}{batteries}{$bn}{$key};
|
||||
}
|
||||
|
||||
return $def;
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Wert des Inverter-Hash zurückliefern
|
||||
# Usage:
|
||||
@ -20289,7 +20380,7 @@ to ensure that the system configuration is correct.
|
||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device or API for the delivery of radiation data. </td></tr>
|
||||
<tr><td> <b>setupInverterDevXX</b> </td><td>Device which provides PV performance data </td></tr>
|
||||
<tr><td> <b>setupMeterDev</b> </td><td>Device which supplies network I/O data </td></tr>
|
||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
||||
<tr><td> <b>setupBatteryDevXX</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
||||
<tr><td> <b>setupInverterStrings</b> </td><td>Identifier of the existing plant strings </td></tr>
|
||||
<tr><td> <b>setupStringAzimuth</b> </td><td>Azimuth of the plant strings </td></tr>
|
||||
<tr><td> <b>setupStringPeak</b> </td><td>the DC peak power of the plant strings </td></tr>
|
||||
@ -20372,6 +20463,7 @@ to ensure that the system configuration is correct.
|
||||
<li><b>batteryTrigger <1on>=<Value> <1off>=<Value> [<2on>=<Value> <2off>=<Value> ...] </b> <br><br>
|
||||
|
||||
Generates triggers when the battery charge exceeds or falls below certain values (SoC in %). <br>
|
||||
The SoC used is formed as an average of the SoCs of all defined battery devices. <br>
|
||||
If the last three SoC measurements exceed a defined <b>Xon-Bedingung</b>, the reading <b>batteryTrigger_X = on</b>
|
||||
is created/set. <br>
|
||||
If the last three SoC measurements fall below a defined <b>Xoff-Bedingung</b>, the reading
|
||||
@ -21106,6 +21198,28 @@ to ensure that the system configuration is correct.
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valBattery"></a>
|
||||
<li><b>valBattery </b> <br><br>
|
||||
Shows the operating values determined for the selected battery or all defined battery devices. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||
<tr><td> <b>bname </b> </td><td>Name of the device </td></tr>
|
||||
<tr><td> <b>balias </b> </td><td>Alias of the device </td></tr>
|
||||
<tr><td> <b>basynchron </b> </td><td>Mode of processing received battery events </td></tr>
|
||||
<tr><td> <b>bcharge </b> </td><td>SOC (State of Charge) of the battery (%) </td></tr>
|
||||
<tr><td> <b>binstcap </b> </td><td>installed battery capacity (Wh) </td></tr>
|
||||
<tr><td> <b>bpowerin </b> </td><td>current charging power (W) </td></tr>
|
||||
<tr><td> <b>bpowerout </b> </td><td>current discharge power (W) </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valConsumerMaster"></a>
|
||||
<li><b>valConsumerMaster </b> <br><br>
|
||||
@ -21542,7 +21656,7 @@ to ensure that the system configuration is correct.
|
||||
|
||||
<a id="SolarForecast-attr-ctrlBatSocManagement"></a>
|
||||
<li><b>ctrlBatSocManagement lowSoc=<Value> upSoC=<Value> [maxSoC=<Value>] [careCycle=<Value>] </b> <br><br>
|
||||
If a battery device (setupBatteryDev) is installed, this attribute activates the battery SoC management. <br>
|
||||
If a battery device (setupBatteryDevXX) is installed, this attribute activates the battery SoC management. <br>
|
||||
The <b>Battery_OptimumTargetSoC</b> reading contains the optimum minimum SoC calculated by the module. <br>
|
||||
The <b>Battery_ChargeRequest</b> reading is set to '1' if the current SoC has fallen below the minimum SoC. <br>
|
||||
In this case, the battery should be forcibly charged, possibly with mains power. <br>
|
||||
@ -21764,9 +21878,9 @@ to ensure that the system configuration is correct.
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
<b>Example: </b> <br>
|
||||
{ <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev', ''))[0]; <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev01', ''))[0]; <br>
|
||||
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); <br>
|
||||
my $cofc = ReadingsNum ($name, 'RestOfDayConsumptionForecast', 0); <br>
|
||||
my $diff = $pvfc - $cofc; <br>
|
||||
@ -22204,10 +22318,10 @@ to ensure that the system configuration is correct.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-setupBatteryDev"></a>
|
||||
<li><b>setupBatteryDev <Battery Device Name> pin=<Readingname>:<Unit> pout=<Readingname>:<Unit>
|
||||
[intotal=<Readingname>:<Unit>] [outtotal=<Readingname>:<Unit>]
|
||||
cap=<Option> [charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
<a id="SolarForecast-attr-setupBatteryDev" data-pattern="setupBatteryDev.*"></a>
|
||||
<li><b>setupBatteryDevXX <Battery Device Name> pin=<Readingname>:<Unit> pout=<Readingname>:<Unit>
|
||||
cap=<Option> [intotal=<Readingname>:<Unit>] [outtotal=<Readingname>:<Unit>]
|
||||
[charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
|
||||
Specifies an arbitrary Device and its Readings to deliver the battery performance data.
|
||||
The module assumes that the numerical value of the readings is always positive.
|
||||
@ -22247,7 +22361,7 @@ to ensure that the system configuration is correct.
|
||||
|
||||
<ul>
|
||||
<b>Example: </b> <br>
|
||||
attr <name> setupBatteryDev BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
attr <name> setupBatteryDev01 BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
@ -22711,7 +22825,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten </td></tr>
|
||||
<tr><td> <b>setupInverterDevXX</b> </td><td>Device welches PV Leistungsdaten liefert </td></tr>
|
||||
<tr><td> <b>setupMeterDev</b> </td><td>Device welches Netz I/O-Daten liefert </td></tr>
|
||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
||||
<tr><td> <b>setupBatteryDevXX</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
||||
<tr><td> <b>setupInverterStrings</b> </td><td>Bezeichner der vorhandenen Anlagenstrings </td></tr>
|
||||
<tr><td> <b>setupStringAzimuth</b> </td><td>Ausrichtung (Azimut) der Anlagenstrings </td></tr>
|
||||
<tr><td> <b>setupStringPeak</b> </td><td>die DC-Peakleistung der Anlagenstrings </td></tr>
|
||||
@ -22793,6 +22907,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<li><b>batteryTrigger <1on>=<Wert> <1off>=<Wert> [<2on>=<Wert> <2off>=<Wert> ...] </b> <br><br>
|
||||
|
||||
Generiert Trigger bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %). <br>
|
||||
Der verwendete SoC wird als Durchschnitt der SoC's aller definierten Batterie Geräte gebildet. <br>
|
||||
Überschreiten die letzten drei SoC-Messungen eine definierte <b>Xon-Bedingung</b>, wird das Reading
|
||||
<b>batteryTrigger_X = on</b> erstellt/gesetzt. <br>
|
||||
Unterschreiten die letzten drei SoC-Messungen eine definierte <b>Xoff-Bedingung</b>, wird das Reading
|
||||
@ -23537,6 +23652,28 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valBattery"></a>
|
||||
<li><b>valBattery </b> <br><br>
|
||||
Zeigt die ermittelten Betriebswerte der ausgewählten Batterie oder aller definierten Batteriegeräte. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||
<tr><td> <b>bname </b> </td><td>Name des Gerätes </td></tr>
|
||||
<tr><td> <b>balias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>basynchron </b> </td><td>Modus der Verarbeitung empfangener Batterie-Events </td></tr>
|
||||
<tr><td> <b>bcharge </b> </td><td>SOC (State of Charge) der Batterie (%) </td></tr>
|
||||
<tr><td> <b>binstcap </b> </td><td>installierte Batteriekapazität (Wh) </td></tr>
|
||||
<tr><td> <b>bpowerin </b> </td><td>momentane Ladeleistung (W) </td></tr>
|
||||
<tr><td> <b>bpowerout </b> </td><td>momentane Entladeleistung (W) </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valConsumerMaster"></a>
|
||||
<li><b>valConsumerMaster </b> <br><br>
|
||||
@ -23589,8 +23726,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>ifeed </b> </td><td>Eigenschaften der Energielieferung </td></tr>
|
||||
<tr><td> <b>igeneration </b> </td><td>aktuelle PV Erzeugung (W) </td></tr>
|
||||
<tr><td> <b>iicon </b> </td><td>die evtl. festgelegten Icons zur Darstellung des Gerätes in der Grafik </td></tr>
|
||||
<tr><td> <b>ialias </b> </td><td>Alias des Devices </td></tr>
|
||||
<tr><td> <b>iname </b> </td><td>Name des Devices </td></tr>
|
||||
<tr><td> <b>ialias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>iname </b> </td><td>Name des Gerätes </td></tr>
|
||||
<tr><td> <b>invertercap </b> </td><td>die nominale Leistung (W) des Wechselrichters (falls definiert) </td></tr>
|
||||
<tr><td> <b>istrings </b> </td><td>Liste der dem Wechselrichter zugeordneten Strings (falls definiert) </td></tr>
|
||||
</table>
|
||||
@ -23612,8 +23749,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>pfeed </b> </td><td>Eigenschaften der Energielieferung </td></tr>
|
||||
<tr><td> <b>pgeneration </b> </td><td>aktuelle Leistung (W) </td></tr>
|
||||
<tr><td> <b>picon </b> </td><td>die evtl. festgelegten Icons zur Darstellung des Gerätes in der Grafik </td></tr>
|
||||
<tr><td> <b>palias </b> </td><td>Alias des Devices </td></tr>
|
||||
<tr><td> <b>pname </b> </td><td>Name des Devices </td></tr>
|
||||
<tr><td> <b>palias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>pname </b> </td><td>Name des Gerätes </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
@ -23971,7 +24108,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
|
||||
<a id="SolarForecast-attr-ctrlBatSocManagement"></a>
|
||||
<li><b>ctrlBatSocManagement lowSoc=<Wert> upSoC=<Wert> [maxSoC=<Wert>] [careCycle=<Wert>] </b> <br><br>
|
||||
Sofern ein Batterie Device (setupBatteryDev) installiert ist, aktiviert dieses Attribut das Batterie
|
||||
Sofern ein Batterie Device (setupBatteryDevXX) installiert ist, aktiviert dieses Attribut das Batterie
|
||||
SoC-Management. <br>
|
||||
Das Reading <b>Battery_OptimumTargetSoC</b> enthält den vom Modul berechneten optimalen Mindest-SoC. <br>
|
||||
Das Reading <b>Battery_ChargeRequest</b> wird auf '1' gesetzt, wenn der aktuelle SoC unter den Mindest-SoC gefallen
|
||||
@ -24197,7 +24334,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
{ <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev', ''))[0]; <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev01', ''))[0]; <br>
|
||||
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); <br>
|
||||
my $cofc = ReadingsNum ($name, 'RestOfDayConsumptionForecast', 0); <br>
|
||||
my $diff = $pvfc - $cofc; <br>
|
||||
@ -24634,10 +24771,10 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-setupBatteryDev"></a>
|
||||
<li><b>setupBatteryDev <Batterie Device Name> pin=<Readingname>:<Einheit> pout=<Readingname>:<Einheit>
|
||||
[intotal=<Readingname>:<Einheit>] [outtotal=<Readingname>:<Einheit>]
|
||||
cap=<Option> [charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
<a id="SolarForecast-attr-setupBatteryDev" data-pattern="setupBatteryDev.*"></a>
|
||||
<li><b>setupBatteryDevXX <Batterie Device Name> pin=<Readingname>:<Einheit> pout=<Readingname>:<Einheit>
|
||||
cap=<Option> [intotal=<Readingname>:<Einheit>] [outtotal=<Readingname>:<Einheit>]
|
||||
[charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
|
||||
Legt ein beliebiges Device und seine Readings zur Lieferung der Batterie Leistungsdaten fest.
|
||||
Das Modul geht davon aus, dass der numerische Wert der Readings immer positiv ist.
|
||||
@ -24677,7 +24814,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
attr <name> setupBatteryDev BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
attr <name> setupBatteryDev01 BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
|
@ -158,7 +158,8 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.40.0" => "21.12.2024 new consumer key 'surpmeth' to calculate surplus in various variants for cunsumer switching ",
|
||||
"1.41.0" => "28.12.2024 _batSocTarget: minor code change, change setupBatteryDev to setupBatteryDev01, getter valBattery ",
|
||||
"1.40.0" => "21.12.2024 new consumer key 'surpmeth' to calculate surplus in various variants for consumer switching ",
|
||||
"1.39.8" => "21.12.2024 prepare of new consumer key 'surpmeth', _batSocTarget: improve care SoC management when dark doldrums ",
|
||||
"1.39.7" => "18.12.2024 ConsumptionRecommended calc method medianArray, change local owndata to global data ",
|
||||
"1.39.6" => "17.12.2024 replace global data-store by local owndata-store, remove sub _composeRemoteObj, delHashRefDeep removed ".
|
||||
@ -404,6 +405,7 @@ my $tempcoeffdef = -0.45;
|
||||
my $tempmodinc = 25; # default Temperaturerhöhung an Solarzellen gegenüber Umgebungstemperatur bei wolkenlosem Himmel
|
||||
my $tempbasedef = 25; # Temperatur Module bei Nominalleistung
|
||||
|
||||
my $maxbatteries = 1; # maximale Anzahl der möglichen Batterien
|
||||
my $maxconsumer = 16; # maximale Anzahl der möglichen Consumer (Attribut)
|
||||
my $maxproducer = 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
||||
my $maxinverter = 3; # maximale Anzahl der möglichen Inverter
|
||||
@ -515,7 +517,7 @@ my @aconfigs = qw( affectBatteryPreferredCharge affectConsForecastIdentWeekdays
|
||||
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
|
||||
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
|
||||
graphicSpaceSize graphicWeatherColor graphicWeatherColorNight
|
||||
setupMeterDev setupBatteryDev setupInverterStrings setupRadiationAPI setupStringPeak
|
||||
setupMeterDev setupInverterStrings setupRadiationAPI setupStringPeak
|
||||
setupRoofTops
|
||||
);
|
||||
|
||||
@ -525,6 +527,11 @@ for my $cn (1..$maxconsumer) {
|
||||
push @dd, "consumerSwitching${cn}"; # ctrlDebug: add specific Consumer
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
push @aconfigs, "setupBatteryDev${bn}"; # Anlagenkonfiguration: add Battery Attribute
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
push @aconfigs, "setupInverterDev${in}"; # Anlagenkonfiguration: add Inverter Attribute
|
||||
@ -580,6 +587,7 @@ my %hget = ( # Ha
|
||||
data => { fn => \&_getdata, needcred => 0 },
|
||||
html => { fn => \&_gethtml, needcred => 0 },
|
||||
ftui => { fn => \&_getftui, needcred => 0 },
|
||||
valBattery => { fn => \&_getlistvalBattery, needcred => 0 },
|
||||
valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
|
||||
valInverter => { fn => \&_getlistvalInverter, needcred => 0 },
|
||||
valProducer => { fn => \&_getlistvalProducer, needcred => 0 },
|
||||
@ -608,8 +616,6 @@ my %hattr = ( # H
|
||||
setupWeatherDev2 => { fn => \&_attrWeatherDev },
|
||||
setupWeatherDev3 => { fn => \&_attrWeatherDev },
|
||||
setupMeterDev => { fn => \&_attrMeterDev },
|
||||
setupBatteryDev => { fn => \&_attrBatteryDev },
|
||||
setupInverterDev => { fn => \&_attrInverterDev },
|
||||
setupInverterStrings => { fn => \&_attrInverterStrings },
|
||||
setupRadiationAPI => { fn => \&_attrRadiationAPI },
|
||||
setupStringPeak => { fn => \&_attrStringPeak },
|
||||
@ -617,6 +623,11 @@ my %hattr = ( # H
|
||||
flowGraphicControl => { fn => \&_attrflowGraphicControl },
|
||||
);
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$hattr{'setupBatteryDev'.$bn}{fn} = \&_attrBatteryDev;
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
$hattr{'setupInverterDev'.$in}{fn} = \&_attrInverterDev;
|
||||
@ -1179,13 +1190,18 @@ sub Initialize {
|
||||
my $srd = join ",", sort keys (%hcsr);
|
||||
my $gbc = 'pvReal,pvForecast,consumption,consumptionForecast,gridconsumption,energycosts,gridfeedin,feedincome';
|
||||
|
||||
my ($consumer, $setupprod, $setupinv, @allc);
|
||||
my ($consumer, $setupbat, $setupprod, $setupinv, @allc);
|
||||
for my $c (1..$maxconsumer) {
|
||||
$c = sprintf "%02d", $c;
|
||||
$consumer .= "consumer${c}:textField-long ";
|
||||
push @allc, $c;
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$setupbat .= "setupBatteryDev${bn}:textField-long ";
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
$setupinv .= "setupInverterDev${in}:textField-long ";
|
||||
@ -1276,9 +1292,9 @@ sub Initialize {
|
||||
"setupWeatherDev2 ".
|
||||
"setupWeatherDev3 ".
|
||||
"setupRoofTops ".
|
||||
"setupBatteryDev:textField-long ".
|
||||
"setupRadiationAPI ".
|
||||
"setupStringPeak ".
|
||||
$setupbat.
|
||||
$setupinv.
|
||||
$setupprod.
|
||||
$consumer.
|
||||
@ -1295,10 +1311,7 @@ sub Initialize {
|
||||
# $hash->{FW_addDetailToSummary} = 1;
|
||||
# $hash->{FW_atPageEnd} = 1; # wenn 1 -> kein Longpoll ohne informid in HTML-Tag
|
||||
|
||||
$hash->{AttrRenameMap} = { "graphicBeamHeight" => "graphicBeamHeightLevel1", # 07.05.24
|
||||
"ctrlWeatherDev1" => "setupWeatherDev1", # 20.08.24
|
||||
"ctrlWeatherDev2" => "setupWeatherDev2",
|
||||
"ctrlWeatherDev3" => "setupWeatherDev3",
|
||||
$hash->{AttrRenameMap} = { "setupBatteryDev" => "setupBatteryDev01", # 28.12.24
|
||||
"setupInverterDev" => "setupInverterDev01", # 11.10.24
|
||||
};
|
||||
|
||||
@ -2318,6 +2331,7 @@ sub Get {
|
||||
|
||||
my @pha = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{pvhist}};
|
||||
my @vcm = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{consumers}};
|
||||
my @vba = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{batteries}};
|
||||
my @vin = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{inverters}};
|
||||
my @vpn = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{producers}};
|
||||
my @vst = sort keys %{$data{$name}{strings}};
|
||||
@ -2325,11 +2339,13 @@ sub Get {
|
||||
my $hol = join ",", @ho;
|
||||
my $pvl = join ",", @pha;
|
||||
my $cml = join ",", @vcm;
|
||||
my $bal = join ",", @vba;
|
||||
my $inl = join ",", @vin;
|
||||
my $pnl = join ",", @vpn;
|
||||
my $str = join ",", @vst;
|
||||
|
||||
my $getlist = "Unknown argument $opt, choose one of ".
|
||||
"valBattery:#,$bal ".
|
||||
"valConsumerMaster:#,$cml ".
|
||||
"valInverter:#,$inl ".
|
||||
"valProducer:#,$pnl ".
|
||||
@ -4518,6 +4534,21 @@ sub _getlistCurrent {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
###############################################################
|
||||
# Getter valBattery
|
||||
###############################################################
|
||||
sub _getlistvalBattery {
|
||||
my $paref = shift;
|
||||
my $name = $paref->{name};
|
||||
my $arg = $paref->{arg};
|
||||
my $hash = $defs{$name};
|
||||
|
||||
my $ret = listDataPool ($hash, 'batteries', $arg);
|
||||
$ret .= lineFromSpaces ($ret, 30);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
###############################################################
|
||||
# Getter valConsumerMaster
|
||||
###############################################################
|
||||
@ -5302,8 +5333,8 @@ sub Attr {
|
||||
|
||||
if ($aName eq 'ctrlBatSocManagement' && $init_done) {
|
||||
if ($cmd eq 'set') {
|
||||
return qq{Define the key 'cap' with "attr $name setupBatteryDev" before this attribute in the correct form.}
|
||||
if(!CurrentVal($hash, 'batinstcap', 0)); # https://forum.fhem.de/index.php?msg=1310930
|
||||
return qq{Define the key 'cap' with "attr $name setupBatteryDev01" before this attribute in the correct form.}
|
||||
if(!BatteryVal ($hash, '01', 'binstcap', 0)); # https://forum.fhem.de/index.php?msg=1310930
|
||||
|
||||
my ($lowSoc, $upSoc, $maxsoc, $careCycle) = __parseAttrBatSoc ($name, $aVal);
|
||||
|
||||
@ -5836,9 +5867,7 @@ sub _attrInverterDev { ## no critic "not used"
|
||||
delete $data{$name}{inverters}{$in}{ifeed};
|
||||
}
|
||||
elsif ($paref->{cmd} eq 'del') {
|
||||
for my $k (keys %{$data{$name}{inverters}}) {
|
||||
delete $data{$name}{inverters}{$k} if($k eq $in);
|
||||
}
|
||||
delete $data{$name}{inverters}{$in};
|
||||
|
||||
readingsDelete ($hash, 'Current_PV');
|
||||
undef @{$data{$name}{current}{genslidereg}};
|
||||
@ -5993,6 +6022,7 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
return if(!$init_done);
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $bn = (split 'setupBatteryDev', $aName)[1];
|
||||
|
||||
if ($paref->{cmd} eq 'set') {
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
|
||||
@ -6010,6 +6040,8 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
if ($h->{pin} eq "-pout" && $h->{pout} eq "-pin") {
|
||||
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
|
||||
}
|
||||
|
||||
delete $data{$name}{batteries}{$bn}{basynchron};
|
||||
}
|
||||
elsif ($paref->{cmd} eq 'del') {
|
||||
readingsDelete ($hash, 'Current_PowerBatIn');
|
||||
@ -6025,11 +6057,7 @@ sub _attrBatteryDev { ## no critic "not used"
|
||||
delete $data{$name}{circular}{99}{batintot};
|
||||
delete $data{$name}{circular}{99}{batouttot};
|
||||
|
||||
delete $data{$name}{current}{powerbatout};
|
||||
delete $data{$name}{current}{powerbatin};
|
||||
delete $data{$name}{current}{batcharge};
|
||||
delete $data{$name}{current}{batinstcap};
|
||||
delete $data{$name}{current}{batasynchron};
|
||||
delete $data{$name}{batteries}{$bn};
|
||||
}
|
||||
|
||||
InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
|
||||
@ -6210,7 +6238,7 @@ sub Notify {
|
||||
|
||||
my $debug = getDebug ($myHash); # Debug Mode
|
||||
|
||||
my ($err, $medev, $badev, $h, $async);
|
||||
my ($err, $medev, $bname, $iname, $h, $async);
|
||||
|
||||
## Meter Event?
|
||||
#################
|
||||
@ -6241,11 +6269,12 @@ sub Notify {
|
||||
|
||||
## Battery Event?
|
||||
###################
|
||||
($err, $badev, $h) = isDeviceValid ( { name => $myName, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
$bname = BatteryVal ($myHash, $bn, 'bname', '');
|
||||
|
||||
if (!$err) {
|
||||
if ($devName eq $badev) {
|
||||
$async = $h->{asynchron} // 0;
|
||||
if ($devName eq $bname) {
|
||||
$async = BatteryVal ($myHash, $bn, 'basynchron', 0);
|
||||
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Battery device >$devName< received - asynchronous mode: $async});
|
||||
@ -6264,22 +6293,23 @@ sub Notify {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
## Inverter Event?
|
||||
####################
|
||||
for my $in (1..$maxinverter) {
|
||||
$in = sprintf "%02d", $in;
|
||||
my $iname = InverterVal ($myHash, $in, 'iname', '');
|
||||
$iname = InverterVal ($myHash, $in, 'iname', '');
|
||||
|
||||
if ($devName eq $iname) {
|
||||
my $iasync = InverterVal ($myHash, $in, 'iasynchron', 0);
|
||||
$async = InverterVal ($myHash, $in, 'iasynchron', 0);
|
||||
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Inverter device >$devName< received - asynchronous mode: $iasync});
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - Event of Inverter device >$devName< received - asynchronous mode: $async});
|
||||
}
|
||||
|
||||
if ($iasync) {
|
||||
if ($async) {
|
||||
if (CurrentVal ($myHash, 'ctrunning', 0)) {
|
||||
if ($debug =~ /notifyHandling/x) {
|
||||
Log3 ($myName, 1, qq{$myName DEBUG> notifyHandling - central task was called from NOTIFY when it is already running ... end this call});
|
||||
@ -6302,7 +6332,6 @@ sub Notify {
|
||||
|
||||
if (@consumers && grep /^$devName$/, @consumers) {
|
||||
my ($cname, $cindex, $dswname);
|
||||
my $type = $myHash->{TYPE};
|
||||
|
||||
for my $c (sort{$a<=>$b} keys %{$data{$myName}{consumers}}) {
|
||||
($err, $cname, $dswname) = getCDnames ($myHash, $c);
|
||||
@ -7287,6 +7316,9 @@ sub centralTask {
|
||||
return;
|
||||
}
|
||||
|
||||
$data{$name}{current}{ctrunning} = 1; # Central Task running Statusbit
|
||||
InternalTimer (gettimeofday() + 1.2, "FHEM::SolarForecast::releaseCentralTask", $hash, 0); # Freigabe centralTask
|
||||
|
||||
my $t = time; # aktuelle Unix-Zeit
|
||||
my $date = strftime "%Y-%m-%d", localtime($t); # aktuelles Datum
|
||||
my $chour = strftime "%H", localtime($t); # aktuelle Stunde in 24h format (00-23)
|
||||
@ -7295,10 +7327,6 @@ sub centralTask {
|
||||
my $dayname = strftime "%a", localtime($t); # aktueller Wochentagsname
|
||||
my $debug = getDebug ($hash); # Debug Module
|
||||
|
||||
$data{$name}{current}{ctrunning} = 1; # Central Task running Statusbit
|
||||
|
||||
InternalTimer (gettimeofday() + 1.2, "FHEM::SolarForecast::releaseCentralTask", $hash, 0); # Freigabe centralTask
|
||||
|
||||
my $centpars = {
|
||||
name => $name,
|
||||
type => $type,
|
||||
@ -9198,10 +9226,16 @@ sub _transferBatteryValues {
|
||||
my $day = $paref->{day};
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
return if($err);
|
||||
my $num = 0;
|
||||
my $socsum;
|
||||
|
||||
my $type = $paref->{type};
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
|
||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
||||
next if($err);
|
||||
|
||||
$num++;
|
||||
|
||||
my ($pin,$piunit) = split ":", $h->{pin}; # Readingname/Unit für aktuelle Batterieladung
|
||||
my ($pou,$pounit) = split ":", $h->{pout}; # Readingname/Unit für aktuelle Batterieentladung
|
||||
@ -9236,10 +9270,10 @@ sub _transferBatteryValues {
|
||||
$instcap = $instcap * ($bcapunit =~ /^kWh$/xi ? 1000 : 1);
|
||||
}
|
||||
|
||||
$data{$name}{current}{batinstcap} = $instcap; # installierte Batteriekapazität
|
||||
$data{$name}{batteries}{$bn}{binstcap} = $instcap; # installierte Batteriekapazität
|
||||
}
|
||||
else {
|
||||
delete $data{$name}{current}{batinstcap};
|
||||
delete $data{$name}{batteries}{$bn}{binstcap};
|
||||
}
|
||||
|
||||
my $debug = $paref->{debug};
|
||||
@ -9270,8 +9304,8 @@ sub _transferBatteryValues {
|
||||
($pbi,$pbo) = substSpecialCases ($params);
|
||||
}
|
||||
|
||||
# Batterielade-, enladeenergie in Circular speichern
|
||||
######################################################
|
||||
# Batterielade, -entladeenergie in Circular speichern
|
||||
#######################################################
|
||||
if (!defined CircularVal ($hash, 99, 'initdaybatintot', undef)) {
|
||||
$data{$name}{circular}{99}{initdaybatintot} = $btotin; # total Batterieladung zu Tagbeginn (Wh)
|
||||
}
|
||||
@ -9285,6 +9319,7 @@ sub _transferBatteryValues {
|
||||
|
||||
my $nhour = $chour+1;
|
||||
|
||||
|
||||
# Batterieladung aktuelle Stunde in pvHistory speichern
|
||||
#########################################################
|
||||
my $histbatintot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), "batintotal", undef); # totale Batterieladung zu Beginn einer Stunde
|
||||
@ -9305,6 +9340,7 @@ sub _transferBatteryValues {
|
||||
$data{$name}{circular}{sprintf("%02d",$nhour)}{batin} = $batinthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||
writeToHistory ( { paref => $paref, key => 'batinthishour', val => $batinthishour, hour => $nhour } );
|
||||
|
||||
|
||||
# Batterieentladung aktuelle Stunde in pvHistory speichern
|
||||
############################################################
|
||||
my $histbatouttot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), 'batouttotal', undef); # totale Betterieladung zu Beginn einer Stunde
|
||||
@ -9325,6 +9361,7 @@ sub _transferBatteryValues {
|
||||
$data{$name}{circular}{sprintf("%02d",$nhour)}{batout} = $batoutthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||
writeToHistory ( { paref => $paref, key => 'batoutthishour', val => $batoutthishour, hour => $nhour } );
|
||||
|
||||
|
||||
# täglichen max. SOC in pvHistory speichern
|
||||
#############################################
|
||||
my $batmaxsoc = HistoryVal ($hash, $day, 99, 'batmaxsoc', 0); # gespeicherter max. SOC des Tages
|
||||
@ -9341,13 +9378,20 @@ sub _transferBatteryValues {
|
||||
storeReading ('Current_PowerBatOut', (int $pbo).' W');
|
||||
storeReading ('Current_BatCharge', $soc.' %');
|
||||
|
||||
$data{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung
|
||||
$data{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung
|
||||
$data{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung
|
||||
$data{$name}{current}{batasynchron} = $h->{asynchron} if($h->{asynchron}); # asynchroner Modus = X
|
||||
$data{$name}{batteries}{$bn}{bname} = $badev; # Batterie Devicename
|
||||
$data{$name}{batteries}{$bn}{balias} = AttrVal ($badev, 'alias', $badev); # Alias Batterie Device
|
||||
$data{$name}{batteries}{$bn}{bpowerin} = int $pbi; # momentane Batterieladung
|
||||
$data{$name}{batteries}{$bn}{bpowerout} = int $pbo; # momentane Batterieentladung
|
||||
$data{$name}{batteries}{$bn}{bcharge} = $soc; # aktuelle Batterieladung
|
||||
$data{$name}{batteries}{$bn}{basynchron} = $h->{asynchron} // 0; # asynchroner Modus = X
|
||||
|
||||
push @{$data{$name}{current}{socslidereg}}, $soc; # Schieberegister Batterie SOC
|
||||
$socsum += $soc;
|
||||
}
|
||||
|
||||
if ($num) {
|
||||
push @{$data{$name}{current}{socslidereg}}, $socsum / $num; # Schieberegister average SOC aller Batterien
|
||||
limitArray ($data{$name}{current}{socslidereg}, $slidenummax);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -9358,7 +9402,6 @@ return;
|
||||
sub _batSocTarget {
|
||||
my $paref = shift;
|
||||
my $name = $paref->{name};
|
||||
my $type = $paref->{type};
|
||||
my $t = $paref->{t}; # aktuelle Zeit
|
||||
|
||||
return if(!isBatteryUsed ($name));
|
||||
@ -9366,8 +9409,8 @@ sub _batSocTarget {
|
||||
my $hash = $defs{$name};
|
||||
my $oldd2care = CircularVal ($hash, 99, 'days2care', 0);
|
||||
my $ltsmsr = CircularVal ($hash, 99, 'lastTsMaxSocRchd', undef);
|
||||
my $batcharge = CurrentVal ($hash, 'batcharge', 0); # aktuelle Ladung in %
|
||||
my $batinstcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $batcharge = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in %
|
||||
my $batinstcap = BatteryVal ($hash, '01', 'binstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $cgbt = AttrVal ($name, 'ctrlBatSocManagement', undef);
|
||||
|
||||
if ($cgbt && !$batinstcap) {
|
||||
@ -9484,7 +9527,8 @@ sub _batSocTarget {
|
||||
$target < $lowSoc ? $lowSoc :
|
||||
$target;
|
||||
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - observe low/up limits -> docare: $docare, Target: $target %");
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - basics -> docare: $docare, lowSoc: $lowSoc %, upSoc: $upSoc %");
|
||||
debugLog ($paref, 'batteryManagement', "SoC calc Step4 - observe low/up limits -> Target: $target %");
|
||||
|
||||
## auf 5er Schritte anpassen (40,45,50,...)
|
||||
#############################################
|
||||
@ -9569,8 +9613,8 @@ sub _batChargeRecmd {
|
||||
my $tomconfc = ReadingsNum ($name, 'Tomorrow_ConsumptionForecast', 0);
|
||||
|
||||
my $pvCu = ReadingsNum ($name, 'Current_PV', 0); # aktuelle PV Erzeugung
|
||||
my $batcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $soc = CurrentVal ($hash, 'batcharge', 0); # aktueller SOC (%)
|
||||
my $batcap = BatteryVal ($hash, '01', 'binstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $soc = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in % # aktueller SOC (%)
|
||||
my $curcon = ReadingsNum ($name, 'Current_Consumption', 0); # aktueller Verbrauch
|
||||
|
||||
my $inpmax = 0;
|
||||
@ -9756,8 +9800,8 @@ sub _createSummaries {
|
||||
my $gcon = CurrentVal ($hash, 'gridconsumption', 0); # aktueller Netzbezug
|
||||
my $tconsum = CurrentVal ($hash, 'tomorrowconsumption', undef); # Verbrauchsprognose für folgenden Tag
|
||||
my $gfeedin = CurrentVal ($hash, 'gridfeedin', 0);
|
||||
my $batin = CurrentVal ($hash, 'powerbatin', 0); # aktuelle Batterieladung
|
||||
my $batout = CurrentVal ($hash, 'powerbatout', 0); # aktuelle Batterieentladung
|
||||
my $batin = BatteryVal ($hash, '01', 'bpowerin', 0); # momentane Batterieladung
|
||||
my $batout = BatteryVal ($hash, '01', 'bpowerout', 0); # momentane Batterieentladung
|
||||
|
||||
my $pvgen = 0;
|
||||
my $pv2grid = 0; # PV-Erzeugung zu Grid-only
|
||||
@ -11400,8 +11444,8 @@ sub ___enableSwitchByBatPrioCharge {
|
||||
|
||||
return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert
|
||||
|
||||
my $cbcharge = CurrentVal ($hash, "batcharge", 0); # aktuelle Batterieladung
|
||||
$ena = 0 if($cbcharge < $pcb); # keine Freigabe wenn Batterieladung kleiner Soll-Ladung
|
||||
my $bcharge = BatteryVal ($hash, '01', 'bcharge', 0); # aktuelle Ladung in %
|
||||
$ena = 0 if($bcharge < $pcb); # keine Freigabe wenn Batterieladung kleiner Soll-Ladung
|
||||
|
||||
return $ena;
|
||||
}
|
||||
@ -16611,11 +16655,12 @@ sub listDataPool {
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol =~ /consumers|inverters|producers|strings/xs) {
|
||||
if ($htol =~ /consumers|inverters|producers|strings|batteries/xs) {
|
||||
my $sub = $htol eq 'consumers' ? \&ConsumerVal :
|
||||
$htol eq 'inverters' ? \&InverterVal :
|
||||
$htol eq 'producers' ? \&ProducerVal :
|
||||
$htol eq 'strings' ? \&StringVal :
|
||||
$htol eq 'batteries' ? \&BatteryVal :
|
||||
'';
|
||||
|
||||
$h = $data{$name}{$htol};
|
||||
@ -16637,6 +16682,11 @@ sub listDataPool {
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
|
||||
for my $ckey (sort keys %{$h->{$idx}}) {
|
||||
if (ref $h->{$idx}{$ckey} eq 'ARRAY') {
|
||||
my $aser = join " ",@{$h->{$idx}{$ckey}};
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ".$aser."\n";
|
||||
}
|
||||
|
||||
if (ref $h->{$idx}{$ckey} eq 'HASH') {
|
||||
my $hk = qq{};
|
||||
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{$ckey}}) {
|
||||
@ -16648,6 +16698,7 @@ sub listDataPool {
|
||||
else {
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ". &{$sub} ($hash, $idx, $ckey, "")."\n";
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
}
|
||||
$sq .= $idx." => ".$cret."\n";
|
||||
@ -18050,11 +18101,6 @@ sub createAssociatedWith {
|
||||
$medev = $ame->[0] // '';
|
||||
push @cd, $medev;
|
||||
|
||||
my $badev = AttrVal ($name, 'setupBatteryDev', ''); # Battery Device
|
||||
($aba,$h) = parseParams ($badev);
|
||||
$badev = $aba->[0] // '';
|
||||
push @cd, $badev;
|
||||
|
||||
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices
|
||||
my $consumer = AttrVal ($name, "consumer${c}", "");
|
||||
my ($ac,$hc) = parseParams ($consumer);
|
||||
@ -18064,9 +18110,16 @@ sub createAssociatedWith {
|
||||
push @cd, $dswitch if($dswitch);
|
||||
}
|
||||
|
||||
for my $bn (1..$maxbatteries) { # Battery Devices
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my $badev = AttrVal ($name, "setupBatteryDev${bn}", '');
|
||||
my ($aba) = parseParams ($badev);
|
||||
push @cd, $aba->[0] if($aba->[0]);
|
||||
}
|
||||
|
||||
for my $in (1..$maxinverter) { # Inverter Devices
|
||||
$in = sprintf "%02d", $in;
|
||||
my $inc = AttrVal ($name, "setupInverterDev${in}", "");
|
||||
my $inc = AttrVal ($name, "setupInverterDev${in}", '');
|
||||
my ($ind) = parseParams ($inc);
|
||||
push @cd, $ind->[0] if($ind->[0]);
|
||||
}
|
||||
@ -18078,7 +18131,6 @@ sub createAssociatedWith {
|
||||
push @nd, $fcdev3 if($fcdev3 && $fcdev3 !~ /-API/xs);
|
||||
push @nd, $radev if($radev && $radev !~ /-API/xs);
|
||||
push @nd, $medev;
|
||||
push @nd, $badev;
|
||||
|
||||
for my $prn (1..$maxproducer) { # Producer Devices
|
||||
$prn = sprintf "%02d", $prn;
|
||||
@ -18624,10 +18676,17 @@ return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0);
|
||||
sub isBatteryUsed {
|
||||
my $name = shift;
|
||||
|
||||
my ($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev', method => 'attr' } );
|
||||
return if($err);
|
||||
my $valid;
|
||||
|
||||
return 1;
|
||||
for my $bn (1..$maxbatteries) {
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my ($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
||||
next if($err);
|
||||
|
||||
$valid = 1;
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
################################################################
|
||||
@ -19809,8 +19868,6 @@ return $def;
|
||||
# $key: aiinitstate - Initialisierungsstatus der KI
|
||||
# aitrainstate - Traisningsstatus der KI
|
||||
# aiaddistate - Add Instanz Status der KI
|
||||
# batcharge - Bat SOC in %
|
||||
# batinstcap - installierte Batteriekapazität in Wh
|
||||
# ctrunning - aktueller Ausführungsstatus des Central Task
|
||||
# dwdRad1hAge - Alter des Rad1h Wertes als Datumstring
|
||||
# dwdRad1hAgeTS - Alter des Rad1h Wertes als Unix Timestamp
|
||||
@ -19823,8 +19880,6 @@ return $def;
|
||||
# consumerdevs - alle registrierten Consumerdevices (Array)
|
||||
# consumerCollected - Statusbit Consumer Attr gesammelt und ausgewertet
|
||||
# gridconsumption - aktueller Netzbezug
|
||||
# powerbatin - Batterie Ladeleistung
|
||||
# powerbatout - Batterie Entladeleistung
|
||||
# temp - aktuelle Außentemperatur
|
||||
# surplus - aktueller PV Überschuß
|
||||
# tomorrowconsumption - Verbrauch des kommenden Tages
|
||||
@ -20032,6 +20087,42 @@ sub ConsumerVal {
|
||||
return $def;
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Wert des Batterie-Hash zurückliefern
|
||||
# Usage:
|
||||
# BatteryVal ($hash or $name, $bn, $key, $def)
|
||||
#
|
||||
# $bn: Batterie Nummer (01,02,03,...)
|
||||
# $key: balias - Alias des Batterie Devices
|
||||
# bname - Name des Batterie Devices
|
||||
# basynchron - Asynchron Modus
|
||||
# bcharge - Bat SOC in %
|
||||
# binstcap - installierte Batteriekapazität in Wh
|
||||
# bpowerin - Batterie momentane Ladeleistung
|
||||
# bpowerout - Batterie momentane Entladeleistung
|
||||
#
|
||||
# $def: Defaultwert
|
||||
#
|
||||
###################################################################################################
|
||||
sub BatteryVal {
|
||||
my $name = shift;
|
||||
my $bn = shift;
|
||||
my $key = shift;
|
||||
my $def = shift;
|
||||
|
||||
if (ref $name eq 'HASH') {
|
||||
$name = $name->{NAME};
|
||||
}
|
||||
|
||||
if (defined $data{$name}{batteries} &&
|
||||
defined $data{$name}{batteries}{$bn} &&
|
||||
defined $data{$name}{batteries}{$bn}{$key}) {
|
||||
return $data{$name}{batteries}{$bn}{$key};
|
||||
}
|
||||
|
||||
return $def;
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Wert des Inverter-Hash zurückliefern
|
||||
# Usage:
|
||||
@ -20289,7 +20380,7 @@ to ensure that the system configuration is correct.
|
||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device or API for the delivery of radiation data. </td></tr>
|
||||
<tr><td> <b>setupInverterDevXX</b> </td><td>Device which provides PV performance data </td></tr>
|
||||
<tr><td> <b>setupMeterDev</b> </td><td>Device which supplies network I/O data </td></tr>
|
||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
||||
<tr><td> <b>setupBatteryDevXX</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
||||
<tr><td> <b>setupInverterStrings</b> </td><td>Identifier of the existing plant strings </td></tr>
|
||||
<tr><td> <b>setupStringAzimuth</b> </td><td>Azimuth of the plant strings </td></tr>
|
||||
<tr><td> <b>setupStringPeak</b> </td><td>the DC peak power of the plant strings </td></tr>
|
||||
@ -20372,6 +20463,7 @@ to ensure that the system configuration is correct.
|
||||
<li><b>batteryTrigger <1on>=<Value> <1off>=<Value> [<2on>=<Value> <2off>=<Value> ...] </b> <br><br>
|
||||
|
||||
Generates triggers when the battery charge exceeds or falls below certain values (SoC in %). <br>
|
||||
The SoC used is formed as an average of the SoCs of all defined battery devices. <br>
|
||||
If the last three SoC measurements exceed a defined <b>Xon-Bedingung</b>, the reading <b>batteryTrigger_X = on</b>
|
||||
is created/set. <br>
|
||||
If the last three SoC measurements fall below a defined <b>Xoff-Bedingung</b>, the reading
|
||||
@ -21106,6 +21198,28 @@ to ensure that the system configuration is correct.
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valBattery"></a>
|
||||
<li><b>valBattery </b> <br><br>
|
||||
Shows the operating values determined for the selected battery or all defined battery devices. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||
<tr><td> <b>bname </b> </td><td>Name of the device </td></tr>
|
||||
<tr><td> <b>balias </b> </td><td>Alias of the device </td></tr>
|
||||
<tr><td> <b>basynchron </b> </td><td>Mode of processing received battery events </td></tr>
|
||||
<tr><td> <b>bcharge </b> </td><td>SOC (State of Charge) of the battery (%) </td></tr>
|
||||
<tr><td> <b>binstcap </b> </td><td>installed battery capacity (Wh) </td></tr>
|
||||
<tr><td> <b>bpowerin </b> </td><td>current charging power (W) </td></tr>
|
||||
<tr><td> <b>bpowerout </b> </td><td>current discharge power (W) </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valConsumerMaster"></a>
|
||||
<li><b>valConsumerMaster </b> <br><br>
|
||||
@ -21542,7 +21656,7 @@ to ensure that the system configuration is correct.
|
||||
|
||||
<a id="SolarForecast-attr-ctrlBatSocManagement"></a>
|
||||
<li><b>ctrlBatSocManagement lowSoc=<Value> upSoC=<Value> [maxSoC=<Value>] [careCycle=<Value>] </b> <br><br>
|
||||
If a battery device (setupBatteryDev) is installed, this attribute activates the battery SoC management. <br>
|
||||
If a battery device (setupBatteryDevXX) is installed, this attribute activates the battery SoC management. <br>
|
||||
The <b>Battery_OptimumTargetSoC</b> reading contains the optimum minimum SoC calculated by the module. <br>
|
||||
The <b>Battery_ChargeRequest</b> reading is set to '1' if the current SoC has fallen below the minimum SoC. <br>
|
||||
In this case, the battery should be forcibly charged, possibly with mains power. <br>
|
||||
@ -21764,9 +21878,9 @@ to ensure that the system configuration is correct.
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
<b>Example: </b> <br>
|
||||
{ <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev', ''))[0]; <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev01', ''))[0]; <br>
|
||||
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); <br>
|
||||
my $cofc = ReadingsNum ($name, 'RestOfDayConsumptionForecast', 0); <br>
|
||||
my $diff = $pvfc - $cofc; <br>
|
||||
@ -22204,10 +22318,10 @@ to ensure that the system configuration is correct.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-setupBatteryDev"></a>
|
||||
<li><b>setupBatteryDev <Battery Device Name> pin=<Readingname>:<Unit> pout=<Readingname>:<Unit>
|
||||
[intotal=<Readingname>:<Unit>] [outtotal=<Readingname>:<Unit>]
|
||||
cap=<Option> [charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
<a id="SolarForecast-attr-setupBatteryDev" data-pattern="setupBatteryDev.*"></a>
|
||||
<li><b>setupBatteryDevXX <Battery Device Name> pin=<Readingname>:<Unit> pout=<Readingname>:<Unit>
|
||||
cap=<Option> [intotal=<Readingname>:<Unit>] [outtotal=<Readingname>:<Unit>]
|
||||
[charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
|
||||
Specifies an arbitrary Device and its Readings to deliver the battery performance data.
|
||||
The module assumes that the numerical value of the readings is always positive.
|
||||
@ -22247,7 +22361,7 @@ to ensure that the system configuration is correct.
|
||||
|
||||
<ul>
|
||||
<b>Example: </b> <br>
|
||||
attr <name> setupBatteryDev BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
attr <name> setupBatteryDev01 BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
@ -22711,7 +22825,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten </td></tr>
|
||||
<tr><td> <b>setupInverterDevXX</b> </td><td>Device welches PV Leistungsdaten liefert </td></tr>
|
||||
<tr><td> <b>setupMeterDev</b> </td><td>Device welches Netz I/O-Daten liefert </td></tr>
|
||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
||||
<tr><td> <b>setupBatteryDevXX</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
||||
<tr><td> <b>setupInverterStrings</b> </td><td>Bezeichner der vorhandenen Anlagenstrings </td></tr>
|
||||
<tr><td> <b>setupStringAzimuth</b> </td><td>Ausrichtung (Azimut) der Anlagenstrings </td></tr>
|
||||
<tr><td> <b>setupStringPeak</b> </td><td>die DC-Peakleistung der Anlagenstrings </td></tr>
|
||||
@ -22793,6 +22907,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<li><b>batteryTrigger <1on>=<Wert> <1off>=<Wert> [<2on>=<Wert> <2off>=<Wert> ...] </b> <br><br>
|
||||
|
||||
Generiert Trigger bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %). <br>
|
||||
Der verwendete SoC wird als Durchschnitt der SoC's aller definierten Batterie Geräte gebildet. <br>
|
||||
Überschreiten die letzten drei SoC-Messungen eine definierte <b>Xon-Bedingung</b>, wird das Reading
|
||||
<b>batteryTrigger_X = on</b> erstellt/gesetzt. <br>
|
||||
Unterschreiten die letzten drei SoC-Messungen eine definierte <b>Xoff-Bedingung</b>, wird das Reading
|
||||
@ -23537,6 +23652,28 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valBattery"></a>
|
||||
<li><b>valBattery </b> <br><br>
|
||||
Zeigt die ermittelten Betriebswerte der ausgewählten Batterie oder aller definierten Batteriegeräte. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||
<tr><td> <b>bname </b> </td><td>Name des Gerätes </td></tr>
|
||||
<tr><td> <b>balias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>basynchron </b> </td><td>Modus der Verarbeitung empfangener Batterie-Events </td></tr>
|
||||
<tr><td> <b>bcharge </b> </td><td>SOC (State of Charge) der Batterie (%) </td></tr>
|
||||
<tr><td> <b>binstcap </b> </td><td>installierte Batteriekapazität (Wh) </td></tr>
|
||||
<tr><td> <b>bpowerin </b> </td><td>momentane Ladeleistung (W) </td></tr>
|
||||
<tr><td> <b>bpowerout </b> </td><td>momentane Entladeleistung (W) </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-get-valConsumerMaster"></a>
|
||||
<li><b>valConsumerMaster </b> <br><br>
|
||||
@ -23589,8 +23726,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>ifeed </b> </td><td>Eigenschaften der Energielieferung </td></tr>
|
||||
<tr><td> <b>igeneration </b> </td><td>aktuelle PV Erzeugung (W) </td></tr>
|
||||
<tr><td> <b>iicon </b> </td><td>die evtl. festgelegten Icons zur Darstellung des Gerätes in der Grafik </td></tr>
|
||||
<tr><td> <b>ialias </b> </td><td>Alias des Devices </td></tr>
|
||||
<tr><td> <b>iname </b> </td><td>Name des Devices </td></tr>
|
||||
<tr><td> <b>ialias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>iname </b> </td><td>Name des Gerätes </td></tr>
|
||||
<tr><td> <b>invertercap </b> </td><td>die nominale Leistung (W) des Wechselrichters (falls definiert) </td></tr>
|
||||
<tr><td> <b>istrings </b> </td><td>Liste der dem Wechselrichter zugeordneten Strings (falls definiert) </td></tr>
|
||||
</table>
|
||||
@ -23612,8 +23749,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>pfeed </b> </td><td>Eigenschaften der Energielieferung </td></tr>
|
||||
<tr><td> <b>pgeneration </b> </td><td>aktuelle Leistung (W) </td></tr>
|
||||
<tr><td> <b>picon </b> </td><td>die evtl. festgelegten Icons zur Darstellung des Gerätes in der Grafik </td></tr>
|
||||
<tr><td> <b>palias </b> </td><td>Alias des Devices </td></tr>
|
||||
<tr><td> <b>pname </b> </td><td>Name des Devices </td></tr>
|
||||
<tr><td> <b>palias </b> </td><td>Alias des Gerätes </td></tr>
|
||||
<tr><td> <b>pname </b> </td><td>Name des Gerätes </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
|
||||
@ -23971,7 +24108,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
|
||||
<a id="SolarForecast-attr-ctrlBatSocManagement"></a>
|
||||
<li><b>ctrlBatSocManagement lowSoc=<Wert> upSoC=<Wert> [maxSoC=<Wert>] [careCycle=<Wert>] </b> <br><br>
|
||||
Sofern ein Batterie Device (setupBatteryDev) installiert ist, aktiviert dieses Attribut das Batterie
|
||||
Sofern ein Batterie Device (setupBatteryDevXX) installiert ist, aktiviert dieses Attribut das Batterie
|
||||
SoC-Management. <br>
|
||||
Das Reading <b>Battery_OptimumTargetSoC</b> enthält den vom Modul berechneten optimalen Mindest-SoC. <br>
|
||||
Das Reading <b>Battery_ChargeRequest</b> wird auf '1' gesetzt, wenn der aktuelle SoC unter den Mindest-SoC gefallen
|
||||
@ -24197,7 +24334,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
{ <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev', ''))[0]; <br>
|
||||
my $batdev = (split " ", AttrVal ($name, 'setupBatteryDev01', ''))[0]; <br>
|
||||
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); <br>
|
||||
my $cofc = ReadingsNum ($name, 'RestOfDayConsumptionForecast', 0); <br>
|
||||
my $diff = $pvfc - $cofc; <br>
|
||||
@ -24634,10 +24771,10 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-setupBatteryDev"></a>
|
||||
<li><b>setupBatteryDev <Batterie Device Name> pin=<Readingname>:<Einheit> pout=<Readingname>:<Einheit>
|
||||
[intotal=<Readingname>:<Einheit>] [outtotal=<Readingname>:<Einheit>]
|
||||
cap=<Option> [charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
<a id="SolarForecast-attr-setupBatteryDev" data-pattern="setupBatteryDev.*"></a>
|
||||
<li><b>setupBatteryDevXX <Batterie Device Name> pin=<Readingname>:<Einheit> pout=<Readingname>:<Einheit>
|
||||
cap=<Option> [intotal=<Readingname>:<Einheit>] [outtotal=<Readingname>:<Einheit>]
|
||||
[charge=<Readingname>] [asynchron=<Option>] </b> <br><br>
|
||||
|
||||
Legt ein beliebiges Device und seine Readings zur Lieferung der Batterie Leistungsdaten fest.
|
||||
Das Modul geht davon aus, dass der numerische Wert der Readings immer positiv ist.
|
||||
@ -24677,7 +24814,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
attr <name> setupBatteryDev BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
attr <name> setupBatteryDev01 BatDummy pin=BatVal:W pout=-pin intotal=BatInTot:Wh outtotal=BatOutTot:Wh cap=BatCap:kWh
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user