diff --git a/fhem/CHANGED b/fhem/CHANGED index d1eec4a0c..8aab0a7c9 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,9 @@ # 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 + - change: 76_SolarForecast: set moduleAzimuth to attr setupStringAzimuth + set moduleDeclination to setupStringDeclination + set moduleRoofTops to attr setupRoofTops + !NOTE! save FHEM config after restart - feature: 76_SolarForecast: new consumer key exconfc - change: 76_SolarForecast: set modulePeakString to attr setupStringPeak !NOTE! save FHEM config after restart diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 7f0f4825d..c79d69c7c 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -157,6 +157,10 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.29.0" => "16.06.2024 _setreset: improve reset consumerMaster ". + "tranformed setter moduleAzimuth to setupStringAzimuth ". + "tranformed setter moduleDeclination to setupStringDeclination ". + "tranformed setter moduleRoofTops to setupRoofTops ", "1.28.0" => "15.06.2024 new consumer key exconfc, Forum: https://forum.fhem.de/index.php?msg=1315111 ", "1.27.0" => "12.06.2024 __VictronVRM_ApiResponseLogin: check token not empty ". "transformed setter modulePeakString to attr setupStringPeak ", @@ -501,9 +505,8 @@ my @fs = qw( ftui_forecast.css ); # Anlagenkonfiguration: maßgebliche Readings my @rconfigs = qw( pvCorrectionFactor_Auto - moduleAzimuth - moduleDeclination - moduleRoofTops + setupStringAzimuth + setupStringDeclination batteryTrigger powerTrigger energyH4Trigger @@ -530,6 +533,7 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight setupMeterDev setupBatteryDev setupInverterDev setupInverterStrings setupRadiationAPI setupStringPeak + setupRoofTops ); for my $cinit (1..$maxconsumer) { @@ -571,10 +575,8 @@ my %hset = ( # Ha pvCorrectionFactor_21 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_Auto => { fn => \&_setpvCorrectionFactorAuto }, reset => { fn => \&_setreset }, - roofIdentPair => { fn => \&_setroofIdentPair }, - moduleRoofTops => { fn => \&_setmoduleRoofTops }, - moduleDeclination => { fn => \&_setmoduleDeclination }, - moduleAzimuth => { fn => \&_setmoduleAzimuth }, + setupStringDeclination => { fn => \&_setstringDeclination }, + setupStringAzimuth => { fn => \&_setstringAzimuth }, operatingMemory => { fn => \&_setoperatingMemory }, vrmCredentials => { fn => \&_setVictronCredentials }, aiDecTree => { fn => \&_setaiDecTree }, @@ -612,6 +614,7 @@ my %hattr = ( # H setupInverterStrings => { fn => \&_attrInverterStrings }, setupRadiationAPI => { fn => \&_attrRadiationAPI }, setupStringPeak => { fn => \&_attrStringPeak }, + setupRoofTops => { fn => \&_attrRoofTops }, ); my %htr = ( # Hash even/odd für @@ -666,14 +669,14 @@ my %hqtxt = ( DE => qq{Bitte geben sie alle von Ihnen verwendeten Stringnamen mit "attr LINK setupInverterStrings" an} }, mps => { EN => qq{Please enter the DC peak power of each string with "attr LINK setupStringPeak"}, DE => qq{Bitte geben sie die DC Spitzenleistung von jedem String mit "attr LINK setupStringPeak" an} }, - mdr => { EN => qq{Please specify the module direction with "set LINK moduleAzimuth"}, - DE => qq{Bitte geben sie die Modulausrichtung mit "set LINK moduleAzimuth" an} }, - mta => { EN => qq{Please specify the module tilt angle with "set LINK moduleDeclination"}, - DE => qq{Bitte geben sie den Modulneigungswinkel mit "set LINK moduleDeclination" an} }, + mdr => { EN => qq{Please specify the module direction with "set LINK setupStringAzimuth"}, + DE => qq{Bitte geben sie die Modulausrichtung mit "set LINK setupStringAzimuth" an} }, + mta => { EN => qq{Please specify the module tilt angle with "set LINK setupStringDeclination"}, + DE => qq{Bitte geben sie den Modulneigungswinkel mit "set LINK setupStringDeclination" an} }, rip => { EN => qq{Please specify at least one combination Rooftop-ID/SolCast-API with "set LINK roofIdentPair"}, DE => qq{Bitte geben Sie mindestens eine Kombination Rooftop-ID/SolCast-API mit "set LINK roofIdentPair" an} }, - mrt => { EN => qq{Please set the assignment String / Rooftop identification with "set LINK moduleRoofTops"}, - DE => qq{Bitte setzen sie die Zuordnung String / Rooftop Identifikation mit "set LINK moduleRoofTops"} }, + mrt => { EN => qq{Please set the assignment String / Rooftop identification with "attr LINK setupRoofTops"}, + DE => qq{Bitte setzen sie die Zuordnung String / Rooftop Identifikation mit "attr LINK setupRoofTops"} }, coord => { EN => qq{Please set attributes 'latitude' and 'longitude' in global device}, DE => qq{Bitte setzen sie die Attribute 'latitude' und 'longitude' im global Device} }, cnsm => { EN => qq{Consumer}, @@ -1223,6 +1226,7 @@ sub Initialize { "setupInverterDev:textField-long ". "setupInverterStrings ". "setupMeterDev:textField-long ". + "setupRoofTops ". "setupBatteryDev:textField-long ". "setupRadiationAPI ". "setupStringPeak ". @@ -1423,7 +1427,6 @@ sub Set { consumerPlanning consumption energyH4TriggerSet - moduleRoofTopSet powerTriggerSet pvCorrection roofIdentPair @@ -1485,13 +1488,12 @@ sub Set { ## API spezifische Setter ########################### if (isSolCastUsed ($hash)) { - $setlist .= "moduleRoofTops ". - "roofIdentPair " + $setlist .= "roofIdentPair " ; } elsif (isForecastSolarUsed ($hash)) { - $setlist .= "moduleAzimuth ". - "moduleDeclination " + $setlist .= "setupStringAzimuth ". + "setupStringDeclination " ; } elsif (isVictronKiUsed ($hash)) { @@ -1499,8 +1501,8 @@ sub Set { ; } else { - $setlist .= "moduleAzimuth ". - "moduleDeclination " + $setlist .= "setupStringAzimuth ". + "setupStringDeclination " ; } @@ -1711,42 +1713,6 @@ sub _setVictronCredentials { ## no critic "not used" return $msg; } -################################################################ -# Setter moduleRoofTops -################################################################ -sub _setmoduleRoofTops { ## no critic "not used" - my $paref = shift; - my $hash = $paref->{hash}; - my $name = $paref->{name}; - my $arg = $paref->{arg} // return qq{no module RoofTop was provided}; - - my ($a,$h) = parseParams ($arg); - - if (!keys %$h) { - return qq{The provided module RoofTop has wrong format}; - } - - while (my ($is, $pk) = each %$h) { - my $rtid = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'rtid', ''); - my $apikey = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'apikey', ''); - - if (!$rtid || !$apikey) { - return qq{The roofIdentPair "$pk" of String "$is" has no Rooftop-ID and/or SolCast-API key assigned ! \n}. - qq{Set the roofIdentPair "$pk" previously with "set $name roofIdentPair".} ; - } - } - - readingsSingleUpdate ($hash, "moduleRoofTops", $arg, 1); - writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben - - return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett - - my $ret = createStringConfig ($hash); - return $ret if($ret); - -return; -} - ################################################################ # Setter operationMode ################################################################ @@ -1806,9 +1772,9 @@ return; } ################################################################ -# Setter moduleDeclination +# Setter setupStringDeclination ################################################################ -sub _setmoduleDeclination { ## no critic "not used" +sub _setstringDeclination { ## no critic "not used" my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; @@ -1828,8 +1794,8 @@ sub _setmoduleDeclination { ## no critic "not used" } } - readingsSingleUpdate ($hash, 'moduleDeclination', $arg, 1); - writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben + readingsSingleUpdate ($hash, 'setupStringDeclination', $arg, 1); + writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett @@ -1840,13 +1806,13 @@ return; } ################################################################ -# Setter moduleAzimuth +# Setter setupStringAzimuth # # Angabe entweder als Azimut-Bezeichner oder direkte # Azimut Angabe -180 ...0...180 # ################################################################ -sub _setmoduleAzimuth { ## no critic "not used" +sub _setstringAzimuth { ## no critic "not used" my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; @@ -1866,7 +1832,7 @@ sub _setmoduleAzimuth { ## no critic "not used" } } - readingsSingleUpdate ($hash, 'moduleAzimuth', $arg, 1); + readingsSingleUpdate ($hash, 'setupStringAzimuth', $arg, 1); writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett @@ -2019,8 +1985,7 @@ sub _setreset { ## no critic "not used" my $hash = $paref->{hash}; my $name = $paref->{name}; my $prop = $paref->{prop} // return qq{no source specified for reset}; - - my $type = $hash->{TYPE}; + my $type = $paref->{type}; if ($prop eq 'pvHistory') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? @@ -2178,12 +2143,6 @@ sub _setreset { ## no critic "not used" return; } - if ($prop eq 'moduleRoofTopSet') { - readingsDelete ($hash, "moduleRoofTops"); - writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); - return; - } - readingsDelete ($hash, $prop); if ($prop eq 'roofIdentPair') { @@ -2218,22 +2177,24 @@ sub _setreset { ## no critic "not used" } if ($prop eq 'consumerMaster') { # Verbraucherhash löschen - my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben + my $c = $paref->{prop1} // ''; # bestimmten Verbraucher setzen falls angegeben if ($c) { - my $calias = ConsumerVal ($hash, $c, "alias", ""); - delete $data{$type}{$name}{consumers}{$c}; - Log3($name, 3, qq{$name - Consumer "$calias" deleted from memory}); + $paref->{c} = $c; + delConsumerFromMem ($paref); # spezifischen Consumer aus History löschen } else { - for my $cs (keys %{$data{$type}{$name}{consumers}}) { - my $calias = ConsumerVal ($hash, $cs, "alias", ""); - delete $data{$type}{$name}{consumers}{$cs}; - Log3($name, 3, qq{$name - Consumer "$calias" deleted from memory}); + for my $c (keys %{$data{$type}{$name}{consumers}}) { + $paref->{c} = $c; + delConsumerFromMem ($paref); # alle Consumer aus History löschen } } - - writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + delete $paref->{c}; + $data{$type}{$name}{current}{consumerCollected} = 0; # Consumer neu sammeln + + writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + centralTask ($hash, 0); } createAssociatedWith ($hash); @@ -2604,7 +2565,7 @@ sub __solCast_ApiRequest { my $string; ($string, $allstrings) = split ",", $allstrings, 2; - my $rft = ReadingsVal ($name, "moduleRoofTops", ""); + my $rft = AttrVal ($name, 'setupRoofTops', ''); my ($a,$h) = parseParams ($rft); my $pk = $h->{$string} // q{}; @@ -5295,17 +5256,11 @@ sub _attrconsumer { ## no critic "not used" else { my $day = strftime "%d", localtime(time); # aktueller Tag (range 01 to 31) my ($c) = $aName =~ /consumer([0-9]+)/xs; + + $paref->{c} = $c; + delConsumerFromMem ($paref); # Consumerdaten aus History löschen deleteReadingspec ($hash, "consumer${c}.*"); - - for my $i (1..24) { # Consumer aus History löschen - delete $data{$type}{$name}{pvhist}{$day}{sprintf("%02d",$i)}{"csmt${c}"}; - delete $data{$type}{$name}{pvhist}{$day}{sprintf("%02d",$i)}{"csme${c}"}; - } - - delete $data{$type}{$name}{pvhist}{$day}{99}{"csmt${c}"}; - delete $data{$type}{$name}{pvhist}{$day}{99}{"csme${c}"}; - delete $data{$type}{$name}{consumers}{$c}; # Consumer Hash Verbraucher löschen } writeCacheToFile ($hash, 'consumers', $csmcache.$name); # Cache File Consumer schreiben @@ -5569,6 +5524,45 @@ sub _attrStringPeak { ## no critic "not used" return; } +################################################################ +# Attr setupRoofTops +################################################################ +sub _attrRoofTops { ## no critic "not used" + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $aVal = $paref->{aVal}; + + return if(!$init_done); + + if ($paref->{cmd} eq 'set') { + my ($a,$h) = parseParams ($aVal); + + if (!keys %$h) { + return qq{The attribute content has wrong format}; + } + + while (my ($is, $pk) = each %$h) { + my $rtid = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'rtid', ''); + my $apikey = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'apikey', ''); + + if (!$rtid || !$apikey) { + return qq{The roofIdentPair "$pk" of String "$is" has no Rooftop-ID and/or SolCast-API key assigned! \n}. + qq{Set the roofIdentPair "$pk" previously with "set $name roofIdentPair".} ; + } + } + + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + + #my $ret = createStringConfig ($hash); + #return $ret if($ret); + } + + InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben + +return; +} + ################################################################ # Attr setupBatteryDev ################################################################ @@ -5692,20 +5686,20 @@ sub _attrRadiationAPI { ## no critic "not used" return "You have to install the required perl module: ".$rmf if($rmf); } - return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett if ($aVal =~ /(ForecastSolar|OpenMeteoDWD|OpenMeteoDWDEnsemble|OpenMeteoWorld)-API/xs) { my ($set, $lat, $lon, $elev) = locCoordinates(); return qq{set attributes 'latitude' and 'longitude' in global device first} if(!$set); - my $tilt = ReadingsVal ($name, 'moduleDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner - return qq{Please complete command "set $name moduleDeclination".} if(!$tilt); + my $tilt = ReadingsVal ($name, 'setupStringDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringDeclination".} if(!$tilt); - my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner - return qq{Please complete command "set $name moduleAzimuth".} if(!$dir); + my $dir = ReadingsVal ($name, 'setupStringAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringAzimuth".} if(!$dir); } - $data{$type}{$name}{current}{allStringsFullfilled} = 0; # Stringkonfiguration neu prüfen lassen + $data{$type}{$name}{current}{allStringsFullfilled} = 0; # Stringkonfiguration neu prüfen lassen } readingsDelete ($hash, 'nextRadiationAPICall'); @@ -6059,6 +6053,40 @@ sub deleteOldBckpFiles { return; } +################################################################ +# Consumer Daten aus History löschen +################################################################ +sub delConsumerFromMem { + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $type = $paref->{type}; + my $c = $paref->{c}; + + my $calias = ConsumerVal ($hash, $c, 'alias', ''); + + for my $d (1..31) { + $d = sprintf("%02d", $d); + delete $data{$type}{$name}{pvhist}{$d}{99}{"csme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"cyclescsm${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"hourscsme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"avgcycmntscsm${c}"}; + + for my $i (1..24) { + $i = sprintf("%02d", $i); + delete $data{$type}{$name}{pvhist}{$d}{$i}{"csmt${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{$i}{"csme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{$i}{"minutescsm${c}"}; + } + } + + delete $data{$type}{$name}{consumers}{$c}; + + Log3 ($name, 3, qq{$name - Consumer "$c - $calias" deleted from memory}); + +return; +} + ################################################################ # Daten in File wegschreiben ################################################################ @@ -6457,6 +6485,24 @@ sub centralTask { CommandAttr (undef, "$name setupStringPeak $val5"); readingsDelete ($hash, 'modulePeakString'); } + + my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # 16.06.2024 + if ($dir) { + readingsSingleUpdate ($hash, 'setupStringAzimuth', $dir, 0); + readingsDelete ($hash, 'moduleAzimuth'); + } + + my $dec = ReadingsVal ($name, 'moduleDeclination', ''); # 16.06.2024 + if ($dec) { + readingsSingleUpdate ($hash, 'setupStringDeclination', $dec, 0); + readingsDelete ($hash, 'moduleDeclination'); + } + + my $val6 = ReadingsVal ($name, 'moduleRoofTops', ''); # 16.06.2024 + if ($val6) { + CommandAttr (undef, "$name setupRoofTops $val6"); + readingsDelete ($hash, 'moduleRoofTops'); + } ########################################################################################################################## setModel ($hash); # Model setzen @@ -6595,8 +6641,8 @@ sub createStringConfig { ## no critic "not used" } if (isSolCastUsed ($hash)) { # SolCast-API Strahlungsquelle - my $mrt = ReadingsVal ($name, 'moduleRoofTops', ''); # RoofTop Konfiguration -> Zuordnung - return qq{Please complete command "set $name moduleRoofTops".} if(!$mrt); + my $mrt = AttrVal ($name, 'setupRoofTops', ''); # RoofTop Konfiguration -> Zuordnung + return qq{Please complete command "attr $name setupRoofTops".} if(!$mrt); my ($ad,$hd) = parseParams ($mrt); @@ -6605,7 +6651,7 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$is}{pk} = $pk; } else { - return qq{Check "moduleRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"}; } } } @@ -6617,8 +6663,8 @@ sub createStringConfig { ## no critic "not used" } } elsif (!isVictronKiUsed ($hash)) { - my $tilt = ReadingsVal ($name, 'moduleDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner - return qq{Please complete command "set $name moduleDeclination".} if(!$tilt); + my $tilt = ReadingsVal ($name, 'setupStringDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringDeclination".} if(!$tilt); my ($at,$ht) = parseParams ($tilt); @@ -6627,15 +6673,15 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$key}{tilt} = $value; } else { - return qq{Check "moduleDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupStringDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; } } - my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner - return qq{Please complete command "set $name moduleAzimuth".} if(!$dir); + my $dir = ReadingsVal ($name, 'setupStringAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringAzimuth".} if(!$dir); my ($ad,$hd) = parseParams ($dir); - my $iwrong = qq{Please check the input of set "moduleAzimuth". It seems to be wrong.}; + my $iwrong = qq{Please check the input of set "setupStringAzimuth". It seems to be wrong.}; while (my ($key, $value) = each %$hd) { if (grep /^$key$/, @istrings) { @@ -6643,15 +6689,15 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$key}{azimut} = _ident2azimuth ($value) // return $iwrong; } else { - return qq{Check "moduleAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupStringAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; } } } - if(!keys %{$data{$type}{$name}{strings}}) { + if (!keys %{$data{$type}{$name}{strings}}) { return qq{The string configuration seems to be incomplete. \n}. - qq{Please check the settings of setupInverterStrings, setupStringPeak, moduleAzimuth, moduleDeclination }. - qq{and/or moduleRoofTops if SolCast-API is used.}; + qq{Please check the settings of setupInverterStrings, setupStringPeak, setupStringAzimuth, setupStringDeclination }. + qq{and/or setupRoofTops if SolCast-API is used.}; } my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in setupInverterStrings enthalten sind als eigentlich verwendet @@ -11594,17 +11640,28 @@ sub _checkSetupNotComplete { if ($val3) { CommandAttr (undef, "$name setupInverterStrings $val3"); } + + 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); + } + ########################################################################################## - my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig - my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.) - my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage - my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device - my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device - my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak - my $maz = ReadingsVal ($name, 'moduleAzimuth', undef); # Modulausrichtung Konfig (Azimut) - my $mdec = ReadingsVal ($name, 'moduleDeclination', undef); # Modul Neigungswinkel Konfig - my $mrt = ReadingsVal ($name, 'moduleRoofTops', undef); # RoofTop Konfiguration (SolCast API) + my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig + my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.) + my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage + my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device + my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device + my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak + my $maz = ReadingsVal ($name, 'setupStringAzimuth', undef); # Modulausrichtung Konfig (Azimut) + my $mdec = ReadingsVal ($name, 'setupStringDeclination', undef); # Modul Neigungswinkel Konfig + my $mrt = AttrVal ($name, 'setupRoofTops', undef); # RoofTop Konfiguration (SolCast API) my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt @@ -14828,7 +14885,16 @@ sub listDataPool { my $sub = sub { my $day = shift; + + #for my $dh (keys %{$h->{$day}}) { + # if (!isNumeric ($dh)) { + # delete $data{$type}{$name}{pvhist}{$day}{$dh}; + # Log3 ($name, 2, qq{$name - INFO - invalid key "$day -> $dh" was deleted from pvHistory storage}); + # } + #} + my $ret; + for my $key (sort {$a<=>$b} keys %{$h->{$day}}) { my $pvrl = HistoryVal ($hash, $day, $key, 'pvrl', '-'); my $pvrlvd = HistoryVal ($hash, $day, $key, 'pvrlvd', '-'); @@ -14988,7 +15054,7 @@ sub listDataPool { } } - for my $idx (sort{$a<=>$b} keys %{$h}) { + for my $idx (sort keys %{$h}) { next if($par && $idx ne $par); $sq .= $idx." => ".$sub->($idx)."\n"; } @@ -15637,12 +15703,12 @@ sub checkPlantConfig { $result->{'Rooftop Settings'}{note} = ''; $result->{'Rooftop Settings'}{fault} = 0; - my $rft = ReadingsVal ($name, 'moduleRoofTops', ''); + my $rft = AttrVal ($name, 'setupRoofTops', ''); if (!$rft) { $result->{'Rooftop Settings'}{state} = $nok; $result->{'Rooftop Settings'}{result} .= qq{No RoofTops are defined
}; - $result->{'Rooftop Settings'}{note} .= qq{Set your Rooftops with "set $name moduleRoofTops" command.
}; + $result->{'Rooftop Settings'}{note} .= qq{Set your Rooftops with "attr $name setupRoofTops".
}; $result->{'Rooftop Settings'}{fault} = 1; $result->{'Roof Ident Pair Settings'}{state} = $nok; @@ -17966,7 +18032,7 @@ return $def; # # $strg: - Name des Strings aus setupStringPeak # $key: peak - Peakleistung aus setupStringPeak -# tilt - Neigungswinkel der Module aus moduleDeclination +# tilt - Neigungswinkel der Module aus setupStringDeclination # dir - Ausrichtung der Module als Azimut-Bezeichner (N,NE,E,SE,S,SW,W,NW) # azimut - Ausrichtung der Module als Azimut Angabe -180 .. 0 .. 180 # @@ -18251,17 +18317,17 @@ to ensure that the system configuration is correct.
@@ -18408,8 +18474,8 @@ to ensure that the system configuration is correct.

