From 555be1b4da23baf84d1901d9a39851914545ca69 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Tue, 17 Oct 2023 19:45:58 +0000 Subject: [PATCH] 76_SolarForecast: allow key 'noshow' more values, KI improves git-svn-id: https://svn.fhem.de/fhem/trunk@28063 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/76_SolarForecast.pm | 156 ++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 25 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 8618608e9..06913a300 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - feature: 76_SolarForecast: allow key 'noshow' more values, KI improves - change: 22_HOMEMODE: change url for IP check - bugfix: 14_Hideki.pm: fixed partial carp error - feature: 70_ESCVP21net: add reading stateP for on/off diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 4222b2fea..8030b41f6 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -144,6 +144,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.0.5" => "11.10.2023 new sub _aiGetSpread for estimate AI results stepwise, allow key 'noshow' values 0,1,2,3 ", "1.0.4" => "10.10.2023 fix: print always Log in _calcCaQ* subroutines even if calaculated factors are equal ". "new consumer attr key 'noshow' ", "1.0.3" => "08.10.2023 change graphic header PV/CO detail, new attr graphicHeaderOwnspec, internal code changes ". @@ -7759,12 +7760,12 @@ sub _calcTodayPVdeviation { my $diff = $pvfc - $pvre; - if($pvre) { + if ($pvre) { my $dp = sprintf "%.2f" , (100 * $diff / $pvre); $data{$type}{$name}{circular}{99}{tdayDvtn} = $dp; push @$daref, "Today_PVdeviation<>". $dp. " %"; - push @$daref, "Today_PVreal<>". $pvre." Wh"; + push @$daref, "Today_PVreal<>". (sprintf "%.0f", $pvre)." Wh"; } return; @@ -9220,7 +9221,7 @@ sub _graphicConsumerLegend { my $tro = 0; for my $c (@consumers) { - next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + next if(isConsumerNoshow ($hash, $c) =~ /^[12]$/xs); # Consumer ausblenden my $caicon = $paref->{caicon}; # Consumer AdviceIcon my ($cname, $dswname) = getCDnames ($hash, $c); # Consumer und Switch Device Name @@ -10059,7 +10060,12 @@ END0 if ($flowgcons) { my $type = $paref->{type}; - @consumers = sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}; # definierte Verbraucher ermitteln + + for my $c (sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}) { # definierte Verbraucher ermitteln + next if(isConsumerNoshow ($hash, $c) =~ /^[13]$/xs); # ausgeblendete Consumer nicht berücksichtigen + push @consumers, $c; + } + $consumercount = scalar @consumers; if ($consumercount % 2) { @@ -10072,11 +10078,9 @@ END0 $pos_left = $consumer_start + 15; for my $c (@consumers) { - next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden - - my $calias = ConsumerVal ($hash, $c, "alias", ""); # Name des Consumerdevices + my $calias = ConsumerVal ($hash, $c, "alias", ""); # Name des Consumerdevices $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); - my $cicon = __substConsumerIcon ($hash, $c, $currentPower); # Icon des Consumerdevices + my $cicon = __substConsumerIcon ($hash, $c, $currentPower); # Icon des Consumerdevices $cc_dummy -= $currentPower; $ret .= ''; @@ -10150,8 +10154,6 @@ END3 } for my $c (@consumers) { - next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden - my $power = ConsumerVal ($hash, $c, "power", 0); my $rpcurr = ConsumerVal ($hash, $c, "rpcurr", ""); # Reading für akt. Verbrauch angegeben ? $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); @@ -10200,8 +10202,6 @@ END3 $pos_left = ($consumer_start * 2) - 50; # -XX -> Start Lage Consumer Beschriftung for my $c (@consumers) { - next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden - $currentPower = sprintf "%.1f", ReadingsNum($name, "consumer${c}_currentPower", 0); $currentPower =~ s/\.0$// if (int($currentPower) > 0); # .0 am Ende interessiert nicht my $consumerTime = ConsumerVal ($hash, $c, "remainTime", ""); # Restlaufzeit @@ -11194,14 +11194,109 @@ sub aiGetResult { ## no critic "not used" } ); }; - - if ($@) { + + if ($@) { Log3 ($name, 1, "$name - aiGetResult ERROR: $@"); return $@; } if (defined $pvaifc) { - debugLog ($paref, 'aiData', qq{result AI: pvaifc: $pvaifc (hod: $hod, rad1h: $rad1h, wcc: $wcc, wrp: $rbin, temp: $tbin)}); + debugLog ($paref, 'aiData', qq{accurate result AI: pvaifc: $pvaifc (hod: $hod, rad1h: $rad1h, wcc: $wcc, wrp: $rbin, temp: $tbin)}); + return ('', $pvaifc); + } + + my $msg = 'no decition delivered'; + + ($msg, $pvaifc) = _aiGetSpread ( { hash => $hash, + name => $name, + type => $type, + rad1h => $rad1h, + temp => $tbin, + wcc => $cbin, + wrp => $rbin, + hod => $hod, + dtree => $dtree, + debug => $paref->{debug} + } + ); + + if (defined $pvaifc) { + return ('', $pvaifc); + } + +return $msg; +} + +################################################################ +# AI Ergebnis aus einer positiven und negativen +# rad1h-Abweichung schätzen +################################################################ +sub _aiGetSpread { + my $paref = shift; + my $rad1h = $paref->{rad1h}; + my $temp = $paref->{temp}; + my $wcc = $paref->{wcc}; + my $wrp = $paref->{wrp}; + my $hod = $paref->{hod}; + my $dtree = $paref->{dtree}; + + my $dtn = 50; # positive und negative rad1h Abweichung testen mit Schrittweite "$step" + my $step = 10; + + my ($pos, $neg, $p, $n); + + debugLog ($paref, 'aiData', qq{no accurate result AI found with initial value "$rad1h"}); + debugLog ($paref, 'aiData', qq{test AI estimation with variance "$dtn", positive/negative step "$step"}); + + for ($p = $rad1h; $p <= $rad1h + $dtn; $p += $step) { + $p = sprintf "%.2f", $p; + + eval { $pos = $dtree->get_result (attributes => { rad1h => $p, + temp => $temp, + wcc => $wcc, + wrp => $wrp, + hod => $hod + } + ); + }; + + if ($@) { + return $@; + } + + if ($pos) { + debugLog ($paref, 'aiData', qq{AI estimation with test value "$p": $pos}); + last; + } + } + + for ($n = $rad1h; $n >= $rad1h - $dtn; $n -= $step) { + last if($n <= 0); + $n = sprintf "%.2f", $n; + + eval { $neg = $dtree->get_result (attributes => { rad1h => $n, + temp => $temp, + wcc => $wcc, + wrp => $wrp, + hod => $hod + } + ); + }; + + if ($@) { + return $@; + } + + if ($neg) { + debugLog ($paref, 'aiData', qq{AI estimation with test value "$n": $neg}); + last; + } + } + + my $pvaifc = $pos && $neg ? sprintf "%.0f", (($pos + $neg) / 2) : undef; + + if (defined $pvaifc) { + debugLog ($paref, 'aiData', qq{appreciated result AI: pvaifc: $pvaifc (hod: $hod, wcc: $wcc, wrp: $wrp, temp: $temp)}); return ('', $pvaifc); } @@ -12929,8 +13024,11 @@ return 0; ################################################################ # Consumer $c in Grafik ausblenden (1) oder nicht (0) -# default: $noshow=0 -################################################################ isConsumerNoshow ($hash, $c); +# 0 - nicht aublenden (default) +# 1 - ausblenden +# 2 - nur in Consumerlegende ausblenden +# 3 - nur in Flowgrafik ausblenden +################################################################ sub isConsumerNoshow { my $hash = shift; my $c = shift; @@ -12947,7 +13045,11 @@ sub isConsumerNoshow { $noshow = ReadingsNum ($dev, $rdg, 0); } - + + if ($noshow !~ /^[0123]$/xs) { # nue Ergebnisse 0..3 zulassen + $noshow = 0; + } + return $noshow; } @@ -14720,7 +14822,7 @@ to ensure that the system configuration is correct. The recommended autocorrection method is on_complex or on_complex_ai.

