From 538bdbfe15316fc9de5fd0f37cadedc6117bf5a6 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Mon, 3 Jun 2024 18:43:25 +0000 Subject: [PATCH] 76_SolarForecast: set currentInverterDev to attr setupInverterDev git-svn-id: https://svn.fhem.de/fhem/trunk@28941 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/76_SolarForecast.pm | 287 ++++++++++--------- fhem/contrib/DS_Starter/76_SolarForecast.pm | 290 ++++++++++---------- 3 files changed, 282 insertions(+), 297 deletions(-) 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

    @@ -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>