-
- - @@ -18663,7 +18710,8 @@ to ensure that the system configuration is correct. To delete the planning data of only one consumer, use: The module carries out an automatic rescheduling of the consumer circuit. - consumerMaster deletes the data of all registered consumers from the memory + consumerMaster deletes the current and historical data of all registered consumers from the memory + The defined consumer attributes remain and the data is collected again. To delete the data of only one consumer use: consumption deletes the stored consumption values of the house @@ -18684,7 +18732,6 @@ to ensure that the system configuration is correct. To delete a specific hour of a historical day: - moduleRoofTopSet deletes the SolCast API Rooftops roofIdentPair deletes all saved SolCast API Rooftop ID / API Key pairs. To delete a specific pair, specify its key <pk>: @@ -18706,7 +18753,7 @@ to ensure that the system configuration is correct. one after the other. In that case, a new name for "<pk>" is to be used in each case.

- The key <pk> is assigned in the setter moduleRoofTops to the + The key <pk> is assigned in the atribute setupRoofTops to the Rooftops (=Strings) to be retrieved.

@@ -20429,6 +20476,23 @@ to ensure that the system configuration is correct.
+ + +
  • setupRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
    + (only when using Model SolCastAPI)

    + + The string "StringnameX" is assigned to a key <pk>. The key <pk> was created with the setter + roofIdentPair. This is used to specify the rooftop ID and API key to + be used in the SolCast API.
    + The StringnameX is a key value of the attribute setupInverterStrings. +

    + +
      + Example:
      + attr <name> setupRoofTops eastroof=p1 southgarage=p2 S3=p3
      +
    +
  • +
  • setupStringPeak <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]

    @@ -20514,17 +20578,17 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      - - - - - - - - - - - + + + + + + + + + + +
      ctrlWeatherDevX DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert
      setupRadiationAPI DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten
      setupInverterDev Device welches PV Leistungsdaten liefert
      setupMeterDev Device welches Netz I/O-Daten liefert
      setupBatteryDev Device welches Batterie Leistungsdaten liefert (sofern vorhanden)
      setupInverterStrings Bezeichner der vorhandenen Anlagenstrings
      moduleAzimuth Ausrichtung (Azimut) der Anlagenstrings
      setupStringPeak die DC-Peakleistung der Anlagenstrings
      roofIdentPair die Identifikationsdaten (bei Nutzung der SolCast API)
      moduleRoofTops die Rooftop Parameter (bei Nutzung der SolCast API)
      moduleDeclination die Neigungswinkel der der Anlagenmodule
      ctrlWeatherDevX DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert
      setupRadiationAPI DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten
      setupInverterDev Device welches PV Leistungsdaten liefert
      setupMeterDev Device welches Netz I/O-Daten liefert
      setupBatteryDev Device welches Batterie Leistungsdaten liefert (sofern vorhanden)
      setupInverterStrings Bezeichner der vorhandenen Anlagenstrings
      setupStringAzimuth Ausrichtung (Azimut) der Anlagenstrings
      setupStringPeak die DC-Peakleistung der Anlagenstrings
      roofIdentPair die Identifikationsdaten (bei Nutzung der SolCast API)
      setupRoofTops die Rooftop Parameter (bei Nutzung der SolCast API)
      setupStringDeclination die Neigungswinkel der Anlagenmodule

    @@ -20671,8 +20735,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      - -
    • moduleAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      + +
    • setupStringAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      (nur Model DWD, ForecastSolarAPI)

      Ausrichtung <dir> der Solarmodule im String "StringnameX". Der Stringname ist ein Schlüsselwert des @@ -20703,15 +20767,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
        Beispiel:
        - set <name> moduleAzimuth Ostdach=-90 Südgarage=S S3=NW
        + set <name> setupStringAzimuth Ostdach=-90 Südgarage=S S3=NW

      - -
    • moduleDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
      + +
    • setupStringDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
      (nur Model DWD, ForecastSolarAPI)

      Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Attributs setupInverterStrings.
      @@ -20720,26 +20784,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
        Beispiel:
        - set <name> moduleDeclination Ostdach=40 Südgarage=60 S3=30
        -
      -
    • -
    -
    - -
      - -
    • moduleRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
      - (nur bei Verwendung Model SolCastAPI)

      - - Es erfolgt die Zuordnung des Strings "StringnameX" zu einem Schlüssel <pk>. Der Schlüssel <pk> wurde mit dem - Setter roofIdentPair angelegt. Damit wird bei Abruf des Rooftops (=String) - in der SolCast API die zu verwendende Rooftop-ID sowie der zu verwendende API-Key festgelegt.
      - Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings. -

      - -
        - Beispiel:
        - set <name> moduleRoofTops Ostdach=p1 Südgarage=p2 S3=p3
        + set <name> setupStringDeclination Ostdach=40 Südgarage=60 S3=30
    @@ -20934,7 +20979,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man:
      set <name> reset consumerPlanning <Verbrauchernummer>
    Das Modul führt eine automatische Neuplanung der Verbraucherschaltung durch. - consumerMaster löscht die Daten aller registrierten Verbraucher aus dem Speicher + consumerMaster löscht die aktuellen und historischen Daten aller registrierten Verbraucher aus dem Speicher + Die definierten Consumer Attribute bleiben bestehen und die Daten werden neu gesammelt. Um die Daten nur eines Verbrauchers zu löschen verwendet man:
      set <name> reset consumerMaster <Verbrauchernummer>
    consumption löscht die gespeicherten Verbrauchswerte des Hauses @@ -20955,7 +21001,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      set <name> reset pvHistory <Tag> (z.B. set <name> reset pvHistory 08)
    Um eine bestimmte Stunde eines historischer Tages zu löschen:
      set <name> reset pvHistory <Tag> <Stunde> (z.B. set <name> reset pvHistory 08 10)
    - moduleRoofTopSet löscht die SolCast API Rooftops roofIdentPair löscht alle gespeicherten SolCast API Rooftop-ID / API-Key Paare Um ein bestimmtes Paar zu löschen ist dessen Schlüssel <pk> anzugeben:
      set <name> reset roofIdentPair <pk> (z.B. set <name> reset roofIdentPair p1)
    @@ -20976,8 +21021,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Paare nacheinander angelegt werden. In dem Fall ist jeweils ein neuer Name für "<pk>" zu verwenden.

    - Der Schlüssel <pk> wird im Setter moduleRoofTops der abzurufenden - Rooftops (=Strings) zugeordnet. + Der Schlüssel <pk> wird im Attribut setupRoofTops dem abzurufenden + Rooftop (=String) zugeordnet.

      @@ -22702,6 +22747,23 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.

  • + + +
  • setupRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
    + (nur bei Verwendung Model SolCastAPI)

    + + Es erfolgt die Zuordnung des Strings "StringnameX" zu einem Schlüssel <pk>. Der Schlüssel <pk> wurde mit dem + Setter roofIdentPair angelegt. Damit wird bei Abruf des Rooftops (=String) + in der SolCast API die zu verwendende Rooftop-ID sowie der zu verwendende API-Key festgelegt.
    + Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings. +

    + +
      + Beispiel:
      + attr <name> setupRoofTops Ostdach=p1 Südgarage=p2 S3=p3
      +
    +
  • +
  • setupStringPeak <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]

    diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 7f0f4825d..c79d69c7c 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -157,6 +157,10 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.29.0" => "16.06.2024 _setreset: improve reset consumerMaster ". + "tranformed setter moduleAzimuth to setupStringAzimuth ". + "tranformed setter moduleDeclination to setupStringDeclination ". + "tranformed setter moduleRoofTops to setupRoofTops ", "1.28.0" => "15.06.2024 new consumer key exconfc, Forum: https://forum.fhem.de/index.php?msg=1315111 ", "1.27.0" => "12.06.2024 __VictronVRM_ApiResponseLogin: check token not empty ". "transformed setter modulePeakString to attr setupStringPeak ", @@ -501,9 +505,8 @@ my @fs = qw( ftui_forecast.css ); # Anlagenkonfiguration: maßgebliche Readings my @rconfigs = qw( pvCorrectionFactor_Auto - moduleAzimuth - moduleDeclination - moduleRoofTops + setupStringAzimuth + setupStringDeclination batteryTrigger powerTrigger energyH4Trigger @@ -530,6 +533,7 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight setupMeterDev setupBatteryDev setupInverterDev setupInverterStrings setupRadiationAPI setupStringPeak + setupRoofTops ); for my $cinit (1..$maxconsumer) { @@ -571,10 +575,8 @@ my %hset = ( # Ha pvCorrectionFactor_21 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_Auto => { fn => \&_setpvCorrectionFactorAuto }, reset => { fn => \&_setreset }, - roofIdentPair => { fn => \&_setroofIdentPair }, - moduleRoofTops => { fn => \&_setmoduleRoofTops }, - moduleDeclination => { fn => \&_setmoduleDeclination }, - moduleAzimuth => { fn => \&_setmoduleAzimuth }, + setupStringDeclination => { fn => \&_setstringDeclination }, + setupStringAzimuth => { fn => \&_setstringAzimuth }, operatingMemory => { fn => \&_setoperatingMemory }, vrmCredentials => { fn => \&_setVictronCredentials }, aiDecTree => { fn => \&_setaiDecTree }, @@ -612,6 +614,7 @@ my %hattr = ( # H setupInverterStrings => { fn => \&_attrInverterStrings }, setupRadiationAPI => { fn => \&_attrRadiationAPI }, setupStringPeak => { fn => \&_attrStringPeak }, + setupRoofTops => { fn => \&_attrRoofTops }, ); my %htr = ( # Hash even/odd für @@ -666,14 +669,14 @@ my %hqtxt = ( DE => qq{Bitte geben sie alle von Ihnen verwendeten Stringnamen mit "attr LINK setupInverterStrings" an} }, mps => { EN => qq{Please enter the DC peak power of each string with "attr LINK setupStringPeak"}, DE => qq{Bitte geben sie die DC Spitzenleistung von jedem String mit "attr LINK setupStringPeak" an} }, - mdr => { EN => qq{Please specify the module direction with "set LINK moduleAzimuth"}, - DE => qq{Bitte geben sie die Modulausrichtung mit "set LINK moduleAzimuth" an} }, - mta => { EN => qq{Please specify the module tilt angle with "set LINK moduleDeclination"}, - DE => qq{Bitte geben sie den Modulneigungswinkel mit "set LINK moduleDeclination" an} }, + mdr => { EN => qq{Please specify the module direction with "set LINK setupStringAzimuth"}, + DE => qq{Bitte geben sie die Modulausrichtung mit "set LINK setupStringAzimuth" an} }, + mta => { EN => qq{Please specify the module tilt angle with "set LINK setupStringDeclination"}, + DE => qq{Bitte geben sie den Modulneigungswinkel mit "set LINK setupStringDeclination" an} }, rip => { EN => qq{Please specify at least one combination Rooftop-ID/SolCast-API with "set LINK roofIdentPair"}, DE => qq{Bitte geben Sie mindestens eine Kombination Rooftop-ID/SolCast-API mit "set LINK roofIdentPair" an} }, - mrt => { EN => qq{Please set the assignment String / Rooftop identification with "set LINK moduleRoofTops"}, - DE => qq{Bitte setzen sie die Zuordnung String / Rooftop Identifikation mit "set LINK moduleRoofTops"} }, + mrt => { EN => qq{Please set the assignment String / Rooftop identification with "attr LINK setupRoofTops"}, + DE => qq{Bitte setzen sie die Zuordnung String / Rooftop Identifikation mit "attr LINK setupRoofTops"} }, coord => { EN => qq{Please set attributes 'latitude' and 'longitude' in global device}, DE => qq{Bitte setzen sie die Attribute 'latitude' und 'longitude' im global Device} }, cnsm => { EN => qq{Consumer}, @@ -1223,6 +1226,7 @@ sub Initialize { "setupInverterDev:textField-long ". "setupInverterStrings ". "setupMeterDev:textField-long ". + "setupRoofTops ". "setupBatteryDev:textField-long ". "setupRadiationAPI ". "setupStringPeak ". @@ -1423,7 +1427,6 @@ sub Set { consumerPlanning consumption energyH4TriggerSet - moduleRoofTopSet powerTriggerSet pvCorrection roofIdentPair @@ -1485,13 +1488,12 @@ sub Set { ## API spezifische Setter ########################### if (isSolCastUsed ($hash)) { - $setlist .= "moduleRoofTops ". - "roofIdentPair " + $setlist .= "roofIdentPair " ; } elsif (isForecastSolarUsed ($hash)) { - $setlist .= "moduleAzimuth ". - "moduleDeclination " + $setlist .= "setupStringAzimuth ". + "setupStringDeclination " ; } elsif (isVictronKiUsed ($hash)) { @@ -1499,8 +1501,8 @@ sub Set { ; } else { - $setlist .= "moduleAzimuth ". - "moduleDeclination " + $setlist .= "setupStringAzimuth ". + "setupStringDeclination " ; } @@ -1711,42 +1713,6 @@ sub _setVictronCredentials { ## no critic "not used" return $msg; } -################################################################ -# Setter moduleRoofTops -################################################################ -sub _setmoduleRoofTops { ## no critic "not used" - my $paref = shift; - my $hash = $paref->{hash}; - my $name = $paref->{name}; - my $arg = $paref->{arg} // return qq{no module RoofTop was provided}; - - my ($a,$h) = parseParams ($arg); - - if (!keys %$h) { - return qq{The provided module RoofTop has wrong format}; - } - - while (my ($is, $pk) = each %$h) { - my $rtid = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'rtid', ''); - my $apikey = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'apikey', ''); - - if (!$rtid || !$apikey) { - return qq{The roofIdentPair "$pk" of String "$is" has no Rooftop-ID and/or SolCast-API key assigned ! \n}. - qq{Set the roofIdentPair "$pk" previously with "set $name roofIdentPair".} ; - } - } - - readingsSingleUpdate ($hash, "moduleRoofTops", $arg, 1); - writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben - - return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett - - my $ret = createStringConfig ($hash); - return $ret if($ret); - -return; -} - ################################################################ # Setter operationMode ################################################################ @@ -1806,9 +1772,9 @@ return; } ################################################################ -# Setter moduleDeclination +# Setter setupStringDeclination ################################################################ -sub _setmoduleDeclination { ## no critic "not used" +sub _setstringDeclination { ## no critic "not used" my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; @@ -1828,8 +1794,8 @@ sub _setmoduleDeclination { ## no critic "not used" } } - readingsSingleUpdate ($hash, 'moduleDeclination', $arg, 1); - writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben + readingsSingleUpdate ($hash, 'setupStringDeclination', $arg, 1); + writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett @@ -1840,13 +1806,13 @@ return; } ################################################################ -# Setter moduleAzimuth +# Setter setupStringAzimuth # # Angabe entweder als Azimut-Bezeichner oder direkte # Azimut Angabe -180 ...0...180 # ################################################################ -sub _setmoduleAzimuth { ## no critic "not used" +sub _setstringAzimuth { ## no critic "not used" my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; @@ -1866,7 +1832,7 @@ sub _setmoduleAzimuth { ## no critic "not used" } } - readingsSingleUpdate ($hash, 'moduleAzimuth', $arg, 1); + readingsSingleUpdate ($hash, 'setupStringAzimuth', $arg, 1); writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett @@ -2019,8 +1985,7 @@ sub _setreset { ## no critic "not used" my $hash = $paref->{hash}; my $name = $paref->{name}; my $prop = $paref->{prop} // return qq{no source specified for reset}; - - my $type = $hash->{TYPE}; + my $type = $paref->{type}; if ($prop eq 'pvHistory') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? @@ -2178,12 +2143,6 @@ sub _setreset { ## no critic "not used" return; } - if ($prop eq 'moduleRoofTopSet') { - readingsDelete ($hash, "moduleRoofTops"); - writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); - return; - } - readingsDelete ($hash, $prop); if ($prop eq 'roofIdentPair') { @@ -2218,22 +2177,24 @@ sub _setreset { ## no critic "not used" } if ($prop eq 'consumerMaster') { # Verbraucherhash löschen - my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben + my $c = $paref->{prop1} // ''; # bestimmten Verbraucher setzen falls angegeben if ($c) { - my $calias = ConsumerVal ($hash, $c, "alias", ""); - delete $data{$type}{$name}{consumers}{$c}; - Log3($name, 3, qq{$name - Consumer "$calias" deleted from memory}); + $paref->{c} = $c; + delConsumerFromMem ($paref); # spezifischen Consumer aus History löschen } else { - for my $cs (keys %{$data{$type}{$name}{consumers}}) { - my $calias = ConsumerVal ($hash, $cs, "alias", ""); - delete $data{$type}{$name}{consumers}{$cs}; - Log3($name, 3, qq{$name - Consumer "$calias" deleted from memory}); + for my $c (keys %{$data{$type}{$name}{consumers}}) { + $paref->{c} = $c; + delConsumerFromMem ($paref); # alle Consumer aus History löschen } } - - writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + delete $paref->{c}; + $data{$type}{$name}{current}{consumerCollected} = 0; # Consumer neu sammeln + + writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + centralTask ($hash, 0); } createAssociatedWith ($hash); @@ -2604,7 +2565,7 @@ sub __solCast_ApiRequest { my $string; ($string, $allstrings) = split ",", $allstrings, 2; - my $rft = ReadingsVal ($name, "moduleRoofTops", ""); + my $rft = AttrVal ($name, 'setupRoofTops', ''); my ($a,$h) = parseParams ($rft); my $pk = $h->{$string} // q{}; @@ -5295,17 +5256,11 @@ sub _attrconsumer { ## no critic "not used" else { my $day = strftime "%d", localtime(time); # aktueller Tag (range 01 to 31) my ($c) = $aName =~ /consumer([0-9]+)/xs; + + $paref->{c} = $c; + delConsumerFromMem ($paref); # Consumerdaten aus History löschen deleteReadingspec ($hash, "consumer${c}.*"); - - for my $i (1..24) { # Consumer aus History löschen - delete $data{$type}{$name}{pvhist}{$day}{sprintf("%02d",$i)}{"csmt${c}"}; - delete $data{$type}{$name}{pvhist}{$day}{sprintf("%02d",$i)}{"csme${c}"}; - } - - delete $data{$type}{$name}{pvhist}{$day}{99}{"csmt${c}"}; - delete $data{$type}{$name}{pvhist}{$day}{99}{"csme${c}"}; - delete $data{$type}{$name}{consumers}{$c}; # Consumer Hash Verbraucher löschen } writeCacheToFile ($hash, 'consumers', $csmcache.$name); # Cache File Consumer schreiben @@ -5569,6 +5524,45 @@ sub _attrStringPeak { ## no critic "not used" return; } +################################################################ +# Attr setupRoofTops +################################################################ +sub _attrRoofTops { ## no critic "not used" + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $aVal = $paref->{aVal}; + + return if(!$init_done); + + if ($paref->{cmd} eq 'set') { + my ($a,$h) = parseParams ($aVal); + + if (!keys %$h) { + return qq{The attribute content has wrong format}; + } + + while (my ($is, $pk) = each %$h) { + my $rtid = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'rtid', ''); + my $apikey = SolCastAPIVal ($hash, '?IdPair', '?'.$pk, 'apikey', ''); + + if (!$rtid || !$apikey) { + return qq{The roofIdentPair "$pk" of String "$is" has no Rooftop-ID and/or SolCast-API key assigned! \n}. + qq{Set the roofIdentPair "$pk" previously with "set $name roofIdentPair".} ; + } + } + + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + + #my $ret = createStringConfig ($hash); + #return $ret if($ret); + } + + InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben + +return; +} + ################################################################ # Attr setupBatteryDev ################################################################ @@ -5692,20 +5686,20 @@ sub _attrRadiationAPI { ## no critic "not used" return "You have to install the required perl module: ".$rmf if($rmf); } - return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett + return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett if ($aVal =~ /(ForecastSolar|OpenMeteoDWD|OpenMeteoDWDEnsemble|OpenMeteoWorld)-API/xs) { my ($set, $lat, $lon, $elev) = locCoordinates(); return qq{set attributes 'latitude' and 'longitude' in global device first} if(!$set); - my $tilt = ReadingsVal ($name, 'moduleDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner - return qq{Please complete command "set $name moduleDeclination".} if(!$tilt); + my $tilt = ReadingsVal ($name, 'setupStringDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringDeclination".} if(!$tilt); - my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner - return qq{Please complete command "set $name moduleAzimuth".} if(!$dir); + my $dir = ReadingsVal ($name, 'setupStringAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringAzimuth".} if(!$dir); } - $data{$type}{$name}{current}{allStringsFullfilled} = 0; # Stringkonfiguration neu prüfen lassen + $data{$type}{$name}{current}{allStringsFullfilled} = 0; # Stringkonfiguration neu prüfen lassen } readingsDelete ($hash, 'nextRadiationAPICall'); @@ -6059,6 +6053,40 @@ sub deleteOldBckpFiles { return; } +################################################################ +# Consumer Daten aus History löschen +################################################################ +sub delConsumerFromMem { + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $type = $paref->{type}; + my $c = $paref->{c}; + + my $calias = ConsumerVal ($hash, $c, 'alias', ''); + + for my $d (1..31) { + $d = sprintf("%02d", $d); + delete $data{$type}{$name}{pvhist}{$d}{99}{"csme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"cyclescsm${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"hourscsme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{99}{"avgcycmntscsm${c}"}; + + for my $i (1..24) { + $i = sprintf("%02d", $i); + delete $data{$type}{$name}{pvhist}{$d}{$i}{"csmt${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{$i}{"csme${c}"}; + delete $data{$type}{$name}{pvhist}{$d}{$i}{"minutescsm${c}"}; + } + } + + delete $data{$type}{$name}{consumers}{$c}; + + Log3 ($name, 3, qq{$name - Consumer "$c - $calias" deleted from memory}); + +return; +} + ################################################################ # Daten in File wegschreiben ################################################################ @@ -6457,6 +6485,24 @@ sub centralTask { CommandAttr (undef, "$name setupStringPeak $val5"); readingsDelete ($hash, 'modulePeakString'); } + + my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # 16.06.2024 + if ($dir) { + readingsSingleUpdate ($hash, 'setupStringAzimuth', $dir, 0); + readingsDelete ($hash, 'moduleAzimuth'); + } + + my $dec = ReadingsVal ($name, 'moduleDeclination', ''); # 16.06.2024 + if ($dec) { + readingsSingleUpdate ($hash, 'setupStringDeclination', $dec, 0); + readingsDelete ($hash, 'moduleDeclination'); + } + + my $val6 = ReadingsVal ($name, 'moduleRoofTops', ''); # 16.06.2024 + if ($val6) { + CommandAttr (undef, "$name setupRoofTops $val6"); + readingsDelete ($hash, 'moduleRoofTops'); + } ########################################################################################################################## setModel ($hash); # Model setzen @@ -6595,8 +6641,8 @@ sub createStringConfig { ## no critic "not used" } if (isSolCastUsed ($hash)) { # SolCast-API Strahlungsquelle - my $mrt = ReadingsVal ($name, 'moduleRoofTops', ''); # RoofTop Konfiguration -> Zuordnung - return qq{Please complete command "set $name moduleRoofTops".} if(!$mrt); + my $mrt = AttrVal ($name, 'setupRoofTops', ''); # RoofTop Konfiguration -> Zuordnung + return qq{Please complete command "attr $name setupRoofTops".} if(!$mrt); my ($ad,$hd) = parseParams ($mrt); @@ -6605,7 +6651,7 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$is}{pk} = $pk; } else { - return qq{Check "moduleRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"}; } } } @@ -6617,8 +6663,8 @@ sub createStringConfig { ## no critic "not used" } } elsif (!isVictronKiUsed ($hash)) { - my $tilt = ReadingsVal ($name, 'moduleDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner - return qq{Please complete command "set $name moduleDeclination".} if(!$tilt); + my $tilt = ReadingsVal ($name, 'setupStringDeclination', ''); # Modul Neigungswinkel für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringDeclination".} if(!$tilt); my ($at,$ht) = parseParams ($tilt); @@ -6627,15 +6673,15 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$key}{tilt} = $value; } else { - return qq{Check "moduleDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupStringDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; } } - my $dir = ReadingsVal ($name, 'moduleAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner - return qq{Please complete command "set $name moduleAzimuth".} if(!$dir); + my $dir = ReadingsVal ($name, 'setupStringAzimuth', ''); # Modul Ausrichtung für jeden Stringbezeichner + return qq{Please complete command "set $name setupStringAzimuth".} if(!$dir); my ($ad,$hd) = parseParams ($dir); - my $iwrong = qq{Please check the input of set "moduleAzimuth". It seems to be wrong.}; + my $iwrong = qq{Please check the input of set "setupStringAzimuth". It seems to be wrong.}; while (my ($key, $value) = each %$hd) { if (grep /^$key$/, @istrings) { @@ -6643,15 +6689,15 @@ sub createStringConfig { ## no critic "not used" $data{$type}{$name}{strings}{$key}{azimut} = _ident2azimuth ($value) // return $iwrong; } else { - return qq{Check "moduleAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; + return qq{Check "setupStringAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"}; } } } - if(!keys %{$data{$type}{$name}{strings}}) { + if (!keys %{$data{$type}{$name}{strings}}) { return qq{The string configuration seems to be incomplete. \n}. - qq{Please check the settings of setupInverterStrings, setupStringPeak, moduleAzimuth, moduleDeclination }. - qq{and/or moduleRoofTops if SolCast-API is used.}; + qq{Please check the settings of setupInverterStrings, setupStringPeak, setupStringAzimuth, setupStringDeclination }. + qq{and/or setupRoofTops if SolCast-API is used.}; } my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in setupInverterStrings enthalten sind als eigentlich verwendet @@ -11594,17 +11640,28 @@ sub _checkSetupNotComplete { if ($val3) { CommandAttr (undef, "$name setupInverterStrings $val3"); } + + 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); + } + ########################################################################################## - my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig - my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.) - my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage - my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device - my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device - my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak - my $maz = ReadingsVal ($name, 'moduleAzimuth', undef); # Modulausrichtung Konfig (Azimut) - my $mdec = ReadingsVal ($name, 'moduleDeclination', undef); # Modul Neigungswinkel Konfig - my $mrt = ReadingsVal ($name, 'moduleRoofTops', undef); # RoofTop Konfiguration (SolCast API) + my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig + my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.) + my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage + my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device + my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device + my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak + my $maz = ReadingsVal ($name, 'setupStringAzimuth', undef); # Modulausrichtung Konfig (Azimut) + my $mdec = ReadingsVal ($name, 'setupStringDeclination', undef); # Modul Neigungswinkel Konfig + my $mrt = AttrVal ($name, 'setupRoofTops', undef); # RoofTop Konfiguration (SolCast API) my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt @@ -14828,7 +14885,16 @@ sub listDataPool { my $sub = sub { my $day = shift; + + #for my $dh (keys %{$h->{$day}}) { + # if (!isNumeric ($dh)) { + # delete $data{$type}{$name}{pvhist}{$day}{$dh}; + # Log3 ($name, 2, qq{$name - INFO - invalid key "$day -> $dh" was deleted from pvHistory storage}); + # } + #} + my $ret; + for my $key (sort {$a<=>$b} keys %{$h->{$day}}) { my $pvrl = HistoryVal ($hash, $day, $key, 'pvrl', '-'); my $pvrlvd = HistoryVal ($hash, $day, $key, 'pvrlvd', '-'); @@ -14988,7 +15054,7 @@ sub listDataPool { } } - for my $idx (sort{$a<=>$b} keys %{$h}) { + for my $idx (sort keys %{$h}) { next if($par && $idx ne $par); $sq .= $idx." => ".$sub->($idx)."\n"; } @@ -15637,12 +15703,12 @@ sub checkPlantConfig { $result->{'Rooftop Settings'}{note} = ''; $result->{'Rooftop Settings'}{fault} = 0; - my $rft = ReadingsVal ($name, 'moduleRoofTops', ''); + my $rft = AttrVal ($name, 'setupRoofTops', ''); if (!$rft) { $result->{'Rooftop Settings'}{state} = $nok; $result->{'Rooftop Settings'}{result} .= qq{No RoofTops are defined
    }; - $result->{'Rooftop Settings'}{note} .= qq{Set your Rooftops with "set $name moduleRoofTops" command.
    }; + $result->{'Rooftop Settings'}{note} .= qq{Set your Rooftops with "attr $name setupRoofTops".
    }; $result->{'Rooftop Settings'}{fault} = 1; $result->{'Roof Ident Pair Settings'}{state} = $nok; @@ -17966,7 +18032,7 @@ return $def; # # $strg: - Name des Strings aus setupStringPeak # $key: peak - Peakleistung aus setupStringPeak -# tilt - Neigungswinkel der Module aus moduleDeclination +# tilt - Neigungswinkel der Module aus setupStringDeclination # dir - Ausrichtung der Module als Azimut-Bezeichner (N,NE,E,SE,S,SW,W,NW) # azimut - Ausrichtung der Module als Azimut Angabe -180 .. 0 .. 180 # @@ -18251,17 +18317,17 @@ to ensure that the system configuration is correct.
      - - - - - - - - - - - + + + + + + + + + + +
      ctrlWeatherDevX DWD_OpenData Device which provides meteorological data (e.g. cloud cover)
      setupRadiationAPI DWD_OpenData Device or API for the delivery of radiation data.
      setupInverterDev Device which provides PV performance data
      setupMeterDev Device which supplies network I/O data
      setupBatteryDev Device which provides battery performance data (if available)
      setupInverterStrings Identifier of the existing plant strings
      moduleAzimuth Azimuth of the plant strings
      setupStringPeak the DC peak power of the plant strings
      roofIdentPair the identification data (when using the SolCast API)
      moduleRoofTops the Rooftop parameters (when using the SolCast API)
      moduleDeclination the inclination angles of the plant modules
      ctrlWeatherDevX DWD_OpenData Device which provides meteorological data (e.g. cloud cover)
      setupRadiationAPI DWD_OpenData Device or API for the delivery of radiation data.
      setupInverterDev Device which provides PV performance data
      setupMeterDev Device which supplies network I/O data
      setupBatteryDev Device which provides battery performance data (if available)
      setupInverterStrings Identifier of the existing plant strings
      setupStringAzimuth Azimuth of the plant strings
      setupStringPeak the DC peak power of the plant strings
      roofIdentPair the identification data (when using the SolCast API)
      setupRoofTops the Rooftop parameters (when using the SolCast API)
      setupStringDeclination the angle of inclination of the plant modules

    @@ -18408,8 +18474,8 @@ to ensure that the system configuration is correct.
      - -
    • moduleAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      + +
    • setupStringAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      (only model DWD, ForecastSolarAPI)

      Alignment <dir> of the solar modules in the string "StringnameX". The string name is a key value of the @@ -18440,15 +18506,15 @@ to ensure that the system configuration is correct.
        Example:
        - set <name> moduleAzimuth eastroof=-90 southgarage=S S3=NW
        + set <name> setupStringAzimuth eastroof=-90 southgarage=S S3=NW

      - -
    • moduleDeclination <Stringname1>=<Angle> [<Stringname2>=<Angle> <Stringname3>=<Angle> ...]
      + +
    • setupStringDeclination <Stringname1>=<Angle> [<Stringname2>=<Angle> <Stringname3>=<Angle> ...]
      (only model DWD, ForecastSolarAPI)

      Tilt angle of the solar modules. The string name is a key value of the attribute setupInverterStrings.
      @@ -18457,26 +18523,7 @@ to ensure that the system configuration is correct.
        Example:
        - set <name> moduleDeclination eastroof=40 southgarage=60 S3=30
        -
      -
    • -
    -
    - -
      - -
    • moduleRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
      - (only when using Model SolCastAPI)

      - - The string "StringnameX" is assigned to a key <pk>. The key <pk> was created with the setter - roofIdentPair. This is used to specify the rooftop ID and API key to - be used in the SolCast API.
      - The string nameX is a key value of the attribute setupInverterStrings. -

      - -
        - Example:
        - set <name> moduleRoofTops eastroof=p1 southgarage=p2 S3=p3
        + set <name> setupStringDeclination eastroof=40 southgarage=60 S3=30
    @@ -18663,7 +18710,8 @@ to ensure that the system configuration is correct. To delete the planning data of only one consumer, use:
      set <name> reset consumerPlanning <Consumer number>
    The module carries out an automatic rescheduling of the consumer circuit. - consumerMaster deletes the data of all registered consumers from the memory + consumerMaster deletes the current and historical data of all registered consumers from the memory + The defined consumer attributes remain and the data is collected again. To delete the data of only one consumer use:
      set <name> reset consumerMaster <Consumer number>
    consumption deletes the stored consumption values of the house @@ -18684,7 +18732,6 @@ to ensure that the system configuration is correct.
      set <name> reset pvHistory <Day> (e.g. set <name> reset pvHistory 08)
    To delete a specific hour of a historical day:
      set <name> reset pvHistory <Day> <Hour> (e.g. set <name> reset pvHistory 08 10)
    - moduleRoofTopSet deletes the SolCast API Rooftops roofIdentPair deletes all saved SolCast API Rooftop ID / API Key pairs. To delete a specific pair, specify its key <pk>:
      set <name> reset roofIdentPair <pk> (e.g. set <name> reset roofIdentPair p1)
    @@ -18706,7 +18753,7 @@ to ensure that the system configuration is correct. one after the other. In that case, a new name for "<pk>" is to be used in each case.

    - The key <pk> is assigned in the setter moduleRoofTops to the + The key <pk> is assigned in the atribute setupRoofTops to the Rooftops (=Strings) to be retrieved.

    @@ -20429,6 +20476,23 @@ to ensure that the system configuration is correct.

  • + + +
  • setupRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
    + (only when using Model SolCastAPI)

    + + The string "StringnameX" is assigned to a key <pk>. The key <pk> was created with the setter + roofIdentPair. This is used to specify the rooftop ID and API key to + be used in the SolCast API.
    + The StringnameX is a key value of the attribute setupInverterStrings. +

    + +
      + Example:
      + attr <name> setupRoofTops eastroof=p1 southgarage=p2 S3=p3
      +
    +
  • +
  • setupStringPeak <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]

    @@ -20514,17 +20578,17 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      - - - - - - - - - - - + + + + + + + + + + +
      ctrlWeatherDevX DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert
      setupRadiationAPI DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten
      setupInverterDev Device welches PV Leistungsdaten liefert
      setupMeterDev Device welches Netz I/O-Daten liefert
      setupBatteryDev Device welches Batterie Leistungsdaten liefert (sofern vorhanden)
      setupInverterStrings Bezeichner der vorhandenen Anlagenstrings
      moduleAzimuth Ausrichtung (Azimut) der Anlagenstrings
      setupStringPeak die DC-Peakleistung der Anlagenstrings
      roofIdentPair die Identifikationsdaten (bei Nutzung der SolCast API)
      moduleRoofTops die Rooftop Parameter (bei Nutzung der SolCast API)
      moduleDeclination die Neigungswinkel der der Anlagenmodule
      ctrlWeatherDevX DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert
      setupRadiationAPI DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten
      setupInverterDev Device welches PV Leistungsdaten liefert
      setupMeterDev Device welches Netz I/O-Daten liefert
      setupBatteryDev Device welches Batterie Leistungsdaten liefert (sofern vorhanden)
      setupInverterStrings Bezeichner der vorhandenen Anlagenstrings
      setupStringAzimuth Ausrichtung (Azimut) der Anlagenstrings
      setupStringPeak die DC-Peakleistung der Anlagenstrings
      roofIdentPair die Identifikationsdaten (bei Nutzung der SolCast API)
      setupRoofTops die Rooftop Parameter (bei Nutzung der SolCast API)
      setupStringDeclination die Neigungswinkel der Anlagenmodule

    @@ -20671,8 +20735,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      - -
    • moduleAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      + +
    • setupStringAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
      (nur Model DWD, ForecastSolarAPI)

      Ausrichtung <dir> der Solarmodule im String "StringnameX". Der Stringname ist ein Schlüsselwert des @@ -20703,15 +20767,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
        Beispiel:
        - set <name> moduleAzimuth Ostdach=-90 Südgarage=S S3=NW
        + set <name> setupStringAzimuth Ostdach=-90 Südgarage=S S3=NW

      - -
    • moduleDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
      + +
    • setupStringDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
      (nur Model DWD, ForecastSolarAPI)

      Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Attributs setupInverterStrings.
      @@ -20720,26 +20784,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
        Beispiel:
        - set <name> moduleDeclination Ostdach=40 Südgarage=60 S3=30
        -
      -
    • -
    -
    - -
      - -
    • moduleRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
      - (nur bei Verwendung Model SolCastAPI)

      - - Es erfolgt die Zuordnung des Strings "StringnameX" zu einem Schlüssel <pk>. Der Schlüssel <pk> wurde mit dem - Setter roofIdentPair angelegt. Damit wird bei Abruf des Rooftops (=String) - in der SolCast API die zu verwendende Rooftop-ID sowie der zu verwendende API-Key festgelegt.
      - Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings. -

      - -
        - Beispiel:
        - set <name> moduleRoofTops Ostdach=p1 Südgarage=p2 S3=p3
        + set <name> setupStringDeclination Ostdach=40 Südgarage=60 S3=30
    @@ -20934,7 +20979,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man:
      set <name> reset consumerPlanning <Verbrauchernummer>
    Das Modul führt eine automatische Neuplanung der Verbraucherschaltung durch. - consumerMaster löscht die Daten aller registrierten Verbraucher aus dem Speicher + consumerMaster löscht die aktuellen und historischen Daten aller registrierten Verbraucher aus dem Speicher + Die definierten Consumer Attribute bleiben bestehen und die Daten werden neu gesammelt. Um die Daten nur eines Verbrauchers zu löschen verwendet man:
      set <name> reset consumerMaster <Verbrauchernummer>
    consumption löscht die gespeicherten Verbrauchswerte des Hauses @@ -20955,7 +21001,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
      set <name> reset pvHistory <Tag> (z.B. set <name> reset pvHistory 08)
    Um eine bestimmte Stunde eines historischer Tages zu löschen:
      set <name> reset pvHistory <Tag> <Stunde> (z.B. set <name> reset pvHistory 08 10)
    - moduleRoofTopSet löscht die SolCast API Rooftops roofIdentPair löscht alle gespeicherten SolCast API Rooftop-ID / API-Key Paare Um ein bestimmtes Paar zu löschen ist dessen Schlüssel <pk> anzugeben:
      set <name> reset roofIdentPair <pk> (z.B. set <name> reset roofIdentPair p1)
    @@ -20976,8 +21021,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Paare nacheinander angelegt werden. In dem Fall ist jeweils ein neuer Name für "<pk>" zu verwenden.

    - Der Schlüssel <pk> wird im Setter moduleRoofTops der abzurufenden - Rooftops (=Strings) zugeordnet. + Der Schlüssel <pk> wird im Attribut setupRoofTops dem abzurufenden + Rooftop (=String) zugeordnet.

      @@ -22702,6 +22747,23 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.

  • + + +
  • setupRoofTops <Stringname1>=<pk> [<Stringname2>=<pk> <Stringname3>=<pk> ...]
    + (nur bei Verwendung Model SolCastAPI)

    + + Es erfolgt die Zuordnung des Strings "StringnameX" zu einem Schlüssel <pk>. Der Schlüssel <pk> wurde mit dem + Setter roofIdentPair angelegt. Damit wird bei Abruf des Rooftops (=String) + in der SolCast API die zu verwendende Rooftop-ID sowie der zu verwendende API-Key festgelegt.
    + Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings. +

    + +
      + Beispiel:
      + attr <name> setupRoofTops Ostdach=p1 Südgarage=p2 S3=p3
      +
    +
  • +
  • setupStringPeak <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]