From 63edb19fef0e6b20d26b0a01a256aa1ad774c1d7 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sat, 7 Sep 2024 19:37:11 +0000 Subject: [PATCH] 76_SolarForecast: contrib 1.32.0 git-svn-id: https://svn.fhem.de/fhem/trunk@29130 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/76_SolarForecast.pm | 370 ++++++++++++++++---- 1 file changed, 300 insertions(+), 70 deletions(-) diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 10d84c4b8..a42c0a160 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -155,7 +155,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( - "1.32.0" => "26.08.2024 vermeide Kalkulation und Speicherung negativer Verbrauchswerte ". + "1.32.0" => "02.09.2024 new attr setupOtherProducerXX, report calculation and storage of negative consumption values ". "Forum: https://forum.fhem.de/index.php?msg=1319083 ", "1.31.0" => "20.08.2024 rename attributes ctrlWeatherDevX to setupWeatherDevX ", "1.30.0" => "18.08.2024 new attribute flowGraphicShift, Forum:https://forum.fhem.de/index.php?msg=1318597 ", @@ -439,6 +439,7 @@ my $tempmodinc = 25; my $tempbasedef = 25; # Temperatur Module bei Nominalleistung my $maxconsumer = 16; # maximale Anzahl der möglichen Consumer (Attribut) +my $maxproducer = 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut) my $epiecMaxCycles = 10; # Anzahl Einschaltzyklen (Consumer) für verbraucherspezifische Energiestück Ermittlung my @ctypes = qw(dishwasher dryer washingmachine heater charger other noSchedule); # erlaubte Consumer Typen @@ -548,6 +549,11 @@ for my $cinit (1..$maxconsumer) { push @dd, "consumerSwitching${cinit}"; # ctrlDebug: add specific Consumer } +for my $prn (1..$maxproducer) { + $prn = sprintf "%02d", $prn; + push @aconfigs, "setupOtherProducer${prn}"; # Anlagenkonfiguration: add Producer Attribute +} + my $allwidgets = 'icon|sortable|uzsu|knob|noArg|time|text|slider|multiple|select|bitfield|widgetList|colorpicker'; # Steuerhashes @@ -624,6 +630,11 @@ my %hattr = ( # H setupRoofTops => { fn => \&_attrRoofTops }, ); + for my $prn (1..$maxproducer) { + $prn = sprintf "%02d", $prn; + $hattr{'setupOtherProducer'.$prn}{fn} = \&_attrOtherProducer; + } + my %htr = ( # Hash even/odd für 0 => { cl => 'even' }, 1 => { cl => 'odd' }, @@ -1106,7 +1117,13 @@ my %hfspvh = ( gcons => { fn => \&_storeVal, storname => 'gcons', validkey => undef, fpar => 'comp99' }, # bezogene Energie gfeedin => { fn => \&_storeVal, storname => 'gfeedin', validkey => undef, fpar => 'comp99' }, # eingespeiste Energie con => { fn => \&_storeVal, storname => 'con', validkey => undef, fpar => 'comp99' }, # realer Hausverbrauch Energie - pvrl => { fn => \&_storeVal, storname => 'pvrl', validkey => 'pvrlvd', fpar => 'comp99' }, # realer Energieertrag + pvrl => { fn => \&_storeVal, storname => 'pvrl', validkey => 'pvrlvd', fpar => 'comp99' }, # realer Energieertrag PV + pprl01 => { fn => \&_storeVal, storname => 'pprl01', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 01 + pprl02 => { fn => \&_storeVal, storname => 'pprl02', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 02 + pprl03 => { fn => \&_storeVal, storname => 'pprl03', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 03 + etotalp01 => { fn => \&_storeVal, storname => 'etotalp01', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 01 + etotalp02 => { fn => \&_storeVal, storname => 'etotalp02', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 02 + etotalp03 => { fn => \&_storeVal, storname => 'etotalp03', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 03 ); @@ -1138,12 +1155,17 @@ sub Initialize { my $srd = join ",", sort keys (%hcsr); my $gbc = 'pvReal,pvForecast,consumption,consumptionForecast,gridconsumption,energycosts,gridfeedin,feedincome'; - my ($consumer,@allc); + my ($consumer, $setupprod, @allc); for my $c (1..$maxconsumer) { $c = sprintf "%02d", $c; $consumer .= "consumer${c}:textField-long "; push @allc, $c; } + + for my $prn (1..$maxproducer) { + $prn = sprintf "%02d", $prn; + $setupprod .= "setupOtherProducer${prn}:textField-long "; + } my $allcs = join ",", @allc; my $dm = 'none,'.join ",", sort @dd; @@ -1239,6 +1261,7 @@ sub Initialize { "setupBatteryDev:textField-long ". "setupRadiationAPI ". "setupStringPeak ". + $setupprod. $consumer. $readingFnAttributes; @@ -2027,7 +2050,6 @@ sub _setreset { ## no critic "not used" my $name = $paref->{name}; my $prop = $paref->{prop} // return qq{no source specified for reset}; my $type = $paref->{type}; - my $hash = $defs{$name}; if ($prop eq 'pvHistory') { @@ -5458,6 +5480,72 @@ sub _attrMeterDev { ## no critic "not used" return; } +################################################################ +# Attr setupOtherProducer +################################################################ +sub _attrOtherProducer { ## no critic "not used" + my $paref = shift; + my $name = $paref->{name}; + my $aVal = $paref->{aVal}; + my $aName = $paref->{aName}; + my $type = $paref->{type}; + + return if(!$init_done); + + my $hash = $defs{$name}; + my $prn = (split 'Producer', $aName)[1]; + + if ($paref->{cmd} eq 'set') { + my ($err, $dev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } ); + return $err if($err); + + if (!$h->{pcurr} || !$h->{etotal}) { + return qq{The syntax of '$aName' is not correct. Please consider the commandref.}; + } + } + elsif ($paref->{cmd} eq 'del') { + $paref->{prn} = $prn; + __delProducerValues ($paref); + delete $paref->{prn}; + } + + InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0); + InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben + +return; +} + +################################################################ +# löschen Werte eines Producers aus Speicherhashes +################################################################ +sub __delProducerValues { + my $paref = shift; + my $name = $paref->{name}; + my $prn = $paref->{prn} // return 'The producer number is empty'; # Producernummer (01, 02, 03) + my $type = $paref->{type}; + my $hash = $defs{$name}; + + deleteReadingspec ($hash, ".*_PPreal".$prn); + readingsDelete ($hash, 'Current_PP'.$prn); + delete $data{$type}{$name}{current}{'generationp'.$prn}; + delete $data{$type}{$name}{current}{'etotalp'.$prn}; + + for my $hod (keys %{$data{$type}{$name}{circular}}) { + delete $data{$type}{$name}{circular}{$hod}{'pprl'.$prn}; + } + + for my $dy (sort keys %{$data{$type}{$name}{pvhist}}) { + for my $hr (sort keys %{$data{$type}{$name}{pvhist}{$dy}}) { + delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'pprl'.$prn}; + delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'etotalp'.$prn}; + } + } + + Log3 ($name, 3, qq{$name - all stored data from producer $prn has been deleted}); + +return; +} + ################################################################ # Attr setupInverterDev ################################################################ @@ -6593,6 +6681,7 @@ sub centralTask { _transferAPIRadiationValues ($centpars); # Raw Erzeugungswerte aus solcastapi-Hash übertragen und Forecast mit/ohne Korrektur erstellen _calcMaxEstimateToday ($centpars); # heutigen Max PV Estimate & dessen Tageszeit ermitteln _transferInverterValues ($centpars); # WR Werte übertragen + _transferProducerValues ($centpars); # Werte anderer Erzeuger übertragen _transferMeterValues ($centpars); # Energy Meter auswerten _transferBatteryValues ($centpars); # Batteriewerte einsammeln _batSocTarget ($centpars); # Batterie Optimum Ziel SOC berechnen @@ -7125,8 +7214,7 @@ sub _specialActivities { $gcon = ReadingsNum ($name, "Today_Hour24_GridConsumption", 0); storeReading ('LastHourGridconsumptionReal', "$gcon Wh", $ts); - deleteReadingspec ($hash, '(Today_Hour(.*_Grid.*|.*_PV.*|.*_Bat.*)|powerTrigger_.*|Today_MaxPVforecast.*)'); - + deleteReadingspec ($hash, '(Today_Hour(.*_Grid.*|.*_PV.*|.*_PPreal.*|.*_Bat.*)|powerTrigger_.*|Today_MaxPVforecast.*)'); readingsDelete ($hash, 'Today_PVdeviation'); readingsDelete ($hash, 'Today_PVreal'); @@ -8235,6 +8323,83 @@ sub _transferInverterValues { return; } +################################################################ +# Werte anderer Erzeuger ermitteln und übertragen +################################################################ +sub _transferProducerValues { + my $paref = shift; + my $name = $paref->{name}; + my $t = $paref->{t}; # aktuelle Unix-Zeit + my $chour = $paref->{chour}; + my $day = $paref->{day}; + + my $hash = $defs{$name}; + + for my $prn (1..$maxproducer) { + $prn = sprintf "%02d", $prn; + my ($err, $prdev, $h) = isDeviceValid ( { name => $name, obj => 'setupOtherProducer'.$prn, method => 'attr' } ); + next if($err); + + my $type = $paref->{type}; + + my ($pcread, $pcunit) = split ":", $h->{pcurr}; # Readingname/Unit für aktuelle Erzeugung + my ($edread, $etunit) = split ":", $h->{etotal}; # Readingname/Unit für Energie total (Erzeugung) + + next if(!$pcread || !$edread); + + my $pu = $pcunit =~ /^kW$/xi ? 1000 : 1; + my $p = ReadingsNum ($prdev, $pcread, 0) * $pu; # aktuelle Erzeugung (W) + $p = $p < 0 ? 0 : sprintf("%.0f", $p); + + storeReading ('Current_PP'.$prn, $p.' W'); + $data{$type}{$name}{current}{'generationp'.$prn} = $p; + + my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1; + my $etotal = ReadingsNum ($prdev, $edread, 0) * $etu; # Erzeugung total (Wh) + + debugLog ($paref, "collectData", "collect Producer$prn data - device: $prdev =>"); + debugLog ($paref, "collectData", "pcurr: $p W, etotalp$prn: $etotal Wh"); + + my $nhour = $chour + 1; + my $histetot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), 'etotalp'.$prn, 0); # etotal zu Beginn einer Stunde + my $warn = ''; + my ($ethishour, $etotsvd); + + if (!$histetot) { # etotal der aktuelle Stunde gesetzt ? + writeToHistory ( { paref => $paref, key => 'etotalp'.$prn, val => $etotal, hour => $nhour } ); + + $etotsvd = CurrentVal ($hash, 'etotalp'.$prn, $etotal); + $ethishour = int ($etotal - $etotsvd); + } + else { + $ethishour = int ($etotal - $histetot); + } + + $data{$type}{$name}{current}{'etotalp'.$prn} = $etotal; # aktuellen etotal des WR speichern + + if ($ethishour < 0) { + $ethishour = 0; + my $vl = 3; + my $pre = '- WARNING -'; + + if ($paref->{debug} =~ /collectData/xs) { + $vl = 1; + $pre = 'DEBUG> - WARNING -'; + } + + Log3 ($name, $vl, "$name $pre The Total Energy of Producer$prn '$prdev' is lower than the value saved before. This situation is unexpected and the Energy generated of current hour is set to '0'."); + $warn = ' (WARNING $prdev invalid real produced energy occured - see Logfile)'; + } + + storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_PPreal'.$prn, $ethishour.' Wh'.$warn); + $data{$type}{$name}{circular}{sprintf("%02d",$nhour)}{'pprl'.$prn} = $ethishour; # Ringspeicher P real + + writeToHistory ( { paref => $paref, key => 'pprl'.$prn, val => $ethishour, hour => $nhour } ); + } + +return; +} + ################################################################ # Werte Meter Device ermitteln und übertragen ################################################################ @@ -10599,15 +10764,15 @@ sub _estConsumptionForecast { next if($m eq $day); # next wenn gleicher Tag (Datum) wie heute if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen - my $hdn = HistoryVal ($hash, $m, 99, "dayname", undef); + my $hdn = HistoryVal ($hash, $m, 99, 'dayname', undef); next if(!$hdn || $hdn ne $nhday); } - my $hcon = HistoryVal ($hash, $m, $nhhr, "con", 0); # historische Verbrauchswerte + my $hcon = HistoryVal ($hash, $m, $nhhr, 'con', 0); # historische Verbrauchswerte next if(!$hcon); if ($hcon < 0) { # V1.32.0 - $hcon = 0; + #$hcon = 0; my $vl = 3; my $pre = '- WARNING -'; @@ -10616,7 +10781,7 @@ sub _estConsumptionForecast { $pre = 'DEBUG> - WARNING -'; } - Log3 ($name, $vl, "$name $pre The stored Energy consumption of day/hour $m/$nhhr is negative. This appears to be an error and this hour is taken into account in the consumption forecast with value '0'."); + Log3 ($name, $vl, "$name $pre The stored Energy consumption of day/hour $m/$nhhr is negative. This appears to be an error. The incorrect value can be deleted with 'set $name reset consumption $m $nhhr'."); } for my $c (sort{$a<=>$b} keys %{$acref}) { # historischen Verbrauch aller registrierten Verbraucher aufaddieren @@ -11152,20 +11317,25 @@ return ($val1,$val2); # Energieverbrauch des Hauses in History speichern ################################################################ sub saveEnergyConsumption { - my $paref = shift; - my $name = $paref->{name}; - my $chour = $paref->{chour}; + my $paref = shift; + my $name = $paref->{name}; + my $chour = $paref->{chour}; - my $shr = $chour + 1; - my $pvrl = ReadingsNum ($name, "Today_Hour".sprintf("%02d",$shr)."_PVreal", 0); - my $gfeedin = ReadingsNum ($name, "Today_Hour".sprintf("%02d",$shr)."_GridFeedIn", 0); - my $gcon = ReadingsNum ($name, "Today_Hour".sprintf("%02d",$shr)."_GridConsumption", 0); - my $batin = ReadingsNum ($name, "Today_Hour".sprintf("%02d",$shr)."_BatIn", 0); - my $batout = ReadingsNum ($name, "Today_Hour".sprintf("%02d",$shr)."_BatOut", 0); + my $shr = sprintf "%02d", ($chour + 1); + my $pvrl = ReadingsNum ($name, "Today_Hour".$shr."_PVreal", 0); + my $gfeedin = ReadingsNum ($name, "Today_Hour".$shr."_GridFeedIn", 0); + my $gcon = ReadingsNum ($name, "Today_Hour".$shr."_GridConsumption", 0); + my $batin = ReadingsNum ($name, "Today_Hour".$shr."_BatIn", 0); + my $batout = ReadingsNum ($name, "Today_Hour".$shr."_BatOut", 0); + my $con = $pvrl - $gfeedin + $gcon - $batin + $batout; - if ($con < 0) { # V1.32.0 - $con = 0; + for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen + $prn = sprintf "%02d", $prn; + $con += ReadingsNum ($name, "Today_Hour".$shr."_PPreal".$prn, 0); + } + + if (int $paref->{minute} > 30 && $con < 0) { # V1.32.0 : erst den "eingeschwungenen" Zustand mit mehreren Meßwerten auswerten my $vl = 3; my $pre = '- WARNING -'; @@ -11174,7 +11344,7 @@ sub saveEnergyConsumption { $pre = 'DEBUG> - WARNING -'; } - Log3 ($name, $vl, "$name $pre The calculated Energy consumption of the house is negative. This appears to be an error and the energy consumption for the current hour is set to '0'."); + Log3 ($name, $vl, "$name $pre The calculated Energy consumption of the house is negative. This appears to be an error. Check Readings _PVreal, _GridFeedIn, _GridConsumption, _BatIn, _BatOut of hour >$shr<"); } writeToHistory ( { paref => $paref, key => 'con', val => $con, hour => $shr } ); @@ -11712,15 +11882,6 @@ sub _checkSetupNotComplete { ### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !! ########################################################################################## - my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # 16.06.2024 - if ($dir) { - readingsSingleUpdate ($hash, 'setupStringAzimuth', $dir, 0); - } - - my $dec = ReadingsVal ($name, 'moduleDeclination', ''); # 16.06.2024 - if ($dec) { - readingsSingleUpdate ($hash, 'setupStringDeclination', $dec, 0); - } ########################################################################################## @@ -14998,7 +15159,13 @@ sub listDataPool { my $don = HistoryVal ($hash, $day, $key, 'DoN', '-'); my $conprc = HistoryVal ($hash, $day, $key, 'conprice', '-'); my $feedprc = HistoryVal ($hash, $day, $key, 'feedprice', '-'); - + my $etotp01 = HistoryVal ($hash, $day, $key, 'etotalp01', '-'); + my $etotp02 = HistoryVal ($hash, $day, $key, 'etotalp02', '-'); + my $etotp03 = HistoryVal ($hash, $day, $key, 'etotalp03', '-'); + my $pprl01 = HistoryVal ($hash, $day, $key, 'pprl01', '-'); + my $pprl02 = HistoryVal ($hash, $day, $key, 'pprl02', '-'); + my $pprl03 = HistoryVal ($hash, $day, $key, 'pprl03', '-'); + if ($export eq 'csv') { $hexp->{$day}{$key}{PVreal} = $pvrl; $hexp->{$day}{$key}{PVrealValid} = $pvrlvd; @@ -15027,28 +15194,44 @@ sub listDataPool { $hexp->{$day}{$key}{DayOrNight} = $don; $hexp->{$day}{$key}{PurchasePrice} = $conprc; $hexp->{$day}{$key}{FeedInPrice} = $feedprc; + $hexp->{$day}{$key}{etotalp01} = $etotp01; + $hexp->{$day}{$key}{etotalp02} = $etotp02; + $hexp->{$day}{$key}{etotalp03} = $etotp03; + $hexp->{$day}{$key}{pprl01} = $pprl01; + $hexp->{$day}{$key}{pprl02} = $pprl02; + $hexp->{$day}{$key}{pprl03} = $pprl03; } $ret .= "\n " if($ret); $ret .= $key." => "; - $ret .= "etotal: $etotal, pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h"; + $ret .= "etotal: $etotal, " if($key ne '99'); + $ret .= "pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h"; $ret .= "\n "; + $ret .= "etotalp01: $etotp01, etotalp02: $etotp02, etotalp03: $etotp03" if($key ne '99'); + $ret .= "\n " if($key ne '99'); + $ret .= "pprl01: $pprl01, pprl02: $pprl02, pprl03: $pprl03"; + $ret .= "\n "; $ret .= "confc: $confc, con: $con, gcons: $gcons, conprice: $conprc"; $ret .= "\n "; $ret .= "gfeedin: $gfeedin, feedprice: $feedprc"; $ret .= "\n "; $ret .= "DoN: $don, sunaz: $sunaz, sunalt: $sunalt"; $ret .= "\n "; - $ret .= "batintotal: $btotin, batin: $batin, batouttotal: $btotout, batout: $batout"; - $ret .= "\n " if($key eq '99'); - $ret .= "batmaxsoc: $batmsoc, batsetsoc: $batssoc" if($key eq '99'); + $ret .= "batintotal: $btotin, batouttotal: $btotout, " if($key ne '99'); + $ret .= "batin: $batin, batout: $batout"; + $ret .= "\n " if($key eq '99'); + $ret .= "batmaxsoc: $batmsoc, batsetsoc: $batssoc" if($key eq '99'); $ret .= "\n "; - $ret .= "wid: $wid"; - $ret .= ", wcc: $wcc"; - $ret .= ", rr1c: $rr1c"; - $ret .= ", temp: $temp" if($temp); - $ret .= ", pvcorrf: $pvcorrf"; - $ret .= ", dayname: $dayname" if($dayname); + + if ($key ne '99') { + $ret .= "wid: $wid, "; + $ret .= "wcc: $wcc, "; + $ret .= "rr1c: $rr1c, "; + $ret .= "pvcorrf: $pvcorrf"; + } + + $ret .= "temp: $temp, " if($temp); + $ret .= "dayname: $dayname, " if($dayname); my $csm; for my $c (1..$maxconsumer) { @@ -15193,31 +15376,34 @@ sub listDataPool { my $confc = CircularVal ($hash, $idx, 'confc', '-'); my $gcons = CircularVal ($hash, $idx, 'gcons', '-'); my $gfeedin = CircularVal ($hash, $idx, 'gfeedin', '-'); - my $wid = CircularVal ($hash, $idx, "weatherid", '-'); - my $wtxt = CircularVal ($hash, $idx, "weathertxt", '-'); - my $wccv = CircularVal ($hash, $idx, "wcc", '-'); - my $rr1c = CircularVal ($hash, $idx, "rr1c", '-'); - my $temp = CircularVal ($hash, $idx, "temp", '-'); - my $pvcorrf = CircularVal ($hash, $idx, "pvcorrf", '-'); - my $quality = CircularVal ($hash, $idx, "quality", '-'); - my $batin = CircularVal ($hash, $idx, "batin", '-'); - my $batout = CircularVal ($hash, $idx, "batout", '-'); - my $tdayDvtn = CircularVal ($hash, $idx, "tdayDvtn", '-'); - my $ydayDvtn = CircularVal ($hash, $idx, "ydayDvtn", '-'); + my $wid = CircularVal ($hash, $idx, 'weatherid', '-'); + my $wtxt = CircularVal ($hash, $idx, 'weathertxt', '-'); + my $wccv = CircularVal ($hash, $idx, 'wcc', '-'); + my $rr1c = CircularVal ($hash, $idx, 'rr1c', '-'); + my $temp = CircularVal ($hash, $idx, 'temp', '-'); + my $pvcorrf = CircularVal ($hash, $idx, 'pvcorrf', '-'); + my $quality = CircularVal ($hash, $idx, 'quality', '-'); + my $batin = CircularVal ($hash, $idx, 'batin', '-'); + my $batout = CircularVal ($hash, $idx, 'batout', '-'); + my $tdayDvtn = CircularVal ($hash, $idx, 'tdayDvtn', '-'); + my $ydayDvtn = CircularVal ($hash, $idx, 'ydayDvtn', '-'); my $ltsmsr = CircularVal ($hash, $idx, 'lastTsMaxSocRchd', '-'); my $ntsmsc = CircularVal ($hash, $idx, 'nextTsMaxSocChge', '-'); my $dtocare = CircularVal ($hash, $idx, 'days2care', '-'); - my $fitot = CircularVal ($hash, $idx, "feedintotal", '-'); - my $idfi = CircularVal ($hash, $idx, "initdayfeedin", '-'); - my $gcontot = CircularVal ($hash, $idx, "gridcontotal", '-'); - my $idgcon = CircularVal ($hash, $idx, "initdaygcon", '-'); - my $idbitot = CircularVal ($hash, $idx, "initdaybatintot", '-'); - my $bitot = CircularVal ($hash, $idx, "batintot", '-'); - my $idbotot = CircularVal ($hash, $idx, "initdaybatouttot", '-'); - my $botot = CircularVal ($hash, $idx, "batouttot", '-'); - my $rtaitr = CircularVal ($hash, $idx, "runTimeTrainAI", '-'); - my $fsaitr = CircularVal ($hash, $idx, "aitrainLastFinishTs", '-'); - my $aicts = CircularVal ($hash, $idx, "attrInvChangedTs", '-'); + my $fitot = CircularVal ($hash, $idx, 'feedintotal', '-'); + my $idfi = CircularVal ($hash, $idx, 'initdayfeedin', '-'); + my $gcontot = CircularVal ($hash, $idx, 'gridcontotal', '-'); + my $idgcon = CircularVal ($hash, $idx, 'initdaygcon', '-'); + my $idbitot = CircularVal ($hash, $idx, 'initdaybatintot', '-'); + my $bitot = CircularVal ($hash, $idx, 'batintot', '-'); + my $idbotot = CircularVal ($hash, $idx, 'initdaybatouttot', '-'); + my $botot = CircularVal ($hash, $idx, 'batouttot', '-'); + my $rtaitr = CircularVal ($hash, $idx, 'runTimeTrainAI', '-'); + my $fsaitr = CircularVal ($hash, $idx, 'aitrainLastFinishTs', '-'); + my $aicts = CircularVal ($hash, $idx, 'attrInvChangedTs', '-'); + my $pprl01 = CircularVal ($hash, $idx, 'pprl01', '-'); + my $pprl02 = CircularVal ($hash, $idx, 'pprl02', '-'); + my $pprl03 = CircularVal ($hash, $idx, 'pprl03', '-'); my $pvcf = _ldchash2val ( {pool => $h, idx => $idx, key => 'pvcorrf', cval => $pvcorrf} ); my $cfq = _ldchash2val ( {pool => $h, idx => $idx, key => 'quality', cval => $quality} ); @@ -15231,6 +15417,7 @@ sub listDataPool { $sq .= $idx." => pvapifc: $pvapifc, pvaifc: $pvaifc, pvfc: $pvfc, aihit: $aihit, pvrl: $pvrl\n"; $sq .= " batin: $batin, batout: $batout, confc: $confc, gcon: $gcons, gfeedin: $gfeedin, wcc: $wccv, rr1c: $rr1c\n"; $sq .= " temp: $temp, wid: $wid, wtxt: $wtxt\n"; + $sq .= " pprl01: $pprl01, pprl02: $pprl02, pprl03: $pprl03\n"; $sq .= " pvcorrf: $pvcf\n"; $sq .= " quality: $cfq\n"; $sq .= " pvrlsum: $pvrs\n"; @@ -16422,7 +16609,7 @@ sub createAssociatedWith { my $badev = AttrVal ($name, 'setupBatteryDev', ''); # Battery Device ($aba,$h) = parseParams ($badev); $badev = $aba->[0] // ""; - + for my $c (sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}) { # Consumer Devices my $consumer = AttrVal ($name, "consumer${c}", ""); my ($ac,$hc) = parseParams ($consumer); @@ -16441,6 +16628,13 @@ sub createAssociatedWith { push @nd, $indev; push @nd, $medev; push @nd, $badev; + + for my $prn (1..$maxproducer) { + $prn = sprintf "%02d", $prn; + my $pdc = AttrVal ($name, "setupOtherProducer${prn}", ""); + my ($prd) = parseParams ($pdc); + push @nd, $prd->[0] if($prd->[0]); + } my @ndn = (); @@ -19076,12 +19270,14 @@ to ensure that the system configuration is correct. csmeXX Energy consumption of ConsumerXX in the hour of the day (hour 99 = daily energy consumption) cyclescsmXX Number of active cycles of ConsumerXX of the day DoN Sunrise and sunset status (0 - night, 1 - day) - etotal total energy yield (Wh) at the beginning of the hour + etotal PV meter reading “Total energy yield” (Wh) at the beginning of the hour + etotalpXX Meter reading “Total energy yield” (Wh) of producer XX at the beginning of the hour gcons real power consumption (Wh) from the electricity grid gfeedin real feed-in (Wh) into the electricity grid feedprice Remuneration for the feed-in of one kWh. The currency of the price is defined in the setupMeterDev. hourscsmeXX total active hours of the day from ConsumerXX minutescsmXX total active minutes in the hour of ConsumerXX + pprlXX Energy generation of producer XX (see attribute setupOtherProducerXX) in the hour (Wh) pvfc the predicted PV yield (Wh) pvrl real PV generation (Wh) pvrlvd 1-'pvrl' is valid and is taken into account in the learning process, 0-'pvrl' is assessed as abnormal @@ -19138,6 +19334,7 @@ to ensure that the system configuration is correct. pvfcsum summary PV forecast per cloud area over the entire term pvrl real PV generation of the last 24h (Attention: pvforecast and pvreal do not refer to the same period!) pvrlsum summary real PV generation per cloud area over the entire term + pprlXX Energy generation of producer XX (see attribute setupOtherProducerXX) in the last 24 hours (Wh) quality Quality of the autocorrection factors (0..1), where 'simple' is the quality of the simple correction factor. runTimeTrainAI Duration of the last AI training aitrainLastFinishTs Timestamp of the last successful AI training @@ -20380,7 +20577,7 @@ to ensure that the system configuration is correct. +
+ + +
+ + Hinweis: Durch Löschen des Attributes werden ebenfalls die intern korrespondierenden Daten entfernt. + +
  • setupRadiationAPI