Model ForecastSolarAPI:
- The recommended autocorrection method is on_simple. + The recommended autocorrection method is on_complex.
@@ -15375,9 +15477,11 @@ to ensure that the system configuration is correct. noshow Hide or show consumers in graphic (optional). 0 - the consumer is displayed (default) 1 - the consumer is hidden + 2 - the consumer is hidden in the consumer legend + 3 - the consumer is hidden in the flow chart [Device:]Reading - Reading in the consumer or optionally an alternative device. - If the reading has the value "0" or is not present, the consumer is displayed. - If the reading has the value "1", the consumer is hidden. + If the reading has the value 0 or is not present, the consumer is displayed. + The effect of the possible reading values 1, 2 and 3 is as described.
@@ -16533,7 +16637,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Die empfohlene Autokorrekturmethode ist on_complex bzw. on_complex_ai.

Model ForecastSolarAPI:
- Die empfohlene Autokorrekturmethode ist on_simple. + Die empfohlene Autokorrekturmethode ist on_complex.
@@ -17185,9 +17289,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. noshow Verbraucher in Grafik ausblenden oder einblenden (optional). 0 - der Verbraucher wird eingeblendet (default) 1 - der Verbraucher wird ausgeblendet - [Device:]Reading - Reading im Verbraucher oder optional einem alternativen Device. - Hat das Reading den Wert "0" oder ist nicht vorhanden, wird der Verbraucher eingeblendet. - Hat das Reading den Wert "1", wird der Verbraucher ausgeblendet. + 2 - der Verbraucher wird in der Verbraucherlegende ausgeblendet + 3 - der Verbraucher wird in der Flußgrafik ausgeblendet + [Device:]Reading - Reading im Verbraucher oder optional einem alternativen Device. + Hat das Reading den Wert 0 oder ist nicht vorhanden, wird der Verbraucher eingeblendet. + Die Wirkung der möglichen Readingwerte 1, 2 und 3 ist wie beschrieben.