diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 0e22c9039..e23c2664b 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -117,7 +117,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( - "0.30.0" => "05.04.2021 estimate readings to the minute in sub _calcSummaries ", + "0.30.0" => "05.04.2021 estimate readings to the minute in sub _calcSummaries, new setter energyH4Trigger ", "0.29.0" => "03.04.2021 new setter powerTrigger ", "0.28.0" => "03.04.2021 new attributes beam1FontColor, beam2FontColor, rename/new some readings ", "0.27.0" => "02.04.2021 additional readings ", @@ -164,6 +164,7 @@ my %hset = ( # Ha inverterStrings => { fn => \&_setinverterStrings }, currentInverterDev => { fn => \&_setinverterDevice }, currentMeterDev => { fn => \&_setmeterDevice }, + energyH4Trigger => { fn => \&_setenergyH4Trigger }, powerTrigger => { fn => \&_setpowerTrigger }, pvCorrectionFactor_05 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_06 => { fn => \&_setpvCorrectionFactor }, @@ -528,13 +529,14 @@ sub Set { "currentForecastDev:$fcd ". "currentInverterDev:textField-long ". "currentMeterDev:textField-long ". + "energyH4Trigger:textField-long ". "inverterStrings ". "modulePeakString ". "moduleTiltAngle ". "moduleDirection ". "powerTrigger:textField-long ". "pvCorrectionFactor_Auto:on,off ". - "reset:currentForecastDev,currentInverterDev,currentMeterDev,inverterStrings,powerTrigger,pvCorrection,pvHistory ". + "reset:currentForecastDev,currentInverterDev,currentMeterDev,energyH4Trigger,inverterStrings,powerTrigger,pvCorrection,pvHistory ". "writeHistory:noArg ". $cf ; @@ -684,6 +686,37 @@ sub _setpowerTrigger { ## no critic "not used" return; } +################################################################ +# Setter energyH4Trigger +################################################################ +sub _setenergyH4Trigger { ## no critic "not used" + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $opt = $paref->{opt}; + my $arg = $paref->{arg}; + + if(!$arg) { + return qq{The command "$opt" needs an argument !}; + } + + my ($a,$h) = parseParams ($arg); + + if(!$h) { + return qq{The syntax of "$opt" is not correct. Please consider the commandref.}; + } + + for my $key (keys %{$h}) { + if($key !~ /^[0-9]+(?:on|off)$/x || $h->{$key} !~ /^[0-9]+$/x) { + return qq{The key "$key" is invalid. Please consider the commandref.}; + } + } + + readingsSingleUpdate($hash, "energyH4Trigger", $arg, 1); + +return; +} + ################################################################ # Setter modulePeakString ################################################################ @@ -855,12 +888,17 @@ sub _setreset { ## no critic "not used" } if($prop eq "pvCorrection") { - deleteReadingspec ($hash, "pvCorrectionFactor_.*"); + deleteReadingspec ($hash, "pvCorrectionFactor_.*"); return; } if($prop eq "powerTrigger") { - deleteReadingspec ($hash, "powerTrigger.*"); + deleteReadingspec ($hash, "powerTrigger.*"); + return; + } + + if($prop eq "energyH4Trigger") { + deleteReadingspec ($hash, "energyH4Trigger.*"); return; } @@ -1663,9 +1701,7 @@ sub _transferInverterValues { $data{$type}{$name}{current}{generation} = $pv; # Hilfshash Wert current generation Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251 push @{$data{$type}{$name}{current}{genslidereg}}, $pv; # Schieberegister PV Erzeugung - while (scalar @{$data{$type}{$name}{current}{genslidereg}} > $defslidenum) { - shift @{$data{$type}{$name}{current}{genslidereg}}; - } + limitArray ($data{$type}{$name}{current}{genslidereg}, $defslidenum); my $etuf = $etunit =~ /^kWh$/xi ? 1000 : 1; my $etotal = ReadingsNum ($indev, $edread, 0) * $etuf; # Erzeugung total (Wh) @@ -1743,8 +1779,8 @@ sub _transferMeterValues { my $gcuf = $gcunit =~ /^kW$/xi ? 1000 : 1; my $co = ReadingsNum ($medev, $gc, 0) * $gcuf; # aktueller Bezug (W) - push @$daref, "Current_GridConsumption<>".$co." W"; - $data{$type}{$name}{current}{gridconsumption} = $co; # Hilfshash Wert current grid consumption Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251 + push @$daref, "Current_GridConsumption<>".(int $co)." W"; + $data{$type}{$name}{current}{gridconsumption} = int $co; # Hilfshash Wert current grid consumption Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251 my $ctuf = $ctunit =~ /^kWh$/xi ? 1000 : 1; my $gctotal = ReadingsNum ($medev, $gt, 0) * $ctuf; # Bezug total (Wh) @@ -1804,20 +1840,59 @@ sub _evaluateThresholds { my $daref = $paref->{daref}; my $pt = ReadingsVal($name, "powerTrigger", ""); + my $eh4t = ReadingsVal($name, "energyH4Trigger", ""); - return if(!$pt); + if ($pt) { + my $aaref = CurrentVal ($hash, "genslidereg", ""); + my @aa = (); + @aa = @{$aaref} if (ref $aaref eq "ARRAY"); + + if (scalar @aa >= $defslidenum) { + $paref->{taref} = \@aa; + $paref->{tname} = "powerTrigger"; + $paref->{tholds} = $pt; + + __evaluateArray ($paref); + } + } - my $aaref = CurrentVal ($hash, "genslidereg", ""); - my @aa = (); - @aa = @{$aaref} if (ref $aaref eq "ARRAY"); + if ($eh4t) { + my $aaref = CurrentVal ($hash, "h4fcslidereg", ""); + my @aa = (); + @aa = @{$aaref} if (ref $aaref eq "ARRAY"); + + if (scalar @aa >= $defslidenum) { + $paref->{taref} = \@aa; + $paref->{tname} = "energyH4Trigger"; + $paref->{tholds} = $eh4t; + + __evaluateArray ($paref); + } + } - return if(scalar @aa < $defslidenum); + delete $paref->{taref}; + delete $paref->{tname}; + delete $paref->{tholds}; - my $gen1 = $aa[0]; - my $gen2 = $aa[1]; - my $gen3 = $aa[2]; +return; +} + +################################################################ +# Threshold-Array auswerten und Readings vorbereiten +################################################################ +sub __evaluateArray { + my $paref = shift; + my $name = $paref->{name}; + my $daref = $paref->{daref}; + my $taref = $paref->{taref}; # Referenz zum Threshold-Array + my $tname = $paref->{tname}; # Thresholdname, z.B. powerTrigger + my $tholds = $paref->{tholds}; # Triggervorgaben, z.B. aus Reading powerTrigger + + my $gen1 = @$taref[0]; + my $gen2 = @$taref[1]; + my $gen3 = @$taref[2]; - my ($a,$h) = parseParams ($pt); + my ($a,$h) = parseParams ($tholds); for my $key (keys %{$h}) { my ($knum,$cond) = $key =~ /^([0-9]+)(on|off)$/x; @@ -1825,13 +1900,13 @@ sub _evaluateThresholds { if($cond eq "on" && $gen1 > $h->{$key}) { next if($gen2 < $h->{$key}); next if($gen3 < $h->{$key}); - push @$daref, "powerTrigger_${knum}<>on" if(ReadingsVal($name, "powerTrigger_${knum}", "off") eq "off"); + push @$daref, "${tname}_${knum}<>on" if(ReadingsVal($name, "${tname}_${knum}", "off") eq "off"); } if($cond eq "off" && $gen1 < $h->{$key}) { next if($gen2 > $h->{$key}); next if($gen3 > $h->{$key}); - push @$daref, "powerTrigger_${knum}<>off" if(ReadingsVal($name, "powerTrigger_${knum}", "on") eq "on"); + push @$daref, "${tname}_${knum}<>off" if(ReadingsVal($name, "${tname}_${knum}", "on") eq "on"); } } @@ -1898,9 +1973,12 @@ sub _calcSummaries { } for my $th (1..24) { - $todaySum->{PV} += ReadingsNum($name, "Today_Hour".sprintf("%02d",$th)."_PVforecast", 0);; + $todaySum->{PV} += ReadingsNum($name, "Today_Hour".sprintf("%02d",$th)."_PVforecast", 0); } + push @{$data{$type}{$name}{current}{h4fcslidereg}}, int $next4HoursSum->{PV}; # Schieberegister 4h Summe Forecast + limitArray ($data{$type}{$name}{current}{h4fcslidereg}, $defslidenum); + push @$daref, "NextHours_Sum01_PVforecast<>".(int $next1HoursSum->{PV})." Wh"; push @$daref, "NextHours_Sum02_PVforecast<>".(int $next2HoursSum->{PV})." Wh"; push @$daref, "NextHours_Sum03_PVforecast<>".(int $next3HoursSum->{PV})." Wh"; @@ -3448,6 +3526,28 @@ sub checkStringConfig { return $sc; } +################################################################ +# Array auf eine festgelegte Anzahl Elemente beschränken, +# Das älteste Element wird entfernt +# +# $href = Referenz zum Array +# $limit = die Anzahl Elemente auf die gekürzt werden soll +# (default 3) +# +################################################################ +sub limitArray { + my $href = shift; + my $limit = shift // 3; + + return if(ref $href ne "ARRAY"); + + while (scalar @{$href} > $limit) { + shift @{$href}; + } + +return; +} + ################################################################ # einen Zeitstring YYYY-MM-TT hh:mm:ss in einen Unix # Timestamp umwandeln @@ -3655,10 +3755,11 @@ return $def; # Usage: # CurrentVal ($hash, $key, $def) # -# $key: generation - aktuelle PV Erzeugung -# genslidereg - Schieberegister PV Erzeugung (Array) -# gridconsumption - aktueller Netzbezug -# $def: Defaultwert +# $key: generation - aktuelle PV Erzeugung +# genslidereg - Schieberegister PV Erzeugung (Array) +# h4fcslidereg - Schieberegister 4h PV Forecast (Array) +# gridconsumption - aktueller Netzbezug +# $def: Defaultwert # ################################################################ sub CurrentVal { @@ -3822,6 +3923,27 @@ werden weitere SolarForecast Devices zugeordnet.
+ +
+