diff --git a/fhem/CHANGED b/fhem/CHANGED
index 1cfa806a0..93eaf2c9e 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 currentInverterDev to attr setupInverterDev
+ !NOTE! save FHEM config after restart
- bugfix: 73_PRESENCE2: entfernt BlockingCall loglevel = GetVerbose($name)
- bugfix: 73_PRESENCE: entfernt BlockingCall loglevel = GetVerbose($name)
- bugfix: 98_CDCOpenData: entfernt BlockingCall loglevel = GetVerbose($name)
diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm
index a92d019c2..63aa37853 100644
--- a/fhem/FHEM/76_SolarForecast.pm
+++ b/fhem/FHEM/76_SolarForecast.pm
@@ -157,6 +157,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "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 ".
"calcTodayPVdeviation: fix daily calc ",
@@ -493,7 +494,6 @@ my @fs = qw( ftui_forecast.css
);
# Anlagenkonfiguration: maßgebliche Readings
my @rconfigs = qw( pvCorrectionFactor_Auto
- currentInverterDev
currentRadiationAPI
inverterStrings
moduleAzimuth
@@ -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
+ setupMeterDev setupBatteryDev setupInverterDev
);
for my $cinit (1..$maxconsumer) {
@@ -546,7 +546,6 @@ my %hset = ( # Ha
modulePeakString => { fn => \&_setmodulePeakString },
inverterStrings => { fn => \&_setinverterStrings },
clientAction => { fn => \&_setclientAction },
- currentInverterDev => { fn => \&_setinverterDevice },
energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration },
batteryTrigger => { fn => \&_setTrigger },
@@ -608,6 +607,7 @@ my %hattr = ( # H
ctrlWeatherDev3 => { fn => \&_attrWeatherDev },
setupMeterDev => { fn => \&_attrMeterDev },
setupBatteryDev => { fn => \&_attrBatteryDev },
+ setupInverterDev => { fn => \&_attrInverterDev },
);
my %htr = ( # Hash even/odd für
@@ -654,8 +654,8 @@ my %hqtxt = (
DE => qq{Bitte geben sie mindestens ein Wettervorhersage Device mit "attr LINK ctrlWeatherDev1" an} },
crd => { EN => qq{Please select the radiation forecast service with "set LINK currentRadiationAPI"},
DE => qq{Bitte geben sie den Strahlungsvorhersage Dienst mit "set LINK currentRadiationAPI" an} },
- cid => { EN => qq{Please specify the Inverter device with "set LINK currentInverterDev"},
- DE => qq{Bitte geben sie das Wechselrichter Device mit "set LINK currentInverterDev" an} },
+ cid => { EN => qq{Please specify the Inverter device with "attr LINK setupInverterDev"},
+ 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"},
@@ -1216,6 +1216,7 @@ sub Initialize {
"graphicEndHtml ".
"graphicWeatherColor:colorpicker,RGB ".
"graphicWeatherColorNight:colorpicker,RGB ".
+ "setupInverterDev:textField-long ".
"setupMeterDev:textField-long ".
"setupBatteryDev:textField-long ".
$consumer.
@@ -1467,7 +1468,6 @@ sub Set {
"consumerImmediatePlanning:$coms ".
"consumerNewPlanning:$coms ".
"currentRadiationAPI:$rdd ".
- "currentInverterDev:textField-long ".
"energyH4Trigger:textField-long ".
"inverterStrings ".
"modulePeakString ".
@@ -1799,41 +1799,6 @@ sub _setmoduleRoofTops { ## no critic "not used"
return;
}
-################################################################
-# Setter currentInverterDev
-################################################################
-sub _setinverterDevice { ## no critic "not used"
- my $paref = shift;
- my $hash = $paref->{hash};
- my $name = $paref->{name};
- my $type = $paref->{type};
- my $opt = $paref->{opt};
- my $arg = $paref->{arg};
-
- if (!$arg) {
- return qq{The command "$opt" needs an argument !};
- }
-
- my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $arg, method => 'string' } );
- return $err if($err);
-
- if (!$h->{pv} || !$h->{etotal}) {
- return qq{The syntax of "$opt" is not correct. Please consider the commandref.};
- }
-
- if ($h->{capacity} && !isNumeric($h->{capacity})) {
- return qq{The syntax of key "capacity" is not correct. Please consider the commandref.};
- }
-
- $data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
-
- readingsSingleUpdate ($hash, 'currentInverterDev', $arg, 1);
- createAssociatedWith ($hash);
- writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
-
-return;
-}
-
################################################################
# Setter inverterStrings
################################################################
@@ -2357,17 +2322,6 @@ sub _setreset { ## no critic "not used"
return;
}
- if ($prop eq 'currentInverterSet') {
- undef @{$data{$type}{$name}{current}{genslidereg}};
- readingsDelete ($hash, "Current_PV");
- readingsDelete ($hash, "currentInverterDev");
- deleteReadingspec ($hash, ".*_PVreal" );
-
- delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
-
- writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
- }
-
if ($prop eq 'consumerPlanning') { # Verbraucherplanung resetten
my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben
@@ -5570,7 +5524,7 @@ sub _attrMeterDev { ## no critic "not used"
return $err if($err);
if (!$h->{gcon} || !$h->{contotal} || !$h->{gfeedin} || !$h->{feedtotal}) {
- return qq{The syntax of "$aName" is not correct. Please consider the commandref.};
+ return qq{The syntax of '$aName' is not correct. Please consider the commandref.};
}
if ($h->{gcon} eq "-gfeedin" && $h->{gfeedin} eq "-gcon") {
@@ -5587,8 +5541,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);
}
}
-
- if ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del' ) {
readingsDelete ($hash, "Current_GridConsumption");
readingsDelete ($hash, "Current_GridFeedIn");
delete $data{$type}{$name}{circular}{'99'}{initdayfeedin};
@@ -5615,6 +5568,46 @@ sub _attrMeterDev { ## no critic "not used"
return;
}
+################################################################
+# Attr setupInverterDev
+################################################################
+sub _attrInverterDev { ## 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' ) {
+ my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
+ return $err if($err);
+
+ if (!$h->{pv} || !$h->{etotal}) {
+ return qq{The syntax of '$aName' is not correct. Please consider the commandref.};
+ }
+
+ if ($h->{capacity} && !isNumeric($h->{capacity})) {
+ return qq{The syntax of key 'capacity' is not correct. Please consider the commandref.};
+ }
+
+ $data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
+ }
+ elsif ($paref->{cmd} eq 'del' ) {
+ readingsDelete ($hash, "Current_PV");
+ deleteReadingspec ($hash, ".*_PVreal" );
+ undef @{$data{$type}{$name}{current}{genslidereg}};
+ delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
+ }
+
+ InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
+ InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben
+
+return;
+}
+
################################################################
# Attr setupBatteryDev
################################################################
@@ -5633,20 +5626,19 @@ sub _attrBatteryDev { ## no critic "not used"
return $err if($err);
if (!$h->{pin} || !$h->{pout}) {
- return qq{The keys "pin" and/or "pout" are not set. Please note the command reference.};
+ return qq{The keys 'pin' and/or 'pout' are not set. Please note the command reference.};
}
if (($h->{pin} !~ /-/xs && $h->{pin} !~ /:/xs) ||
($h->{pout} !~ /-/xs && $h->{pout} !~ /:/xs)) {
- return qq{The keys "pin" and/or "pout" are not set correctly. Please note the command reference.};
+ return qq{The keys 'pin' and/or 'pout' are not set correctly. Please note the command reference.};
}
if ($h->{pin} eq "-pout" && $h->{pout} eq "-pin") {
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
}
}
-
- if ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del' ) {
readingsDelete ($hash, 'Current_PowerBatIn');
readingsDelete ($hash, 'Current_PowerBatOut');
readingsDelete ($hash, 'Current_BatCharge');
@@ -6410,6 +6402,12 @@ sub centralTask {
$idts = timestringToTimestamp ($idts);
$data{$type}{$name}{circular}{99}{attrInvChangedTs} = $idts;
}
+
+ my $val2 = ReadingsVal ($name, 'currentInverterDev', ''); # 03.06.2024
+ if ($val2) {
+ CommandAttr (undef, "$name setupInverterDev $val2");
+ readingsDelete ($hash, 'currentInverterDev');
+ }
##########################################################################################################################
setModel ($hash); # Model setzen
@@ -8024,7 +8022,7 @@ sub _transferInverterValues {
my $chour = $paref->{chour};
my $day = $paref->{day};
- my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'currentInverterDev', method => 'reading' } );
+ my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'setupInverterDev', method => 'attr' } );
return if($err);
my $type = $paref->{type};
@@ -10612,21 +10610,18 @@ sub calcTodayPVdeviation {
my $pvfc = ReadingsNum ($name, 'Today_PVforecast', 0);
my $pvre = ReadingsNum ($name, 'Today_PVreal', 0);
- return if(!$pvre);
+ return if(!$pvre || !$pvfc); # Illegal division by zero verhindern
my $dp;
if (AttrVal ($name, 'ctrlGenPVdeviation', 'daily') eq 'daily') {
my $sstime = timestringToTimestamp ($date.' '.ReadingsVal ($name, "Today_SunSet", '22:00').':00');
- return if(!$pvfc || $t < $sstime); # V 1.23.0
+ return if($t < $sstime);
- $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.23.0
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.23.0
}
- else {
- my $rodfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Forecast für den Rest des Tages
- my $cufc = $pvfc - $rodfc; # laufende PV Prognose aus Tagesprognose - Prognose Resttag
- return if(!$cufc); # Illegal division by zero verhindern
- $dp = sprintf "%.2f", (100 - (100 * $pvre / $cufc));
+ else {
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.24.0
}
$data{$type}{$name}{circular}{99}{tdayDvtn} = $dp;
@@ -11510,15 +11505,17 @@ sub _checkSetupNotComplete {
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
##########################################################################################
-
+ my $val2 = ReadingsVal ($name, 'currentInverterDev', ''); # 03.06.2024
+ if ($val2) {
+ CommandAttr (undef, "$name setupInverterDev $val2");
+ }
##########################################################################################
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 = ReadingsVal ($name, 'currentInverterDev', undef); # Inverter Device
+ 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
@@ -16187,7 +16184,7 @@ sub createAssociatedWith {
($ara,$h) = parseParams ($radev);
$radev = $ara->[0] // "";
- my $indev = ReadingsVal ($name, 'currentInverterDev', ''); # Inverter Device
+ my $indev = AttrVal ($name, 'setupInverterDev', ''); # Inverter Device
($ain,$h) = parseParams ($indev);
$indev = $ain->[0] // "";
@@ -18171,7 +18168,7 @@ to ensure that the system configuration is correct.
| ctrlWeatherDevX | DWD_OpenData Device which provides meteorological data (e.g. cloud cover) |
| currentRadiationAPI | DWD_OpenData Device or API for the delivery of radiation data. |
- | currentInverterDev | Device which provides PV performance 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) |
| inverterStrings | Identifier of the existing plant strings |
@@ -18304,42 +18301,6 @@ to ensure that the system configuration is correct.
-
-
- - currentInverterDev <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit> [capacity=<max. WR-Leistung>]
-
- Specifies any Device and its Readings to deliver the current PV generation values.
- It can also be a dummy device with appropriate readings.
- The values of several inverter devices are merged e.g. in a dummy device and this device is specified with the
- corresponding readings.
- Specifying capacity is optional, but strongly recommended to optimize prediction accuracy.
-
-
-
-
-
- | pv | Reading which provides the current PV generation |
- | etotal | Reading which provides the total PV energy generated (a steadily increasing counter). |
- | | If the reading violates the specification of a continuously rising counter, |
- | | SolarForecast handles this error and reports the situation by means of a log message. |
- | Einheit | the respective unit (W,kW,Wh,kWh) |
- | capacity | Rated power of the inverter according to data sheet, i.e. max. possible output in Watts |
- | | (The entry is optional, but is strongly recommended) |
-
-
-
-
-
- Example:
- set <name> currentInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
-
- # Device STP5000 provides PV values. The currently generated power in the "total_pac" reading (kW) and the total energy
- generated in the reading "etotal" (kWh). The maximum output of the inverter is 5000 watts.
-
-
-
-
-
- currentRadiationAPI
@@ -18765,7 +18726,6 @@ to ensure that the system configuration is correct.
| | set <name> reset consumption <Day> (e.g. set <name> reset consumption 08) |
| | 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) |
- | currentInverterSet | deletes the set inverter device and corresponding data. |
| 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 |
@@ -20314,6 +20274,40 @@ to ensure that the system configuration is correct.
+
+ - setupInverterDev <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit> [capacity=<max. WR-Leistung>]
+
+ Specifies any Device and its Readings to deliver the current PV generation values.
+ It can also be a dummy device with appropriate readings.
+ The values of several inverter devices are merged e.g. in a dummy device and this device is specified with the
+ corresponding readings.
+ Specifying capacity is optional, but strongly recommended to optimize prediction accuracy.
+
+
+
+
+
+ | pv | Reading which provides the current PV generation |
+ | etotal | Reading which provides the total PV energy generated (a steadily increasing counter). |
+ | | If the reading violates the specification of a continuously rising counter, |
+ | | SolarForecast handles this error and reports the situation by means of a log message. |
+ | Einheit | the respective unit (W,kW,Wh,kWh) |
+ | capacity | Rated power of the inverter according to data sheet, i.e. max. possible output in Watts |
+ | | (The entry is optional, but is strongly recommended) |
+
+
+
+
+
+ Example:
+ attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
+
+
+
+ Note: Deleting the attribute also removes the internally corresponding data.
+
+
+
- setupMeterDev <Meter Device Name> gcon=<Readingname>:<Unit> contotal=<Readingname>:<Unit>
gfeedin=<Readingname>:<Unit> feedtotal=<Readingname>:<Unit>
@@ -20440,7 +20434,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| ctrlWeatherDevX | DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert |
| currentRadiationAPI | DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten |
- | currentInverterDev | Device welches PV Leistungsdaten liefert |
+ | 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 |
@@ -20573,42 +20567,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
-
-
- - currentInverterDev <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit> [capacity=<max. WR-Leistung>]
-
- Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
- Es kann auch ein Dummy Device mit entsprechenden Readings sein.
- Die Werte mehrerer Inverterdevices führt man z.B. in einem Dummy Device zusammen und gibt dieses Device mit den
- entsprechenden Readings an.
- Die Angabe von capacity ist optional, wird aber zur Optimierung der Vorhersagegenauigkeit dringend empfohlen.
-
-
-
-
-
- | pv | Reading welches die aktuelle PV-Erzeugung liefert |
- | etotal | Reading welches die gesamte erzeugte PV-Energie liefert (ein stetig aufsteigender Zähler) |
- | | Sollte des Reading die Vorgabe eines stetig aufsteigenden Zählers verletzen, behandelt |
- | | SolarForecast diesen Fehler und meldet die aufgetretene Situation durch eine Logmeldung. |
- | Einheit | die jeweilige Einheit (W,kW,Wh,kWh) |
- | capacity | Bemessungsleistung des Wechselrichters gemäß Datenblatt, d.h. max. möglicher Output in Watt |
- | | (Die Angabe ist optional, wird aber dringend empfohlen zu setzen) |
-
-
-
-
-
- Beispiel:
- set <name> currentInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
-
- # Device STP5000 liefert PV-Werte. Die aktuell erzeugte Leistung im Reading "total_pac" (kW) und die erzeugte Gesamtenergie im
- Reading "etotal" (kWh). Die max. Leistung des Wechselrichters beträgt 5000 Watt.
-
-
-
-
-
- currentRadiationAPI
@@ -21044,7 +21002,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| | set <name> reset consumption <Tag> (z.B. set <name> reset consumption 08) |
| | 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) |
- | currentInverterSet | löscht das eingestellte Inverterdevice und korrespondierende Daten |
| energyH4TriggerSet | löscht die 4-Stunden Energie Triggerpunkte |
| inverterStringSet | löscht die Stringkonfiguration der Anlage |
| powerTriggerSet | löscht die Triggerpunkte für PV Erzeugungswerte |
@@ -22593,6 +22550,40 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
+
+ - setupInverterDev <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit> [capacity=<max. WR-Leistung>]
+
+ Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
+ Es kann auch ein Dummy Device mit entsprechenden Readings sein.
+ Die Werte mehrerer Inverterdevices führt man z.B. in einem Dummy Device zusammen und gibt dieses Device mit den
+ entsprechenden Readings an.
+ Die Angabe von capacity ist optional, wird aber zur Optimierung der Vorhersagegenauigkeit dringend empfohlen.
+
+
+
+
+
+ | pv | Reading welches die aktuelle PV-Erzeugung liefert |
+ | etotal | Reading welches die gesamte erzeugte PV-Energie liefert (ein stetig aufsteigender Zähler) |
+ | | Sollte des Reading die Vorgabe eines stetig aufsteigenden Zählers verletzen, behandelt |
+ | | SolarForecast diesen Fehler und meldet die aufgetretene Situation durch eine Logmeldung. |
+ | Einheit | die jeweilige Einheit (W,kW,Wh,kWh) |
+ | capacity | Bemessungsleistung des Wechselrichters gemäß Datenblatt, d.h. max. möglicher Output in Watt |
+ | | (Die Angabe ist optional, wird aber dringend empfohlen zu setzen) |
+
+
+
+
+
+ Beispiel:
+ attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
+
+
+
+ Hinweis: Durch Löschen des Attributes werden ebenfalls die intern korrespondierenden Daten entfernt.
+
+
+
- setupMeterDev <Meter Device Name> gcon=<Readingname>:<Einheit> contotal=<Readingname>:<Einheit>
gfeedin=<Readingname>:<Einheit> feedtotal=<Readingname>:<Einheit>
diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index 95e18fb71..63aa37853 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -157,8 +157,10 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "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 ",
+ "new key attrInvChangedTs in circular, prepare transformation of currentInverterDev ".
+ "calcTodayPVdeviation: fix daily calc ",
"1.22.0" => "01.06.2024 transformed setter currentMeterDev to attr setupMeterDev, plantConfiguration: setModel after restore ".
"delete reset currentMeterSet ",
"1.21.5" => "30.05.2024 listDataPool: list current can operate three hash levels, first preparation for remote objects ",
@@ -492,7 +494,6 @@ my @fs = qw( ftui_forecast.css
);
# Anlagenkonfiguration: maßgebliche Readings
my @rconfigs = qw( pvCorrectionFactor_Auto
- currentInverterDev
currentRadiationAPI
inverterStrings
moduleAzimuth
@@ -524,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
+ setupMeterDev setupBatteryDev setupInverterDev
);
for my $cinit (1..$maxconsumer) {
@@ -545,7 +546,6 @@ my %hset = ( # Ha
modulePeakString => { fn => \&_setmodulePeakString },
inverterStrings => { fn => \&_setinverterStrings },
clientAction => { fn => \&_setclientAction },
- currentInverterDev => { fn => \&_setinverterDevice },
energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration },
batteryTrigger => { fn => \&_setTrigger },
@@ -607,6 +607,7 @@ my %hattr = ( # H
ctrlWeatherDev3 => { fn => \&_attrWeatherDev },
setupMeterDev => { fn => \&_attrMeterDev },
setupBatteryDev => { fn => \&_attrBatteryDev },
+ setupInverterDev => { fn => \&_attrInverterDev },
);
my %htr = ( # Hash even/odd für
@@ -653,8 +654,8 @@ my %hqtxt = (
DE => qq{Bitte geben sie mindestens ein Wettervorhersage Device mit "attr LINK ctrlWeatherDev1" an} },
crd => { EN => qq{Please select the radiation forecast service with "set LINK currentRadiationAPI"},
DE => qq{Bitte geben sie den Strahlungsvorhersage Dienst mit "set LINK currentRadiationAPI" an} },
- cid => { EN => qq{Please specify the Inverter device with "set LINK currentInverterDev"},
- DE => qq{Bitte geben sie das Wechselrichter Device mit "set LINK currentInverterDev" an} },
+ cid => { EN => qq{Please specify the Inverter device with "attr LINK setupInverterDev"},
+ 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"},
@@ -1215,6 +1216,7 @@ sub Initialize {
"graphicEndHtml ".
"graphicWeatherColor:colorpicker,RGB ".
"graphicWeatherColorNight:colorpicker,RGB ".
+ "setupInverterDev:textField-long ".
"setupMeterDev:textField-long ".
"setupBatteryDev:textField-long ".
$consumer.
@@ -1466,7 +1468,6 @@ sub Set {
"consumerImmediatePlanning:$coms ".
"consumerNewPlanning:$coms ".
"currentRadiationAPI:$rdd ".
- "currentInverterDev:textField-long ".
"energyH4Trigger:textField-long ".
"inverterStrings ".
"modulePeakString ".
@@ -1798,41 +1799,6 @@ sub _setmoduleRoofTops { ## no critic "not used"
return;
}
-################################################################
-# Setter currentInverterDev
-################################################################
-sub _setinverterDevice { ## no critic "not used"
- my $paref = shift;
- my $hash = $paref->{hash};
- my $name = $paref->{name};
- my $type = $paref->{type};
- my $opt = $paref->{opt};
- my $arg = $paref->{arg};
-
- if (!$arg) {
- return qq{The command "$opt" needs an argument !};
- }
-
- my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $arg, method => 'string' } );
- return $err if($err);
-
- if (!$h->{pv} || !$h->{etotal}) {
- return qq{The syntax of "$opt" is not correct. Please consider the commandref.};
- }
-
- if ($h->{capacity} && !isNumeric($h->{capacity})) {
- return qq{The syntax of key "capacity" is not correct. Please consider the commandref.};
- }
-
- $data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
-
- readingsSingleUpdate ($hash, 'currentInverterDev', $arg, 1);
- createAssociatedWith ($hash);
- writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
-
-return;
-}
-
################################################################
# Setter inverterStrings
################################################################
@@ -2356,17 +2322,6 @@ sub _setreset { ## no critic "not used"
return;
}
- if ($prop eq 'currentInverterSet') {
- undef @{$data{$type}{$name}{current}{genslidereg}};
- readingsDelete ($hash, "Current_PV");
- readingsDelete ($hash, "currentInverterDev");
- deleteReadingspec ($hash, ".*_PVreal" );
-
- delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
-
- writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
- }
-
if ($prop eq 'consumerPlanning') { # Verbraucherplanung resetten
my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben
@@ -5569,7 +5524,7 @@ sub _attrMeterDev { ## no critic "not used"
return $err if($err);
if (!$h->{gcon} || !$h->{contotal} || !$h->{gfeedin} || !$h->{feedtotal}) {
- return qq{The syntax of "$aName" is not correct. Please consider the commandref.};
+ return qq{The syntax of '$aName' is not correct. Please consider the commandref.};
}
if ($h->{gcon} eq "-gfeedin" && $h->{gfeedin} eq "-gcon") {
@@ -5586,8 +5541,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);
}
}
-
- if ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del' ) {
readingsDelete ($hash, "Current_GridConsumption");
readingsDelete ($hash, "Current_GridFeedIn");
delete $data{$type}{$name}{circular}{'99'}{initdayfeedin};
@@ -5614,6 +5568,46 @@ sub _attrMeterDev { ## no critic "not used"
return;
}
+################################################################
+# Attr setupInverterDev
+################################################################
+sub _attrInverterDev { ## 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' ) {
+ my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
+ return $err if($err);
+
+ if (!$h->{pv} || !$h->{etotal}) {
+ return qq{The syntax of '$aName' is not correct. Please consider the commandref.};
+ }
+
+ if ($h->{capacity} && !isNumeric($h->{capacity})) {
+ return qq{The syntax of key 'capacity' is not correct. Please consider the commandref.};
+ }
+
+ $data{$type}{$name}{circular}{99}{attrInvChangedTs} = int time;
+ }
+ elsif ($paref->{cmd} eq 'del' ) {
+ readingsDelete ($hash, "Current_PV");
+ deleteReadingspec ($hash, ".*_PVreal" );
+ undef @{$data{$type}{$name}{current}{genslidereg}};
+ delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
+ }
+
+ InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
+ InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0); # Anlagenkonfiguration File schreiben
+
+return;
+}
+
################################################################
# Attr setupBatteryDev
################################################################
@@ -5632,20 +5626,19 @@ sub _attrBatteryDev { ## no critic "not used"
return $err if($err);
if (!$h->{pin} || !$h->{pout}) {
- return qq{The keys "pin" and/or "pout" are not set. Please note the command reference.};
+ return qq{The keys 'pin' and/or 'pout' are not set. Please note the command reference.};
}
if (($h->{pin} !~ /-/xs && $h->{pin} !~ /:/xs) ||
($h->{pout} !~ /-/xs && $h->{pout} !~ /:/xs)) {
- return qq{The keys "pin" and/or "pout" are not set correctly. Please note the command reference.};
+ return qq{The keys 'pin' and/or 'pout' are not set correctly. Please note the command reference.};
}
if ($h->{pin} eq "-pout" && $h->{pout} eq "-pin") {
return qq{Incorrect input. It is not allowed that the keys pin and pout refer to each other.};
}
}
-
- if ($paref->{cmd} eq 'del' ) {
+ elsif ($paref->{cmd} eq 'del' ) {
readingsDelete ($hash, 'Current_PowerBatIn');
readingsDelete ($hash, 'Current_PowerBatOut');
readingsDelete ($hash, 'Current_BatCharge');
@@ -6409,6 +6402,12 @@ sub centralTask {
$idts = timestringToTimestamp ($idts);
$data{$type}{$name}{circular}{99}{attrInvChangedTs} = $idts;
}
+
+ my $val2 = ReadingsVal ($name, 'currentInverterDev', ''); # 03.06.2024
+ if ($val2) {
+ CommandAttr (undef, "$name setupInverterDev $val2");
+ readingsDelete ($hash, 'currentInverterDev');
+ }
##########################################################################################################################
setModel ($hash); # Model setzen
@@ -8023,7 +8022,7 @@ sub _transferInverterValues {
my $chour = $paref->{chour};
my $day = $paref->{day};
- my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'currentInverterDev', method => 'reading' } );
+ my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'setupInverterDev', method => 'attr' } );
return if($err);
my $type = $paref->{type};
@@ -10611,21 +10610,18 @@ sub calcTodayPVdeviation {
my $pvfc = ReadingsNum ($name, 'Today_PVforecast', 0);
my $pvre = ReadingsNum ($name, 'Today_PVreal', 0);
- return if(!$pvre);
+ return if(!$pvre || !$pvfc); # Illegal division by zero verhindern
my $dp;
if (AttrVal ($name, 'ctrlGenPVdeviation', 'daily') eq 'daily') {
my $sstime = timestringToTimestamp ($date.' '.ReadingsVal ($name, "Today_SunSet", '22:00').':00');
- return if($t < $sstime);
+ return if($t < $sstime);
- $dp = sprintf "%.2f", (100 - (100 * $pvfc / $pvre));
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.23.0
}
- else {
- my $rodfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Forecast für den Rest des Tages
- my $cufc = $pvfc - $rodfc; # laufende PV Prognose aus Tagesprognose - Prognose Resttag
- return if(!$cufc); # Illegal division by zero verhindern Forum:
- $dp = sprintf "%.2f", (100 - (100 * $pvre / $cufc));
+ else {
+ $dp = sprintf "%.2f", (100 - (100 * $pvre / $pvfc)); # V 1.24.0
}
$data{$type}{$name}{circular}{99}{tdayDvtn} = $dp;
@@ -11509,15 +11505,17 @@ sub _checkSetupNotComplete {
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
##########################################################################################
-
+ my $val2 = ReadingsVal ($name, 'currentInverterDev', ''); # 03.06.2024
+ if ($val2) {
+ CommandAttr (undef, "$name setupInverterDev $val2");
+ }
##########################################################################################
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 = ReadingsVal ($name, 'currentInverterDev', undef); # Inverter Device
+ 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
@@ -16186,7 +16184,7 @@ sub createAssociatedWith {
($ara,$h) = parseParams ($radev);
$radev = $ara->[0] // "";
- my $indev = ReadingsVal ($name, 'currentInverterDev', ''); # Inverter Device
+ my $indev = AttrVal ($name, 'setupInverterDev', ''); # Inverter Device
($ain,$h) = parseParams ($indev);
$indev = $ain->[0] // "";
@@ -18170,7 +18168,7 @@ to ensure that the system configuration is correct.
| ctrlWeatherDevX | DWD_OpenData Device which provides meteorological data (e.g. cloud cover) |
| currentRadiationAPI | DWD_OpenData Device or API for the delivery of radiation data. |
- | currentInverterDev | Device which provides PV performance 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) |
| inverterStrings | Identifier of the existing plant strings |
@@ -18303,42 +18301,6 @@ to ensure that the system configuration is correct.
-
-
- - currentInverterDev <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit> [capacity=<max. WR-Leistung>]
-
- Specifies any Device and its Readings to deliver the current PV generation values.
- It can also be a dummy device with appropriate readings.
- The values of several inverter devices are merged e.g. in a dummy device and this device is specified with the
- corresponding readings.
- Specifying capacity is optional, but strongly recommended to optimize prediction accuracy.
-
-
-
-
-
- | pv | Reading which provides the current PV generation |
- | etotal | Reading which provides the total PV energy generated (a steadily increasing counter). |
- | | If the reading violates the specification of a continuously rising counter, |
- | | SolarForecast handles this error and reports the situation by means of a log message. |
- | Einheit | the respective unit (W,kW,Wh,kWh) |
- | capacity | Rated power of the inverter according to data sheet, i.e. max. possible output in Watts |
- | | (The entry is optional, but is strongly recommended) |
-
-
-
-
-
- Example:
- set <name> currentInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
-
- # Device STP5000 provides PV values. The currently generated power in the "total_pac" reading (kW) and the total energy
- generated in the reading "etotal" (kWh). The maximum output of the inverter is 5000 watts.
-
-
-
-
-
- currentRadiationAPI
@@ -18764,7 +18726,6 @@ to ensure that the system configuration is correct.
| | set <name> reset consumption <Day> (e.g. set <name> reset consumption 08) |
| | 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) |
- | currentInverterSet | deletes the set inverter device and corresponding data. |
| 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 |
@@ -20313,6 +20274,40 @@ to ensure that the system configuration is correct.
+
+ - setupInverterDev <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit> [capacity=<max. WR-Leistung>]
+
+ Specifies any Device and its Readings to deliver the current PV generation values.
+ It can also be a dummy device with appropriate readings.
+ The values of several inverter devices are merged e.g. in a dummy device and this device is specified with the
+ corresponding readings.
+ Specifying capacity is optional, but strongly recommended to optimize prediction accuracy.
+
+
+
+
+
+ | pv | Reading which provides the current PV generation |
+ | etotal | Reading which provides the total PV energy generated (a steadily increasing counter). |
+ | | If the reading violates the specification of a continuously rising counter, |
+ | | SolarForecast handles this error and reports the situation by means of a log message. |
+ | Einheit | the respective unit (W,kW,Wh,kWh) |
+ | capacity | Rated power of the inverter according to data sheet, i.e. max. possible output in Watts |
+ | | (The entry is optional, but is strongly recommended) |
+
+
+
+
+
+ Example:
+ attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
+
+
+
+ Note: Deleting the attribute also removes the internally corresponding data.
+
+
+
- setupMeterDev <Meter Device Name> gcon=<Readingname>:<Unit> contotal=<Readingname>:<Unit>
gfeedin=<Readingname>:<Unit> feedtotal=<Readingname>:<Unit>
@@ -20439,7 +20434,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| ctrlWeatherDevX | DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert |
| currentRadiationAPI | DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten |
- | currentInverterDev | Device welches PV Leistungsdaten liefert |
+ | 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 |
@@ -20572,42 +20567,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
-
-
- - currentInverterDev <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit> [capacity=<max. WR-Leistung>]
-
- Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
- Es kann auch ein Dummy Device mit entsprechenden Readings sein.
- Die Werte mehrerer Inverterdevices führt man z.B. in einem Dummy Device zusammen und gibt dieses Device mit den
- entsprechenden Readings an.
- Die Angabe von capacity ist optional, wird aber zur Optimierung der Vorhersagegenauigkeit dringend empfohlen.
-
-
-
-
-
- | pv | Reading welches die aktuelle PV-Erzeugung liefert |
- | etotal | Reading welches die gesamte erzeugte PV-Energie liefert (ein stetig aufsteigender Zähler) |
- | | Sollte des Reading die Vorgabe eines stetig aufsteigenden Zählers verletzen, behandelt |
- | | SolarForecast diesen Fehler und meldet die aufgetretene Situation durch eine Logmeldung. |
- | Einheit | die jeweilige Einheit (W,kW,Wh,kWh) |
- | capacity | Bemessungsleistung des Wechselrichters gemäß Datenblatt, d.h. max. möglicher Output in Watt |
- | | (Die Angabe ist optional, wird aber dringend empfohlen zu setzen) |
-
-
-
-
-
- Beispiel:
- set <name> currentInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
-
- # Device STP5000 liefert PV-Werte. Die aktuell erzeugte Leistung im Reading "total_pac" (kW) und die erzeugte Gesamtenergie im
- Reading "etotal" (kWh). Die max. Leistung des Wechselrichters beträgt 5000 Watt.
-
-
-
-
-
- currentRadiationAPI
@@ -21043,7 +21002,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| | set <name> reset consumption <Tag> (z.B. set <name> reset consumption 08) |
| | 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) |
- | currentInverterSet | löscht das eingestellte Inverterdevice und korrespondierende Daten |
| energyH4TriggerSet | löscht die 4-Stunden Energie Triggerpunkte |
| inverterStringSet | löscht die Stringkonfiguration der Anlage |
| powerTriggerSet | löscht die Triggerpunkte für PV Erzeugungswerte |
@@ -22592,6 +22550,40 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
+
+ - setupInverterDev <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit> [capacity=<max. WR-Leistung>]
+
+ Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
+ Es kann auch ein Dummy Device mit entsprechenden Readings sein.
+ Die Werte mehrerer Inverterdevices führt man z.B. in einem Dummy Device zusammen und gibt dieses Device mit den
+ entsprechenden Readings an.
+ Die Angabe von capacity ist optional, wird aber zur Optimierung der Vorhersagegenauigkeit dringend empfohlen.
+
+
+
+
+
+ | pv | Reading welches die aktuelle PV-Erzeugung liefert |
+ | etotal | Reading welches die gesamte erzeugte PV-Energie liefert (ein stetig aufsteigender Zähler) |
+ | | Sollte des Reading die Vorgabe eines stetig aufsteigenden Zählers verletzen, behandelt |
+ | | SolarForecast diesen Fehler und meldet die aufgetretene Situation durch eine Logmeldung. |
+ | Einheit | die jeweilige Einheit (W,kW,Wh,kWh) |
+ | capacity | Bemessungsleistung des Wechselrichters gemäß Datenblatt, d.h. max. möglicher Output in Watt |
+ | | (Die Angabe ist optional, wird aber dringend empfohlen zu setzen) |
+
+
+
+
+
+ Beispiel:
+ attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000
+
+
+
+ Hinweis: Durch Löschen des Attributes werden ebenfalls die intern korrespondierenden Daten entfernt.
+
+
+
- setupMeterDev <Meter Device Name> gcon=<Readingname>:<Einheit> contotal=<Readingname>:<Einheit>
gfeedin=<Readingname>:<Einheit> feedtotal=<Readingname>:<Einheit>