diff --git a/contrib/DS_Starter/76_SolarForecast.pm b/contrib/DS_Starter/76_SolarForecast.pm index 53f11052a..c3b899eb5 100644 --- a/contrib/DS_Starter/76_SolarForecast.pm +++ b/contrib/DS_Starter/76_SolarForecast.pm @@ -120,6 +120,9 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "0.61.0 "=> "15.05.2022 limit PV forecast to inverter capacity ", + "0.60.1 "=> "15.05.2022 consumerHash -> new key avgruntime, don't modify mintime by avgruntime by default anymore ". + "debug switch conditions ", "0.60.0 "=> "14.05.2022 new key 'swoncond' in consumer attributes ", "0.59.0 "=> "01.05.2022 new attr createTomorrowPVFcReadings ", "0.58.0 "=> "20.04.2022 new setter consumerImmediatePlanning, functions isConsumerOn isConsumerOff ", @@ -2499,11 +2502,13 @@ sub _transferInverterValues { my ($a,$h) = parseParams ($indev); $indev = $a->[0] // ""; return if(!$indev || !$defs{$indev}); - + my $type = $hash->{TYPE}; my ($pvread,$pvunit) = split ":", $h->{pv}; # Readingname/Unit für aktuelle PV Erzeugung - my ($edread,$etunit) = split ":", $h->{etotal}; # Readingname/Unit für Energie total + my ($edread,$etunit) = split ":", $h->{etotal}; # Readingname/Unit für Energie total (PV Erzeugung) + + $data{$type}{$name}{current}{invertercapacity} = $h->{capacity} if($h->{capacity}); # optionale Angabe max. WR-Leistung return if(!$pvread || !$edread); @@ -2865,22 +2870,25 @@ sub _manageConsumerData { my $runhours = 0; my $dnum = 0; - for my $n (sort{$a<=>$b} keys %{$data{$type}{$name}{pvhist}}) { # gemessenen Verbrauch ermitteln - my $csme = HistoryVal ($hash, $n, 99, "csme${c}", 0); - next if(!$csme); + for my $n (sort{$a<=>$b} keys %{$data{$type}{$name}{pvhist}}) { # Betriebszeit und gemessenen Verbrauch ermitteln + my $csme = HistoryVal ($hash, $n, 99, "csme${c}", 0); my $hours = HistoryVal ($hash, $n, 99, "hourscsme${c}", 0); + next if(!$hours); $consumerco += $csme; $runhours += $hours; $dnum++; } - - if ($dnum) { - $data{$type}{$name}{consumers}{$c}{avgenergy} = ceil ($consumerco/$dnum); # Durchschnittsverbrauch eines Tages aus History - my $mintime = ConsumerVal ($hash, $c, "mintime", $defmintime); - my $avgruntime = (ceil($runhours/$dnum)) * 60; # Durchschnittslaufzeit in Minuten - $mintime = $avgruntime < $mintime ? $mintime : $avgruntime; - $data{$type}{$name}{consumers}{$c}{mintime} = $mintime; + + if ($dnum) { + if($consumerco) { + $data{$type}{$name}{consumers}{$c}{avgenergy} = ceil ($consumerco/$dnum); # Durchschnittsverbrauch eines Tages aus History + } + else { + delete $data{$type}{$name}{consumers}{$c}{avgenergy}; + } + + $data{$type}{$name}{consumers}{$c}{avgruntime} = (ceil($runhours/$dnum)) * 60; # Durchschnittslaufzeit in Minuten } $paref->{consumer} = $c; @@ -3361,6 +3369,7 @@ sub __switchConsumer { my $pstate = ConsumerVal ($hash, $c, "planstate", ""); my $cname = ConsumerVal ($hash, $c, "name", ""); # Consumer Device Name my $calias = ConsumerVal ($hash, $c, "alias", ""); # Consumer Device Alias + my $debug = AttrVal ($name, "debug", 0); ## Ist Verbraucher empfohlen ? ################################ @@ -3373,9 +3382,19 @@ sub __switchConsumer { ## Verbraucher einschalten ############################ - my $oncom = ConsumerVal ($hash, $c, "oncom", ""); # Set Command für "on" - my $auto = ConsumerVal ($hash, $c, "auto", 1); - my $swoncond = isAddSwitchOnCond ($hash, $c); # zusätzliche Switch on Bedingung + my $oncom = ConsumerVal ($hash, $c, "oncom", ""); # Set Command für "on" + my $auto = ConsumerVal ($hash, $c, "auto", 1); + my ($swoncond,$info,$err) = isAddSwitchOnCond ($hash, $c); # zusätzliche Switch on Bedingung + + Log3 ($name, 1, "$name - $err") if($err); + + if($debug) { # nur für Debugging + Log (1, qq{DEBUG> $name - Parameters for switch on decision consumer "$c": }. + qq{swoncond: $swoncond, auto mode: $auto, on-command: $oncom, }. + qq{planning state: $pstate, start timestamp: }.($startts ? $startts : "undef").", ". + qq{timestamp: $t} + ); + } if($swoncond && $auto && $oncom && $pstate =~ /planned|priority/xs && $startts && $t >= $startts) { # Verbraucher Start ist geplant && Startzeit überschritten @@ -3418,6 +3437,15 @@ sub __switchConsumer { ## Verbraucher ausschalten ############################ my $offcom = ConsumerVal ($hash, $c, "offcom", ""); # Set Command für "off" + + if($debug) { # nur für Debugging + Log (1, qq{DEBUG> $name - Parameters for switch off decision consumer "$c": }. + qq{auto mode: $auto, off-command: $offcom, }. + qq{planning state: $pstate, stop timestamp: }.($stopts ? $stopts : "undef").", ". + qq{timestamp: $t} + ); + } + if($auto && $offcom && $pstate !~ /switched\soff/xs && $stopts && $t >= $stopts) { # Verbraucher nicht switched off && Stopzeit überschritten CommandSet(undef,"$cname $offcom"); @@ -6134,7 +6162,14 @@ sub calcPVforecast { $data{$type}{$name}{current}{allstringspeak} = $peaksum; # insgesamt installierte Peakleistung in W $pvsum *= $hc; # Korrekturfaktor anwenden - $pvsum = $peaksum if($pvsum > $peaksum); + $pvsum = $peaksum if($pvsum > $peaksum); # Vorhersage nicht größer als die Summe aller PV-Strings Peak + + my $invcapacity = CurrentVal ($hash, "invertercapacity", 0); # Max. Leistung des Invertrs + + if ($invcapacity && $pvsum > $invcapacity) { + $pvsum = $invcapacity + ($invcapacity * 0.01); # PV Vorhersage auf WR Kapazität zzgl. 1% begrenzen + Log3 ($name, 4, "$name - PV forecast limited to $pvsum Watt due to inverter capacity"); + } my $logao = qq{}; $paref->{pvsum} = $pvsum; @@ -7148,18 +7183,23 @@ return; ################################################################ # Funktion liefert "1" wenn die zusätzliche Einschaltbedingung # aus dem Schlüssel "swoncond" im Consumer Attribut wahr ist +# +# +# +# ################################################################ sub isAddSwitchOnCond { my $hash = shift; - my $c = shift; + my $c = shift; + + my $info = q{}; + my $err = q{}; my $dswoncond = ConsumerVal ($hash, $c, "dswoncond", ""); # Device zur Lieferung einer zusätzlichen Einschaltbedingung if($dswoncond && !$defs{$dswoncond}) { - my $name = $hash->{NAME}; - my $err = qq{ERROR - the device "$dswoncond" doesn't exist! Check the key "swoncond" in attribute "consumer${c}"}; - Log3 ($name, 1, "$name - $err"); - return; + $err = qq{ERROR - the device "$dswoncond" doesn't exist! Check the key "swoncond" in attribute "consumer${c}"}; + return (0, $info, $err); } my $rswoncond = ConsumerVal ($hash, $c, "rswoncond", ""); # Reading zur Lieferung einer zusätzlichen Einschaltbedingung @@ -7167,10 +7207,12 @@ sub isAddSwitchOnCond { my $condstate = ReadingsVal ($dswoncond, $rswoncond, ""); if ($condstate =~ m/^$swoncondregex$/x) { - return 1; + return (1, $info, $err); } + + $info = qq{The device "$dswoncond", reading "$rswoncond" doen't match the Regex "$swoncondregex"}; -return; +return (0, $info, $err); } ############################################################################### @@ -7359,6 +7401,7 @@ return $def; # powerbatout - Batterie Entladeleistung # temp - aktuelle Außentemperatur # tomorrowconsumption - Verbrauch des kommenden Tages +# invertercapacity - Bemessungsleistung der Wechselrichters (max. W) # $def: Defaultwert # ############################################################################# @@ -7401,6 +7444,7 @@ return $def; # upcurr - Unit des aktuellen Verbrauchs # avgenergy - initialer / gemessener Durchschnittsverbrauch # eines Tages +# avgruntime - durchschnittliche Einschalt- bzw. Zykluszeit (Minuten) # epieces - prognostizierte Energiescheiben (Hash) # isConsumptionRecommended - ist Verbrauch empfohlen ? # dswoncond - Device zur Lieferung einer zusätzliche Einschaltbedingung @@ -7590,12 +7634,13 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
auto | Reading im Verbraucherdevice welches das Schalten des Verbrauchers freigibt bzw. blockiert (optional) |
Readingwert = 1 - Schalten freigegeben (default), 0: Schalten blockiert | |
pcurr | Reading welches den aktuellen Energieverbrauch (z.B. Schaltdose mit Energiemessung) liefert und Einheit (W/kW) (optional) |
etotal | Reading:Einheit (Wh/kWh), welches die Summe der verbrauchten Energie liefert (optional) |
etotal | Reading:Einheit (Wh/kWh) des Consumer Device, welches die Summe der verbrauchten Energie liefert (optional) |
:<Schwellenwert> (Wh) - optionaler Energieverbrauch pro Stunde ab dem der Verbraucher als aktiv gewertet wird. | |
swoncond | zusätzliche Bedingung die erfüllt sein muß um den Verbraucher einzuschalten (optional). |
Device - Device zur Lieferung der zusätzlichen Einschaltbedingung |