diff --git a/fhem/CHANGED b/fhem/CHANGED
index 369049387..a9a7e03ee 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it
+ - change: 76_SolarForecast: set inverterStrings to attr setupInverterStrings
+ !NOTE! save FHEM config after restart
- bufgix: 72_FRITZBOX: Ändern OffSet DECT Heizkörper Termostate Sommerzeit
- change: 76_SolarForecast: set currentInverterDev to attr setupInverterDev
!NOTE! save FHEM config after restart
diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm
index 63aa37853..00b3c8e87 100644
--- a/fhem/FHEM/76_SolarForecast.pm
+++ b/fhem/FHEM/76_SolarForecast.pm
@@ -157,6 +157,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.25.0" => "05.06.2024 transformed setter inverterStrings to attr setupInverterStrings, calcTodayPVdeviation: fix continuously calc again ",
"1.24.0" => "03.06.2024 transformed setter currentInverterDev to attr setupInverterDev, calcTodayPVdeviation: fix continuously calc ",
"1.23.0" => "02.06.2024 transformed setter currentBatteryDev to attr setupBatteryDev, _transferInverterValues: change output for DEBUG ".
"new key attrInvChangedTs in circular, prepare transformation of currentInverterDev ".
@@ -495,7 +496,6 @@ my @fs = qw( ftui_forecast.css
# Anlagenkonfiguration: maßgebliche Readings
my @rconfigs = qw( pvCorrectionFactor_Auto
currentRadiationAPI
- inverterStrings
moduleAzimuth
modulePeakString
moduleDeclination
@@ -525,7 +525,7 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
- setupMeterDev setupBatteryDev setupInverterDev
+ setupMeterDev setupBatteryDev setupInverterDev setupInverterStrings
);
for my $cinit (1..$maxconsumer) {
@@ -544,7 +544,6 @@ my %hset = ( # Ha
consumerNewPlanning => { fn => \&_setconsumerNewPlanning },
currentRadiationAPI => { fn => \&_setcurrentRadiationAPI },
modulePeakString => { fn => \&_setmodulePeakString },
- inverterStrings => { fn => \&_setinverterStrings },
clientAction => { fn => \&_setclientAction },
energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration },
@@ -608,6 +607,7 @@ my %hattr = ( # H
setupMeterDev => { fn => \&_attrMeterDev },
setupBatteryDev => { fn => \&_attrBatteryDev },
setupInverterDev => { fn => \&_attrInverterDev },
+ setupInverterStrings => { fn => \&_attrInverterStrings },
);
my %htr = ( # Hash even/odd für
@@ -658,8 +658,8 @@ my %hqtxt = (
DE => qq{Bitte geben sie das Wechselrichter Device mit "attr LINK setupInverterDev" an} },
mid => { EN => qq{Please specify the device for energy measurement with "attr LINK setupMeterDev"},
DE => qq{Bitte geben sie das Device zur Energiemessung mit "attr LINK setupMeterDev" an} },
- ist => { EN => qq{Please define all of your used string names with "set LINK inverterStrings"},
- DE => qq{Bitte geben sie alle von Ihnen verwendeten Stringnamen mit "set LINK inverterStrings" an} },
+ ist => { EN => qq{Please define all of your used string names with "attr LINK setupInverterStrings"},
+ 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 "set LINK modulePeakString"},
DE => qq{Bitte geben sie die DC Spitzenleistung von jedem String mit "set LINK modulePeakString" an} },
mdr => { EN => qq{Please specify the module direction with "set LINK moduleAzimuth"},
@@ -1217,6 +1217,7 @@ sub Initialize {
"graphicWeatherColor:colorpicker,RGB ".
"graphicWeatherColorNight:colorpicker,RGB ".
"setupInverterDev:textField-long ".
+ "setupInverterStrings ".
"setupMeterDev:textField-long ".
"setupBatteryDev:textField-long ".
$consumer.
@@ -1417,7 +1418,6 @@ sub Set {
consumption
currentInverterSet
energyH4TriggerSet
- inverterStringSet
moduleRoofTopSet
powerTriggerSet
pvCorrection
@@ -1469,7 +1469,6 @@ sub Set {
"consumerNewPlanning:$coms ".
"currentRadiationAPI:$rdd ".
"energyH4Trigger:textField-long ".
- "inverterStrings ".
"modulePeakString ".
"operatingMemory:backup,save".$rf." ".
"operationMode:active,inactive ".
@@ -1799,40 +1798,6 @@ sub _setmoduleRoofTops { ## no critic "not used"
return;
}
-################################################################
-# Setter inverterStrings
-################################################################
-sub _setinverterStrings { ## no critic "not used"
- my $paref = shift;
- my $hash = $paref->{hash};
- my $name = $paref->{name};
- my $prop = $paref->{prop} // return qq{no inverter strings specified};
-
- if ($prop =~ /\?/xs) {
- return qq{The inverter string designation is wrong. An inverter string name must not contain a '?' character!};
- }
-
- my $type = $hash->{TYPE};
-
- my @istrings = split ",", $prop;
-
- for my $k (keys %{$data{$type}{$name}{solcastapi}}) {
- next if ($k =~ /\?/xs || grep /^$k$/, @istrings);
- delete $data{$type}{$name}{solcastapi}{$k};
- }
-
- readingsSingleUpdate ($hash, 'inverterStrings', $prop, 1);
- writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben
-
- return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett
-
- my $ret = qq{NOTE: After setting or changing "inverterStrings" please check }.
- qq{/ set all module parameter (e.g. moduleDeclination) again ! \n}.
- qq{Use "set $name plantConfiguration check" to validate your Setup.};
-
-return $ret;
-}
-
################################################################
# Setter operationMode
################################################################
@@ -2692,7 +2657,7 @@ sub __getSolCastData {
Log3 ($name, 1, "$name DEBUG> SolCast API Call - possible daily API Calls: $madc");
}
- $paref->{allstrings} = ReadingsVal ($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
$paref->{firstreq} = 1; # 1. Request, V 0.80.18
__solCast_ApiRequest ($paref);
@@ -3097,7 +3062,7 @@ sub __getForecastSolarData {
}
}
- $paref->{allstrings} = ReadingsVal($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
__forecastSolar_ApiRequest ($paref);
@@ -3367,7 +3332,7 @@ sub ___setForeCastAPIcallKeyData {
## Berechnung des optimalen Request Intervalls
################################################
- my $snum = scalar (split ",", ReadingsVal($name, 'inverterStrings', 'Dummy')); # Anzahl der Strings (mindestens ein String als Dummy)
+ my $snum = scalar (split ",", AttrVal ($name, 'setupInverterStrings', 'Dummy')); # Anzahl der Strings (mindestens ein String als Dummy)
my $period = SolCastAPIVal ($hash, '?All', '?All', 'requests_limit_period', 3600); # Requests Limit Periode
my $limit = SolCastAPIVal ($hash, '?All', '?All', 'requests_limit', 12); # Request Limit in Periode
@@ -3825,7 +3790,7 @@ sub __VictronVRM_ApiResponseForecast {
if ($val) {
$val = sprintf "%.0f", $val;
- my $string = ReadingsVal ($name, 'inverterStrings', '?');
+ my $string = AttrVal ($name, 'setupInverterStrings', '?');
$data{$type}{$name}{solcastapi}{$string}{$starttmstr}{pv_estimate50} = $val;
}
@@ -3848,7 +3813,7 @@ sub __VictronVRM_ApiResponseForecast {
if ($val) {
$val = sprintf "%.2f", $val;
- my $string = ReadingsVal ($name, 'inverterStrings', '?');
+ my $string = AttrVal ($name, 'setupInverterStrings', '?');
$data{$type}{$name}{solcastapi}{$string.'_co'}{$starttmstr}{co_estimate} = $val;
}
@@ -3973,7 +3938,7 @@ sub __getopenMeteoData {
debugLog ($paref, 'apiCall', qq{Open-Meteo API Call - the daily API requests -> limited to: $ometmaxreq, done: $donearq});
my $submodel = InternalVal ($hash->{NAME}, 'MODEL', '');
- $paref->{allstrings} = ReadingsVal ($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
$paref->{submodel} = $submodel eq 'OpenMeteoDWDAPI' ? 'DWD ICON Seamless' :
$submodel eq 'OpenMeteoDWDEnsembleAPI' ? 'DWD ICON Seamless Ensemble' :
$submodel eq 'OpenMeteoWorldAPI' ? 'World Best Match' :
@@ -5519,7 +5484,7 @@ sub _attrMeterDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $medev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5541,7 +5506,7 @@ sub _attrMeterDev { ## no critic "not used"
return qq{Incorrect input for key 'feedprice'. Please consider the commandref.} if(scalar(@afp) != 2 && scalar(@afp) != 3);
}
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, "Current_GridConsumption");
readingsDelete ($hash, "Current_GridFeedIn");
delete $data{$type}{$name}{circular}{'99'}{initdayfeedin};
@@ -5581,7 +5546,7 @@ sub _attrInverterDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5595,7 +5560,7 @@ sub _attrInverterDev { ## no critic "not used"
$data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, "Current_PV");
deleteReadingspec ($hash, ".*_PVreal" );
undef @{$data{$type}{$name}{current}{genslidereg}};
@@ -5608,6 +5573,37 @@ sub _attrInverterDev { ## no critic "not used"
return;
}
+################################################################
+# Attr setupInverterStrings
+################################################################
+sub _attrInverterStrings { ## no critic "not used"
+ my $paref = shift;
+ my $hash = $paref->{hash};
+ my $name = $paref->{name};
+ my $aVal = $paref->{aVal};
+ my $aName = $paref->{aName};
+ my $type = $paref->{type};
+
+ return if(!$init_done);
+
+ if ($paref->{cmd} eq 'set') {
+ if ($aVal =~ /\?/xs) {
+ return qq{The inverter string designation is wrong. An inverter string name must not contain a '?' character!};
+ }
+
+ my @istrings = split ",", $aVal;
+
+ for my $k (keys %{$data{$type}{$name}{solcastapi}}) {
+ next if ($k =~ /\?/xs || grep /^$k$/, @istrings);
+ delete $data{$type}{$name}{solcastapi}{$k};
+ }
+ }
+
+ InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben
+
+return;
+}
+
################################################################
# Attr setupBatteryDev
################################################################
@@ -5621,7 +5617,7 @@ sub _attrBatteryDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5638,7 +5634,7 @@ sub _attrBatteryDev { ## no critic "not used"
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
}
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, 'Current_PowerBatIn');
readingsDelete ($hash, 'Current_PowerBatOut');
readingsDelete ($hash, 'Current_BatCharge');
@@ -5674,7 +5670,7 @@ sub _attrWeatherDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
if ($aVal !~ /^OpenMeteo/xs && (!$defs{$aVal} || $defs{$aVal}{TYPE} ne "DWD_OpenData")) {
return qq{The device "$aVal" doesn't exist or has no TYPE 'DWD_OpenData'};
}
@@ -6408,6 +6404,12 @@ sub centralTask {
CommandAttr (undef, "$name setupInverterDev $val2");
readingsDelete ($hash, 'currentInverterDev');
}
+
+ my $val3 = ReadingsVal ($name, 'inverterStrings', ''); # 05.06.2024
+ if ($val3) {
+ CommandAttr (undef, "$name setupInverterStrings $val3");
+ readingsDelete ($hash, 'inverterStrings');
+ }
##########################################################################################################################
setModel ($hash); # Model setzen
@@ -6522,11 +6524,11 @@ sub createStringConfig { ## no critic "not used"
delete $data{$type}{$name}{strings}; # Stringhash zurücksetzen
$data{$type}{$name}{current}{allStringsFullfilled} = 0;
- my @istrings = split ",", ReadingsVal ($name, 'inverterStrings', ''); # Stringbezeichner
+ my @istrings = split ",", AttrVal ($name, 'setupInverterStrings', ''); # Stringbezeichner
$data{$type}{$name}{current}{allstringscount} = scalar @istrings; # Anzahl der Anlagenstrings
if (!@istrings) {
- return qq{Define all used strings with command "set $name inverterStrings" first.};
+ return qq{Define all used strings with command "attr $name setupInverterStrings" first.};
}
my $peak = ReadingsVal ($name, 'modulePeakString', ''); # kWp für jeden Stringbezeichner
@@ -6541,7 +6543,7 @@ sub createStringConfig { ## no critic "not used"
$data{$type}{$name}{current}{allstringspeak} += $pp * 1000; # insgesamt installierte Peakleistung in W
}
else {
- return qq{Check "modulePeakString" -> the stringname "$strg" is not defined as valid string in reading "inverterStrings"};
+ return qq{Check "modulePeakString" -> the stringname "$strg" is not defined as valid string in attribute "setupInverterStrings"};
}
}
@@ -6556,15 +6558,15 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"};
}
}
}
elsif (isVictronKiUsed ($hash)) {
- my $invs = ReadingsVal ($name, 'inverterStrings', '');
+ my $invs = AttrVal ($name, 'setupInverterStrings', '');
if ($invs ne 'KI-based') {
- return qq{You use a KI based model. Please set only "KI-based" as String with command "set $name inverterStrings".};
+ return qq{You use a KI based model. Please set only "KI-based" as String with command "attr $name setupInverterStrings".};
}
}
elsif (!isVictronKiUsed ($hash)) {
@@ -6578,7 +6580,7 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"};
}
}
@@ -6594,18 +6596,18 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"};
}
}
}
if(!keys %{$data{$type}{$name}{strings}}) {
return qq{The string configuration seems to be incomplete. \n}.
- qq{Please check the settings of inverterStrings, modulePeakString, moduleAzimuth, moduleDeclination }.
+ qq{Please check the settings of setupInverterStrings, modulePeakString, moduleAzimuth, moduleDeclination }.
qq{and/or moduleRoofTops if SolCast-API is used.};
}
- my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in inverterStrings enthalten sind als eigentlich verwendet
+ my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in setupInverterStrings enthalten sind als eigentlich verwendet
my @tom;
for my $sn (@istrings) {
@@ -6614,7 +6616,7 @@ sub createStringConfig { ## no critic "not used"
}
if (@tom) {
- return qq{Some Strings are not used. Please delete this string names from "inverterStrings" :}.join ",",@tom;
+ return qq{Some Strings are not used. Please delete this string names from "setupInverterStrings" :}.join ",",@tom;
}
$data{$type}{$name}{current}{allStringsFullfilled} = 1;
@@ -7203,7 +7205,7 @@ sub __delObsoleteAPIData {
delete $data{$type}{$name}{solcastapi}{'?All'}{$idx} if($idx =~ /^fc?([0-9]{1,2})_?([0-9]{1,2})$/xs);
}
- my @as = split ",", ReadingsVal($name, 'inverterStrings', '');
+ my @as = split ",", AttrVal ($name, 'setupInverterStrings', '');
return if(!scalar @as);
for my $k (keys %{$data{$type}{$name}{strings}}) { # veraltete Strings aus Strings-Hash löschen
@@ -10621,7 +10623,8 @@ sub calcTodayPVdeviation {
$dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.23.0
}
else {
- $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.24.0
+ my $pvfcd = ReadingsNum ($name, 'RestOfDayPVforecast', 0) - $pvfc; # PV Prognose bis jetzt
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / abs $pvfcd)); # V 1.25.0
}
$data{$type}{$name}{circular}{99}{tdayDvtn} = $dp;
@@ -11088,7 +11091,7 @@ sub genStatisticReadings {
if ($kpi eq 'dayAfterTomorrowPVforecast') { # PV Vorhersage Summe für Übermorgen (falls Werte vorhanden), Forum:#134226
my $dayaftertomorrow = strftime "%Y-%m-%d", localtime($t + 172800); # Datum von Übermorgen
- my @allstrings = split ",", ReadingsVal ($name, 'inverterStrings', '');
+ my @allstrings = split ",", AttrVal ($name, 'setupInverterStrings', '');
my $fcsumdat = 0;
my $type = $paref->{type};
@@ -11509,17 +11512,22 @@ sub _checkSetupNotComplete {
if ($val2) {
CommandAttr (undef, "$name setupInverterDev $val2");
}
+
+ my $val3 = ReadingsVal ($name, 'inverterStrings', ''); # 05.06.2024
+ if ($val3) {
+ CommandAttr (undef, "$name setupInverterStrings $val3");
+ }
##########################################################################################
- my $is = ReadingsVal ($name, 'inverterStrings', undef); # String Konfig
- my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.)
- my $radev = ReadingsVal ($name, 'currentRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
- my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device
- my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
- my $peaks = ReadingsVal ($name, 'modulePeakString', 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 = ReadingsVal ($name, 'currentRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
+ my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device
+ my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
+ my $peaks = ReadingsVal ($name, 'modulePeakString', 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 $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt
@@ -18051,7 +18059,7 @@ return $def;
# Usage:
# SolCastAPIVal ($hash, $tring, $ststr, $key, $def)
#
-# $tring: Stringname aus "inverterStrings" (?All für allg. Werte)
+# $tring: Stringname aus "setupInverterStrings" (?All für allg. Werte)
# $ststr: Startzeit der Form YYYY-MM-DD hh:00:00
# $key: pv_estimate50 - PV Schätzung in Wh
# Rad1h - vorhergesagte Globalstrahlung (Model DWD)
@@ -18171,7 +18179,7 @@ to ensure that the system configuration is correct.
setupInverterDev | Device which provides PV performance data |
setupMeterDev | Device which supplies network I/O data |
setupBatteryDev | Device which provides battery performance data (if available) |
- inverterStrings | Identifier of the existing plant strings |
+ setupInverterStrings | Identifier of the existing plant strings |
moduleAzimuth | Azimuth of the plant strings |
modulePeakString | the DC peak power of the plant strings |
roofIdentPair | the identification data (when using the SolCast API) |
@@ -18352,7 +18360,7 @@ to ensure that the system configuration is correct.
API usage requires one or more API-keys (accounts) and one or more Rooftop-ID's in advance
created on the SolCast website.
- A rooftop is equivalent to one inverterString
+ A rooftop is equivalent to one setupInverterStrings
in the SolarForecast context.
Free API usage is limited to one daily rate API requests. The number of defined strings (rooftops)
increases the number of API requests required. The module optimizes the query cycles with the attribute
@@ -18371,7 +18379,7 @@ to ensure that the system configuration is correct.
This API can be applied by users of the Victron Energy VRM Portal. This API is AI based.
As string the value "AI-based" has to be entered in the setup of the
- inverterStrings.
+ setupInverterStrings.
In the Victron Energy VRM Portal, the location of the PV system must be specified as a prerequisite.
See also the blog post
Introducing Solar Production Forecast.
@@ -18426,31 +18434,13 @@ to ensure that the system configuration is correct.
-
-
- - inverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
-
- Designations of the active strings. These names are used as keys in the further
- settings.
- When using an AI based API (e.g. VictronKI API) only "KI-based" has to be entered regardless of
- which real strings exist.
-
-
- Examples:
- set <name> inverterStrings eastroof,southgarage,S3
- set <name> inverterStrings KI-based
-
-
-
-
-
- moduleAzimuth <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
- inverterStrings reading.
+ setupInverterStrings attribute.
The direction specification <dir> can be specified as an azimuth identifier or as an azimuth value:
@@ -18488,7 +18478,7 @@ to ensure that the system configuration is correct.
- moduleDeclination <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 reading inverterStrings.
+ Tilt angle of the solar modules. The string name is a key value of the attribute setupInverterStrings.
Possible angles of inclination are: 0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90
(0 = horizontal, 90 = vertical).
@@ -18505,7 +18495,7 @@ to ensure that the system configuration is correct.
- modulePeakString <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]
The DC peak power of the string "StringnameX" in kWp. The string name is a key value of the
- Reading inverterStrings.
+ attribute setupInverterStrings.
When using an AI-based API (e.g. Model VictronKiAPI), the peak powers of all existing strings are to be assigned as
a sum to the string name KI-based.
@@ -18526,7 +18516,7 @@ to ensure that the system configuration is correct.
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 reading inverterStrings.
+ The string nameX is a key value of the attribute setupInverterStrings.
@@ -18727,7 +18717,6 @@ to ensure that the system configuration is correct.
| To delete the consumption values of a specific hour of a day: |
| set <name> reset consumption <Day> <Hour> (e.g. set <name> reset consumption 08 10) |
energyH4TriggerSet | deletes the 4-hour energy trigger points |
- inverterStringSet | deletes the string configuration of the installation |
powerTriggerSet | deletes the trigger points for PV generation values |
pvCorrection | deletes the readings pvCorrectionFactor* |
| To delete all previously stored PV correction factors from the caches: |
@@ -20297,6 +20286,22 @@ to ensure that the system configuration is correct.
+
+
+ - setupInverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
+
+ Designations of the active strings. These names are used as keys in the further
+ settings.
+ When using an AI based API (e.g. VictronKI API) only "KI-based" has to be entered regardless of
+ which real strings exist.
+
+
+ Examples:
+ attr <name> setupInverterStrings eastroof,southgarage,S3
+ attr <name> setupInverterStrings KI-based
+
+
+
Example:
@@ -20437,7 +20442,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
setupInverterDev | Device welches PV Leistungsdaten liefert |
setupMeterDev | Device welches Netz I/O-Daten liefert |
setupBatteryDev | Device welches Batterie Leistungsdaten liefert (sofern vorhanden) |
- inverterStrings | Bezeichner der vorhandenen Anlagenstrings |
+ setupInverterStrings | Bezeichner der vorhandenen Anlagenstrings |
moduleAzimuth | Ausrichtung (Azimut) der Anlagenstrings |
modulePeakString | die DC-Peakleistung der Anlagenstrings |
roofIdentPair | die Identifikationsdaten (bei Nutzung der SolCast API) |
@@ -20619,7 +20624,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
Die API-Nutzung benötigt vorab ein oder mehrere API-keys (Accounts) sowie ein oder mehrere Rooftop-ID's
die auf der SolCast Webseite angelegt
werden müssen.
- Ein Rooftop ist im SolarForecast-Kontext mit einem inverterString
+ Ein Rooftop ist im SolarForecast-Kontext mit einem setupInverterString
gleichzusetzen.
Die kostenfreie API-Nutzung ist auf eine Tagesrate API-Anfragen begrenzt. Die Anzahl definierter Strings (Rooftops)
erhöht die Anzahl erforderlicher API-Anfragen. Das Modul optimiert die Abfragezyklen mit dem Attribut
@@ -20637,7 +20642,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
VictronKI-API
Diese API kann durch Nutzer des Victron Energy VRM Portals angewendet werden. Diese API ist KI basierend.
- Als String ist der Wert "KI-based" im Setup der inverterStrings
+ Als String ist der Wert "KI-based" im Setup der setupInverterStrings
einzutragen.
Im Victron Energy VRM Portal ist als Voraussetzung der Standort der PV-Anlage anzugeben.
Siehe dazu auch den Blog-Beitrag
@@ -20694,31 +20699,13 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
-
-
- - inverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
-
- Bezeichnungen der aktiven Strings. Diese Bezeichnungen werden als Schlüssel in den weiteren
- Settings verwendet.
- Bei Nutzung einer KI basierenden API (z.B. VictronKI-API) ist nur "KI-based" einzutragen unabhängig davon
- welche realen Strings existieren.
-
-
- Beispiele:
- set <name> inverterStrings Ostdach,Südgarage,S3
- set <name> inverterStrings KI-based
-
-
-
-
-
- moduleAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
(nur Model DWD, ForecastSolarAPI)
Ausrichtung <dir> der Solarmodule im String "StringnameX". Der Stringname ist ein Schlüsselwert des
- Readings inverterStrings.
+ Attributs setupInverterStrings.
Die Richtungsangabe <dir> kann als Azimut Kennung oder als Azimut Wert angegeben werden:
@@ -20756,7 +20743,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- moduleDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
(nur Model DWD, ForecastSolarAPI)
- Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Readings inverterStrings.
+ Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Attributs setupInverterStrings.
Mögliche Neigungswinkel sind: 0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90
(0 = waagerecht, 90 = senkrecht).
@@ -20773,7 +20760,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- modulePeakString <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]
Die DC Peakleistung des Strings "StringnameX" in kWp. Der Stringname ist ein Schlüsselwert des
- Readings inverterStrings.
+ Attributs setupInverterStrings.
Bei Verwendung einer KI basierenden API (z.B. Model VictronKiAPI) sind die Peakleistungen aller vorhandenen
Strings als Summe dem Stringnamen KI-based zuzuordnen.
@@ -20794,7 +20781,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
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 Readings inverterStrings.
+ Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings.
@@ -21003,7 +20990,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| Um die Verbrauchswerte einer bestimmten Stunde eines Tages zu löschen: |
| set <name> reset consumption <Tag> <Stunde> (z.B. set <name> reset consumption 08 10) |
energyH4TriggerSet | löscht die 4-Stunden Energie Triggerpunkte |
- inverterStringSet | löscht die Stringkonfiguration der Anlage |
powerTriggerSet | löscht die Triggerpunkte für PV Erzeugungswerte |
pvCorrection | löscht die Readings pvCorrectionFactor* |
| Um alle bisher gespeicherten PV Korrekturfaktoren aus den Caches zu löschen: |
@@ -22573,6 +22559,22 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
+
+
+ - setupInverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
+
+ Bezeichnungen der aktiven Strings. Diese Bezeichnungen werden als Schlüssel in den weiteren
+ Settings verwendet.
+ Bei Nutzung einer KI basierenden API (z.B. VictronKI-API) ist nur "KI-based" einzutragen unabhängig davon
+ welche realen Strings existieren.
+
+
+ Beispiele:
+ attr <name> setupInverterStrings Ostdach,Südgarage,S3
+ attr <name> setupInverterStrings KI-based
+
+
+
Beispiel:
diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index 63aa37853..00b3c8e87 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -157,6 +157,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.25.0" => "05.06.2024 transformed setter inverterStrings to attr setupInverterStrings, calcTodayPVdeviation: fix continuously calc again ",
"1.24.0" => "03.06.2024 transformed setter currentInverterDev to attr setupInverterDev, calcTodayPVdeviation: fix continuously calc ",
"1.23.0" => "02.06.2024 transformed setter currentBatteryDev to attr setupBatteryDev, _transferInverterValues: change output for DEBUG ".
"new key attrInvChangedTs in circular, prepare transformation of currentInverterDev ".
@@ -495,7 +496,6 @@ my @fs = qw( ftui_forecast.css
# Anlagenkonfiguration: maßgebliche Readings
my @rconfigs = qw( pvCorrectionFactor_Auto
currentRadiationAPI
- inverterStrings
moduleAzimuth
modulePeakString
moduleDeclination
@@ -525,7 +525,7 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
- setupMeterDev setupBatteryDev setupInverterDev
+ setupMeterDev setupBatteryDev setupInverterDev setupInverterStrings
);
for my $cinit (1..$maxconsumer) {
@@ -544,7 +544,6 @@ my %hset = ( # Ha
consumerNewPlanning => { fn => \&_setconsumerNewPlanning },
currentRadiationAPI => { fn => \&_setcurrentRadiationAPI },
modulePeakString => { fn => \&_setmodulePeakString },
- inverterStrings => { fn => \&_setinverterStrings },
clientAction => { fn => \&_setclientAction },
energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration },
@@ -608,6 +607,7 @@ my %hattr = ( # H
setupMeterDev => { fn => \&_attrMeterDev },
setupBatteryDev => { fn => \&_attrBatteryDev },
setupInverterDev => { fn => \&_attrInverterDev },
+ setupInverterStrings => { fn => \&_attrInverterStrings },
);
my %htr = ( # Hash even/odd für
@@ -658,8 +658,8 @@ my %hqtxt = (
DE => qq{Bitte geben sie das Wechselrichter Device mit "attr LINK setupInverterDev" an} },
mid => { EN => qq{Please specify the device for energy measurement with "attr LINK setupMeterDev"},
DE => qq{Bitte geben sie das Device zur Energiemessung mit "attr LINK setupMeterDev" an} },
- ist => { EN => qq{Please define all of your used string names with "set LINK inverterStrings"},
- DE => qq{Bitte geben sie alle von Ihnen verwendeten Stringnamen mit "set LINK inverterStrings" an} },
+ ist => { EN => qq{Please define all of your used string names with "attr LINK setupInverterStrings"},
+ 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 "set LINK modulePeakString"},
DE => qq{Bitte geben sie die DC Spitzenleistung von jedem String mit "set LINK modulePeakString" an} },
mdr => { EN => qq{Please specify the module direction with "set LINK moduleAzimuth"},
@@ -1217,6 +1217,7 @@ sub Initialize {
"graphicWeatherColor:colorpicker,RGB ".
"graphicWeatherColorNight:colorpicker,RGB ".
"setupInverterDev:textField-long ".
+ "setupInverterStrings ".
"setupMeterDev:textField-long ".
"setupBatteryDev:textField-long ".
$consumer.
@@ -1417,7 +1418,6 @@ sub Set {
consumption
currentInverterSet
energyH4TriggerSet
- inverterStringSet
moduleRoofTopSet
powerTriggerSet
pvCorrection
@@ -1469,7 +1469,6 @@ sub Set {
"consumerNewPlanning:$coms ".
"currentRadiationAPI:$rdd ".
"energyH4Trigger:textField-long ".
- "inverterStrings ".
"modulePeakString ".
"operatingMemory:backup,save".$rf." ".
"operationMode:active,inactive ".
@@ -1799,40 +1798,6 @@ sub _setmoduleRoofTops { ## no critic "not used"
return;
}
-################################################################
-# Setter inverterStrings
-################################################################
-sub _setinverterStrings { ## no critic "not used"
- my $paref = shift;
- my $hash = $paref->{hash};
- my $name = $paref->{name};
- my $prop = $paref->{prop} // return qq{no inverter strings specified};
-
- if ($prop =~ /\?/xs) {
- return qq{The inverter string designation is wrong. An inverter string name must not contain a '?' character!};
- }
-
- my $type = $hash->{TYPE};
-
- my @istrings = split ",", $prop;
-
- for my $k (keys %{$data{$type}{$name}{solcastapi}}) {
- next if ($k =~ /\?/xs || grep /^$k$/, @istrings);
- delete $data{$type}{$name}{solcastapi}{$k};
- }
-
- readingsSingleUpdate ($hash, 'inverterStrings', $prop, 1);
- writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration File schreiben
-
- return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett
-
- my $ret = qq{NOTE: After setting or changing "inverterStrings" please check }.
- qq{/ set all module parameter (e.g. moduleDeclination) again ! \n}.
- qq{Use "set $name plantConfiguration check" to validate your Setup.};
-
-return $ret;
-}
-
################################################################
# Setter operationMode
################################################################
@@ -2692,7 +2657,7 @@ sub __getSolCastData {
Log3 ($name, 1, "$name DEBUG> SolCast API Call - possible daily API Calls: $madc");
}
- $paref->{allstrings} = ReadingsVal ($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
$paref->{firstreq} = 1; # 1. Request, V 0.80.18
__solCast_ApiRequest ($paref);
@@ -3097,7 +3062,7 @@ sub __getForecastSolarData {
}
}
- $paref->{allstrings} = ReadingsVal($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
__forecastSolar_ApiRequest ($paref);
@@ -3367,7 +3332,7 @@ sub ___setForeCastAPIcallKeyData {
## Berechnung des optimalen Request Intervalls
################################################
- my $snum = scalar (split ",", ReadingsVal($name, 'inverterStrings', 'Dummy')); # Anzahl der Strings (mindestens ein String als Dummy)
+ my $snum = scalar (split ",", AttrVal ($name, 'setupInverterStrings', 'Dummy')); # Anzahl der Strings (mindestens ein String als Dummy)
my $period = SolCastAPIVal ($hash, '?All', '?All', 'requests_limit_period', 3600); # Requests Limit Periode
my $limit = SolCastAPIVal ($hash, '?All', '?All', 'requests_limit', 12); # Request Limit in Periode
@@ -3825,7 +3790,7 @@ sub __VictronVRM_ApiResponseForecast {
if ($val) {
$val = sprintf "%.0f", $val;
- my $string = ReadingsVal ($name, 'inverterStrings', '?');
+ my $string = AttrVal ($name, 'setupInverterStrings', '?');
$data{$type}{$name}{solcastapi}{$string}{$starttmstr}{pv_estimate50} = $val;
}
@@ -3848,7 +3813,7 @@ sub __VictronVRM_ApiResponseForecast {
if ($val) {
$val = sprintf "%.2f", $val;
- my $string = ReadingsVal ($name, 'inverterStrings', '?');
+ my $string = AttrVal ($name, 'setupInverterStrings', '?');
$data{$type}{$name}{solcastapi}{$string.'_co'}{$starttmstr}{co_estimate} = $val;
}
@@ -3973,7 +3938,7 @@ sub __getopenMeteoData {
debugLog ($paref, 'apiCall', qq{Open-Meteo API Call - the daily API requests -> limited to: $ometmaxreq, done: $donearq});
my $submodel = InternalVal ($hash->{NAME}, 'MODEL', '');
- $paref->{allstrings} = ReadingsVal ($name, 'inverterStrings', '');
+ $paref->{allstrings} = AttrVal ($name, 'setupInverterStrings', '');
$paref->{submodel} = $submodel eq 'OpenMeteoDWDAPI' ? 'DWD ICON Seamless' :
$submodel eq 'OpenMeteoDWDEnsembleAPI' ? 'DWD ICON Seamless Ensemble' :
$submodel eq 'OpenMeteoWorldAPI' ? 'World Best Match' :
@@ -5519,7 +5484,7 @@ sub _attrMeterDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $medev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5541,7 +5506,7 @@ sub _attrMeterDev { ## no critic "not used"
return qq{Incorrect input for key 'feedprice'. Please consider the commandref.} if(scalar(@afp) != 2 && scalar(@afp) != 3);
}
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, "Current_GridConsumption");
readingsDelete ($hash, "Current_GridFeedIn");
delete $data{$type}{$name}{circular}{'99'}{initdayfeedin};
@@ -5581,7 +5546,7 @@ sub _attrInverterDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5595,7 +5560,7 @@ sub _attrInverterDev { ## no critic "not used"
$data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, "Current_PV");
deleteReadingspec ($hash, ".*_PVreal" );
undef @{$data{$type}{$name}{current}{genslidereg}};
@@ -5608,6 +5573,37 @@ sub _attrInverterDev { ## no critic "not used"
return;
}
+################################################################
+# Attr setupInverterStrings
+################################################################
+sub _attrInverterStrings { ## no critic "not used"
+ my $paref = shift;
+ my $hash = $paref->{hash};
+ my $name = $paref->{name};
+ my $aVal = $paref->{aVal};
+ my $aName = $paref->{aName};
+ my $type = $paref->{type};
+
+ return if(!$init_done);
+
+ if ($paref->{cmd} eq 'set') {
+ if ($aVal =~ /\?/xs) {
+ return qq{The inverter string designation is wrong. An inverter string name must not contain a '?' character!};
+ }
+
+ my @istrings = split ",", $aVal;
+
+ for my $k (keys %{$data{$type}{$name}{solcastapi}}) {
+ next if ($k =~ /\?/xs || grep /^$k$/, @istrings);
+ delete $data{$type}{$name}{solcastapi}{$k};
+ }
+ }
+
+ InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben
+
+return;
+}
+
################################################################
# Attr setupBatteryDev
################################################################
@@ -5621,7 +5617,7 @@ sub _attrBatteryDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
return $err if($err);
@@ -5638,7 +5634,7 @@ sub _attrBatteryDev { ## no critic "not used"
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
}
}
- elsif ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del') {
readingsDelete ($hash, 'Current_PowerBatIn');
readingsDelete ($hash, 'Current_PowerBatOut');
readingsDelete ($hash, 'Current_BatCharge');
@@ -5674,7 +5670,7 @@ sub _attrWeatherDev { ## no critic "not used"
return if(!$init_done);
- if ($paref->{cmd} eq 'set' ) {
+ if ($paref->{cmd} eq 'set') {
if ($aVal !~ /^OpenMeteo/xs && (!$defs{$aVal} || $defs{$aVal}{TYPE} ne "DWD_OpenData")) {
return qq{The device "$aVal" doesn't exist or has no TYPE 'DWD_OpenData'};
}
@@ -6408,6 +6404,12 @@ sub centralTask {
CommandAttr (undef, "$name setupInverterDev $val2");
readingsDelete ($hash, 'currentInverterDev');
}
+
+ my $val3 = ReadingsVal ($name, 'inverterStrings', ''); # 05.06.2024
+ if ($val3) {
+ CommandAttr (undef, "$name setupInverterStrings $val3");
+ readingsDelete ($hash, 'inverterStrings');
+ }
##########################################################################################################################
setModel ($hash); # Model setzen
@@ -6522,11 +6524,11 @@ sub createStringConfig { ## no critic "not used"
delete $data{$type}{$name}{strings}; # Stringhash zurücksetzen
$data{$type}{$name}{current}{allStringsFullfilled} = 0;
- my @istrings = split ",", ReadingsVal ($name, 'inverterStrings', ''); # Stringbezeichner
+ my @istrings = split ",", AttrVal ($name, 'setupInverterStrings', ''); # Stringbezeichner
$data{$type}{$name}{current}{allstringscount} = scalar @istrings; # Anzahl der Anlagenstrings
if (!@istrings) {
- return qq{Define all used strings with command "set $name inverterStrings" first.};
+ return qq{Define all used strings with command "attr $name setupInverterStrings" first.};
}
my $peak = ReadingsVal ($name, 'modulePeakString', ''); # kWp für jeden Stringbezeichner
@@ -6541,7 +6543,7 @@ sub createStringConfig { ## no critic "not used"
$data{$type}{$name}{current}{allstringspeak} += $pp * 1000; # insgesamt installierte Peakleistung in W
}
else {
- return qq{Check "modulePeakString" -> the stringname "$strg" is not defined as valid string in reading "inverterStrings"};
+ return qq{Check "modulePeakString" -> the stringname "$strg" is not defined as valid string in attribute "setupInverterStrings"};
}
}
@@ -6556,15 +6558,15 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleRoofTops" -> the stringname "$is" is not defined as valid string in attribute "setupInverterStrings"};
}
}
}
elsif (isVictronKiUsed ($hash)) {
- my $invs = ReadingsVal ($name, 'inverterStrings', '');
+ my $invs = AttrVal ($name, 'setupInverterStrings', '');
if ($invs ne 'KI-based') {
- return qq{You use a KI based model. Please set only "KI-based" as String with command "set $name inverterStrings".};
+ return qq{You use a KI based model. Please set only "KI-based" as String with command "attr $name setupInverterStrings".};
}
}
elsif (!isVictronKiUsed ($hash)) {
@@ -6578,7 +6580,7 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleDeclination" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"};
}
}
@@ -6594,18 +6596,18 @@ 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 reading "inverterStrings"};
+ return qq{Check "moduleAzimuth" -> the stringname "$key" is not defined as valid string in attribute "setupInverterStrings"};
}
}
}
if(!keys %{$data{$type}{$name}{strings}}) {
return qq{The string configuration seems to be incomplete. \n}.
- qq{Please check the settings of inverterStrings, modulePeakString, moduleAzimuth, moduleDeclination }.
+ qq{Please check the settings of setupInverterStrings, modulePeakString, moduleAzimuth, moduleDeclination }.
qq{and/or moduleRoofTops if SolCast-API is used.};
}
- my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in inverterStrings enthalten sind als eigentlich verwendet
+ my @sca = keys %{$data{$type}{$name}{strings}}; # Gegencheck ob nicht mehr Strings in setupInverterStrings enthalten sind als eigentlich verwendet
my @tom;
for my $sn (@istrings) {
@@ -6614,7 +6616,7 @@ sub createStringConfig { ## no critic "not used"
}
if (@tom) {
- return qq{Some Strings are not used. Please delete this string names from "inverterStrings" :}.join ",",@tom;
+ return qq{Some Strings are not used. Please delete this string names from "setupInverterStrings" :}.join ",",@tom;
}
$data{$type}{$name}{current}{allStringsFullfilled} = 1;
@@ -7203,7 +7205,7 @@ sub __delObsoleteAPIData {
delete $data{$type}{$name}{solcastapi}{'?All'}{$idx} if($idx =~ /^fc?([0-9]{1,2})_?([0-9]{1,2})$/xs);
}
- my @as = split ",", ReadingsVal($name, 'inverterStrings', '');
+ my @as = split ",", AttrVal ($name, 'setupInverterStrings', '');
return if(!scalar @as);
for my $k (keys %{$data{$type}{$name}{strings}}) { # veraltete Strings aus Strings-Hash löschen
@@ -10621,7 +10623,8 @@ sub calcTodayPVdeviation {
$dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.23.0
}
else {
- $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.24.0
+ my $pvfcd = ReadingsNum ($name, 'RestOfDayPVforecast', 0) - $pvfc; # PV Prognose bis jetzt
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / abs $pvfcd)); # V 1.25.0
}
$data{$type}{$name}{circular}{99}{tdayDvtn} = $dp;
@@ -11088,7 +11091,7 @@ sub genStatisticReadings {
if ($kpi eq 'dayAfterTomorrowPVforecast') { # PV Vorhersage Summe für Übermorgen (falls Werte vorhanden), Forum:#134226
my $dayaftertomorrow = strftime "%Y-%m-%d", localtime($t + 172800); # Datum von Übermorgen
- my @allstrings = split ",", ReadingsVal ($name, 'inverterStrings', '');
+ my @allstrings = split ",", AttrVal ($name, 'setupInverterStrings', '');
my $fcsumdat = 0;
my $type = $paref->{type};
@@ -11509,17 +11512,22 @@ sub _checkSetupNotComplete {
if ($val2) {
CommandAttr (undef, "$name setupInverterDev $val2");
}
+
+ my $val3 = ReadingsVal ($name, 'inverterStrings', ''); # 05.06.2024
+ if ($val3) {
+ CommandAttr (undef, "$name setupInverterStrings $val3");
+ }
##########################################################################################
- my $is = ReadingsVal ($name, 'inverterStrings', undef); # String Konfig
- my $wedev = AttrVal ($name, 'ctrlWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.)
- my $radev = ReadingsVal ($name, 'currentRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
- my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device
- my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
- my $peaks = ReadingsVal ($name, 'modulePeakString', 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 = ReadingsVal ($name, 'currentRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
+ my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device
+ my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
+ my $peaks = ReadingsVal ($name, 'modulePeakString', 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 $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt
@@ -18051,7 +18059,7 @@ return $def;
# Usage:
# SolCastAPIVal ($hash, $tring, $ststr, $key, $def)
#
-# $tring: Stringname aus "inverterStrings" (?All für allg. Werte)
+# $tring: Stringname aus "setupInverterStrings" (?All für allg. Werte)
# $ststr: Startzeit der Form YYYY-MM-DD hh:00:00
# $key: pv_estimate50 - PV Schätzung in Wh
# Rad1h - vorhergesagte Globalstrahlung (Model DWD)
@@ -18171,7 +18179,7 @@ to ensure that the system configuration is correct.
setupInverterDev | Device which provides PV performance data |
setupMeterDev | Device which supplies network I/O data |
setupBatteryDev | Device which provides battery performance data (if available) |
- inverterStrings | Identifier of the existing plant strings |
+ setupInverterStrings | Identifier of the existing plant strings |
moduleAzimuth | Azimuth of the plant strings |
modulePeakString | the DC peak power of the plant strings |
roofIdentPair | the identification data (when using the SolCast API) |
@@ -18352,7 +18360,7 @@ to ensure that the system configuration is correct.
API usage requires one or more API-keys (accounts) and one or more Rooftop-ID's in advance
created on the SolCast website.
- A rooftop is equivalent to one inverterString
+ A rooftop is equivalent to one setupInverterStrings
in the SolarForecast context.
Free API usage is limited to one daily rate API requests. The number of defined strings (rooftops)
increases the number of API requests required. The module optimizes the query cycles with the attribute
@@ -18371,7 +18379,7 @@ to ensure that the system configuration is correct.
This API can be applied by users of the Victron Energy VRM Portal. This API is AI based.
As string the value "AI-based" has to be entered in the setup of the
- inverterStrings.
+ setupInverterStrings.
In the Victron Energy VRM Portal, the location of the PV system must be specified as a prerequisite.
See also the blog post
Introducing Solar Production Forecast.
@@ -18426,31 +18434,13 @@ to ensure that the system configuration is correct.
-
-
- - inverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
-
- Designations of the active strings. These names are used as keys in the further
- settings.
- When using an AI based API (e.g. VictronKI API) only "KI-based" has to be entered regardless of
- which real strings exist.
-
-
- Examples:
- set <name> inverterStrings eastroof,southgarage,S3
- set <name> inverterStrings KI-based
-
-
-
-
-
- moduleAzimuth <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
- inverterStrings reading.
+ setupInverterStrings attribute.
The direction specification <dir> can be specified as an azimuth identifier or as an azimuth value:
@@ -18488,7 +18478,7 @@ to ensure that the system configuration is correct.
- moduleDeclination <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 reading inverterStrings.
+ Tilt angle of the solar modules. The string name is a key value of the attribute setupInverterStrings.
Possible angles of inclination are: 0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90
(0 = horizontal, 90 = vertical).
@@ -18505,7 +18495,7 @@ to ensure that the system configuration is correct.
- modulePeakString <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]
The DC peak power of the string "StringnameX" in kWp. The string name is a key value of the
- Reading inverterStrings.
+ attribute setupInverterStrings.
When using an AI-based API (e.g. Model VictronKiAPI), the peak powers of all existing strings are to be assigned as
a sum to the string name KI-based.
@@ -18526,7 +18516,7 @@ to ensure that the system configuration is correct.
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 reading inverterStrings.
+ The string nameX is a key value of the attribute setupInverterStrings.
@@ -18727,7 +18717,6 @@ to ensure that the system configuration is correct.
| To delete the consumption values of a specific hour of a day: |
| set <name> reset consumption <Day> <Hour> (e.g. set <name> reset consumption 08 10) |
energyH4TriggerSet | deletes the 4-hour energy trigger points |
- inverterStringSet | deletes the string configuration of the installation |
powerTriggerSet | deletes the trigger points for PV generation values |
pvCorrection | deletes the readings pvCorrectionFactor* |
| To delete all previously stored PV correction factors from the caches: |
@@ -20297,6 +20286,22 @@ to ensure that the system configuration is correct.
+
+
+ - setupInverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
+
+ Designations of the active strings. These names are used as keys in the further
+ settings.
+ When using an AI based API (e.g. VictronKI API) only "KI-based" has to be entered regardless of
+ which real strings exist.
+
+
+ Examples:
+ attr <name> setupInverterStrings eastroof,southgarage,S3
+ attr <name> setupInverterStrings KI-based
+
+
+
Example:
@@ -20437,7 +20442,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
setupInverterDev | Device welches PV Leistungsdaten liefert |
setupMeterDev | Device welches Netz I/O-Daten liefert |
setupBatteryDev | Device welches Batterie Leistungsdaten liefert (sofern vorhanden) |
- inverterStrings | Bezeichner der vorhandenen Anlagenstrings |
+ setupInverterStrings | Bezeichner der vorhandenen Anlagenstrings |
moduleAzimuth | Ausrichtung (Azimut) der Anlagenstrings |
modulePeakString | die DC-Peakleistung der Anlagenstrings |
roofIdentPair | die Identifikationsdaten (bei Nutzung der SolCast API) |
@@ -20619,7 +20624,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
Die API-Nutzung benötigt vorab ein oder mehrere API-keys (Accounts) sowie ein oder mehrere Rooftop-ID's
die auf der SolCast Webseite angelegt
werden müssen.
- Ein Rooftop ist im SolarForecast-Kontext mit einem inverterString
+ Ein Rooftop ist im SolarForecast-Kontext mit einem setupInverterString
gleichzusetzen.
Die kostenfreie API-Nutzung ist auf eine Tagesrate API-Anfragen begrenzt. Die Anzahl definierter Strings (Rooftops)
erhöht die Anzahl erforderlicher API-Anfragen. Das Modul optimiert die Abfragezyklen mit dem Attribut
@@ -20637,7 +20642,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
VictronKI-API
Diese API kann durch Nutzer des Victron Energy VRM Portals angewendet werden. Diese API ist KI basierend.
- Als String ist der Wert "KI-based" im Setup der inverterStrings
+ Als String ist der Wert "KI-based" im Setup der setupInverterStrings
einzutragen.
Im Victron Energy VRM Portal ist als Voraussetzung der Standort der PV-Anlage anzugeben.
Siehe dazu auch den Blog-Beitrag
@@ -20694,31 +20699,13 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
-
-
- - inverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
-
- Bezeichnungen der aktiven Strings. Diese Bezeichnungen werden als Schlüssel in den weiteren
- Settings verwendet.
- Bei Nutzung einer KI basierenden API (z.B. VictronKI-API) ist nur "KI-based" einzutragen unabhängig davon
- welche realen Strings existieren.
-
-
- Beispiele:
- set <name> inverterStrings Ostdach,Südgarage,S3
- set <name> inverterStrings KI-based
-
-
-
-
-
- moduleAzimuth <Stringname1>=<dir> [<Stringname2>=<dir> <Stringname3>=<dir> ...]
(nur Model DWD, ForecastSolarAPI)
Ausrichtung <dir> der Solarmodule im String "StringnameX". Der Stringname ist ein Schlüsselwert des
- Readings inverterStrings.
+ Attributs setupInverterStrings.
Die Richtungsangabe <dir> kann als Azimut Kennung oder als Azimut Wert angegeben werden:
@@ -20756,7 +20743,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- moduleDeclination <Stringname1>=<Winkel> [<Stringname2>=<Winkel> <Stringname3>=<Winkel> ...]
(nur Model DWD, ForecastSolarAPI)
- Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Readings inverterStrings.
+ Neigungswinkel der Solarmodule. Der Stringname ist ein Schlüsselwert des Attributs setupInverterStrings.
Mögliche Neigungswinkel sind: 0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90
(0 = waagerecht, 90 = senkrecht).
@@ -20773,7 +20760,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
- modulePeakString <Stringname1>=<Peak> [<Stringname2>=<Peak> <Stringname3>=<Peak> ...]
Die DC Peakleistung des Strings "StringnameX" in kWp. Der Stringname ist ein Schlüsselwert des
- Readings inverterStrings.
+ Attributs setupInverterStrings.
Bei Verwendung einer KI basierenden API (z.B. Model VictronKiAPI) sind die Peakleistungen aller vorhandenen
Strings als Summe dem Stringnamen KI-based zuzuordnen.
@@ -20794,7 +20781,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
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 Readings inverterStrings.
+ Der StringnameX ist ein Schlüsselwert des Attributs setupInverterStrings.
@@ -21003,7 +20990,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| Um die Verbrauchswerte einer bestimmten Stunde eines Tages zu löschen: |
| set <name> reset consumption <Tag> <Stunde> (z.B. set <name> reset consumption 08 10) |
energyH4TriggerSet | löscht die 4-Stunden Energie Triggerpunkte |
- inverterStringSet | löscht die Stringkonfiguration der Anlage |
powerTriggerSet | löscht die Triggerpunkte für PV Erzeugungswerte |
pvCorrection | löscht die Readings pvCorrectionFactor* |
| Um alle bisher gespeicherten PV Korrekturfaktoren aus den Caches zu löschen: |
@@ -22573,6 +22559,22 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
+
+
+ - setupInverterStrings <Stringname1>[,<Stringname2>,<Stringname3>,...]
+
+ Bezeichnungen der aktiven Strings. Diese Bezeichnungen werden als Schlüssel in den weiteren
+ Settings verwendet.
+ Bei Nutzung einer KI basierenden API (z.B. VictronKI-API) ist nur "KI-based" einzutragen unabhängig davon
+ welche realen Strings existieren.
+
+
+ Beispiele:
+ attr <name> setupInverterStrings Ostdach,Südgarage,S3
+ attr <name> setupInverterStrings KI-based
+
+
+