From 75075f076ec94c31444247e105d6b7a3d8165730 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Mon, 21 Apr 2025 21:12:59 +0000 Subject: [PATCH] 76_SolarForecast: Version 1.51.2 git-svn-id: https://svn.fhem.de/fhem/trunk@29887 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/76_SolarForecast.pm | 358 ++++++++++++++++++---------------- 2 files changed, 192 insertions(+), 167 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 0095e2585..7b603d11f 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: Version 1.51.2 - bugfix: 76_SMAInverter.pm: fix warning Versions History - feature: 76_SolarForecast: Version 1.51.1 - change: 74_AutomowerConnect: Cref improved, automowerconnect.js fix third diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 8d810cd59..166069241 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -160,6 +160,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.51.2" => "21.04.2025 Attributes obsolet: graphicHeaderShow replaced by graphicSelect, Value 'none' of consumerControl->showLegend deleted ", "1.51.1" => "20.04.2025 consumer: interruptable, swoncond, swoffcond, spignorecond can be perl code enclosed by {..} ". "check key is valid in plantControl, aiControl, flowGraphicControl, consumerControl, setupMeterDev ". "setupOtherProducer, setupInverterDev, setupBatteryDev, consumer ". @@ -578,6 +579,25 @@ my @rconfigs = qw( pvCorrectionFactor_Auto powerTrigger energyH4Trigger ); + # Grafik Selektionsoptionen +my @gsopt = qw ( both + both_noHead + both_noCons + both_noHead_noCons + swap + swap_noHead + swap_noCons + swap_noHead_noCons + flow + flow_noHead + flow_noCons + flow_noHead_noCons + forecast + forecast_noHead + forecast_noCons + forecast_noHead_noCons + none + ); # Anlagenkonfiguration: maßgebliche Attribute my @aconfigs = qw( aiControl consumerControl @@ -596,7 +616,7 @@ my @aconfigs = qw( aiControl graphicBeam1Color graphicBeam2Color graphicBeam3Color graphicBeam4Color graphicBeam5Color graphicBeam6Color graphicBeam1FontColor graphicBeam2FontColor graphicBeam3FontColor graphicBeam4FontColor graphicBeam5FontColor graphicBeam6FontColor graphicEnergyUnit graphicHeaderOwnspec graphicHeaderOwnspecValForm - graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle + graphicHeaderDetail graphicHistoryHour graphicHourCount graphicHourStyle graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather graphicSpaceSize graphicWeatherColor graphicWeatherColorNight plantControl @@ -605,27 +625,27 @@ my @aconfigs = qw( aiControl setupRoofTops ); -for my $cn (1..MAXCONSUMER) { - $cn = sprintf "%02d", $cn; - push @aconfigs, "consumer${cn}"; # Anlagenkonfiguration: add Consumer Attribute - push @dd, "consumerSwitching${cn}"; # ctrlDebug: add specific Consumer -} + for my $cn (1..MAXCONSUMER) { + $cn = sprintf "%02d", $cn; + push @aconfigs, "consumer${cn}"; # Anlagenkonfiguration: add Consumer Attribute + push @dd, "consumerSwitching${cn}"; # ctrlDebug: add specific Consumer + } -for my $bn (1..MAXBATTERIES) { - $bn = sprintf "%02d", $bn; - push @aconfigs, "setupBatteryDev${bn}"; # Anlagenkonfiguration: add Battery Attribute - push @aconfigs, "ctrlBatSocManagement${bn}"; -} + for my $bn (1..MAXBATTERIES) { + $bn = sprintf "%02d", $bn; + push @aconfigs, "setupBatteryDev${bn}"; # Anlagenkonfiguration: add Battery Attribute + push @aconfigs, "ctrlBatSocManagement${bn}"; + } -for my $in (1..MAXINVERTER) { - $in = sprintf "%02d", $in; - push @aconfigs, "setupInverterDev${in}"; # Anlagenkonfiguration: add Inverter Attribute -} + for my $in (1..MAXINVERTER) { + $in = sprintf "%02d", $in; + push @aconfigs, "setupInverterDev${in}"; # Anlagenkonfiguration: add Inverter Attribute + } -for my $pn (1..MAXPRODUCER) { - $pn = sprintf "%02d", $pn; - push @aconfigs, "setupOtherProducer${pn}"; # Anlagenkonfiguration: add Producer Attribute -} + for my $pn (1..MAXPRODUCER) { + $pn = sprintf "%02d", $pn; + push @aconfigs, "setupOtherProducer${pn}"; # Anlagenkonfiguration: add Producer Attribute + } my $allwidgets = 'icon|sortable|uzsu|knob|noArg|time|text|slider|multiple|select|bitfield|widgetList|colorpicker'; @@ -1531,7 +1551,8 @@ sub Initialize { } my $allcs = join ",", @allc; - my $dm = 'none,'.join ",", sort @dd; + my $dm = 'none,'.join ",", sort @dd; # Optionen der Debugselektion + my $gol = join ",", @gsopt; # Optionen der Grafikselektion $hash->{DefFn} = \&Define; $hash->{UndefFn} = \&Undef; @@ -1566,12 +1587,11 @@ sub Initialize { "graphicHeaderOwnspec:textField-long ". "graphicHeaderOwnspecValForm:textField-long ". "graphicHeaderDetail:multiple-strict,all,co,pv,own,status ". - "graphicHeaderShow:1,0 ". "graphicHistoryHour:slider,0,1,23 ". "graphicHourCount:slider,4,1,24 ". "graphicHourStyle ". "graphicLayoutType:single,double,diff ". - "graphicSelect:both,flow,forecast,none ". + "graphicSelect:$gol ". "graphicShowDiff:no,top,bottom ". "graphicShowNight:1,0,01 ". "graphicShowWeather:1,0 ". @@ -1603,8 +1623,8 @@ sub Initialize { ########################################################################################################################## #my $av = 'obsolete#-#use#attr#plantControl#instead'; #my $av1 = 'obsolete#-#will#be#deleted#soon'; - #my $av2 = 'obsolete#-#use#attr#consumerControl#instead'; - #$hash->{AttrList} .= " affectBatteryPreferredCharge:$av "; + my $av2 = 'obsolete#-#use#attr#graphicSelect#instead'; + $hash->{AttrList} .= " graphicHeaderShow:$av2 "; ########################################################################################################################## $hash->{FW_hideDisplayName} = 1; # Forum 88667 @@ -2742,21 +2762,6 @@ sub Get { my $type = $hash->{TYPE}; - my @ho = qw (both - both_noHead - both_noCons - both_noHead_noCons - flow - flow_noHead - flow_noCons - flow_noHead_noCons - forecast - forecast_noHead - forecast_noCons - forecast_noHead_noCons - none - ); - my @pha = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{pvhist}}; my @cla = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{circular}}; my @vcm = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{consumers}}; @@ -2765,7 +2770,7 @@ sub Get { my @vpn = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$name}{producers}}; my @vst = sort keys %{$data{$name}{strings}}; - my $hol = join ",", @ho; + my $gol = join ",", @gsopt; # Optionen der Grafikselektion my $pvl = join ",", @pha; my $cll = join ",", @cla; my $cml = join ",", @vcm; @@ -2784,7 +2789,7 @@ sub Get { "dwdCatalog ". "forecastQualities:noArg ". "ftuiFramefiles:noArg ". - "html:$hol ". + "html:$gol ". "nextHours:noArg ". "pvCircular:#,$cll ". "pvHistory:#,exportToCsv,$pvl ". @@ -6014,15 +6019,15 @@ sub Attr { # } #} - #if ($cmd eq 'set' && $aName =~ /^consumerAdviceIcon$/) { - # my $msg = "The attribute $aName is replaced by 'consumerControl'."; - # if (!$init_done) { - # Log3 ($name, 1, "$name - $msg"); - # } - # else { - # return $msg; - # } - #} + if ($cmd eq 'set' && $aName =~ /^graphicHeaderShow$/) { + my $msg = "The attribute $aName is replaced by 'graphicSelect'."; + if (!$init_done) { + Log3 ($name, 1, "$name - $msg"); + } + else { + return $msg; + } + } #if ($cmd eq 'set' && $aName =~ /^affectSolCastPercentile$/) { # my $msg1 = "The attribute $aName is obsolete and will be deleted soon. Please press 'save config' when restart is finished."; @@ -6386,10 +6391,10 @@ sub _attrconsumerControl { ## no critic "not used" my $cmd = $paref->{cmd}; my $valid = { - adviceIcon => { comp => '.*', act => 0 }, - detailLink => { comp => '(0|1)', act => 0 }, - dummyIcon => { comp => '.*', act => 0 }, - showLegend => { comp => '(none|icon_top|icon_bottom|text_top|text_bottom)', act => 0 }, + adviceIcon => { comp => '.*', act => 0 }, + detailLink => { comp => '(0|1)', act => 0 }, + dummyIcon => { comp => '.*', act => 0 }, + showLegend => { comp => '(icon_top|icon_bottom|text_top|text_bottom)', act => 0 }, }; for my $av (keys %{$valid}) { @@ -14107,16 +14112,12 @@ sub entryGraphic { lotype => AttrVal ($name, 'graphicLayoutType', 'double'), kw => AttrVal ($name, 'graphicEnergyUnit', 'Wh'), height => AttrNum ($name, 'graphicBeamHeightLevel1', BHEIGHTLEVEL), - width => $width, fsize => AttrNum ($name, 'graphicSpaceSize', 24), - layersync => $layersync, # Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen - show_night => $show_night, # alle Balken (Spalten) anzeigen ? show_diff => AttrVal ($name, 'graphicShowDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen weather => AttrNum ($name, 'graphicShowWeather', 1), # Wetter Icons anzeigen colorw => AttrVal ($name, 'graphicWeatherColor', WTHCOLDDEF), # Wetter Icon Farbe Tag colorwn => AttrVal ($name, 'graphicWeatherColorNight', WTHCOLNDEF), # Wetter Icon Farbe Nacht wlalias => AttrVal ($name, 'alias', $name), - sheader => AttrNum ($name, 'graphicHeaderShow', 1), # Anzeigen des Grafik Headers hdrDetail => AttrVal ($name, 'graphicHeaderDetail', 'all'), # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten clegendpos => CurrentVal ($name, 'showLegend', 'icon_top'), # Lage und Art Cunsumer Legende clink => CurrentVal ($name, 'detailLink', 1), # Link zur Detailansicht des Verbrauchers @@ -14134,38 +14135,30 @@ sub entryGraphic { genpvdva => CurrentVal ($name, 'genPVdeviation', 'daily'), # Methode der Abweichungsberechnung lang => getLang ($hash), debug => getDebug ($hash), # Debug Module + width => $width, + layersync => $layersync, # Zeitsynchronisation zwischen Ebene 1 und den folgenden Balkengrafikebenen + show_night => $show_night, # alle Balken (Spalten) anzeigen ? + graphicselect => $gsel, # Optionen der Grafikselektion }; my $colspan = $maxhours + 2; my $ret = q{}; $ret .= "$dlink
" if(CurrentVal ($name, 'showLink', 0)); - - #$ret .= ""; $ret .= ""; $ret .= ""; $ret .= " - + @@ -25297,14 +25307,6 @@ to ensure that the system configuration is correct.
- -
  • graphicHeaderShow
    - Show/hide the graphic table header with forecast data and certain current and - statistical values.
    - (default: 1) -
  • -
    -
  • graphicHistoryHour
    Number of previous hours displayed in the bar graph.
    @@ -25357,13 +25359,26 @@ to ensure that the system configuration is correct.

  • "; - # Headerzeile generieren - ########################## + # Kopfbereich inkl. Benutzerbereich generieren + ################################################ my $header = _graphicHeader ($paref); - # Verbraucherlegende und Steuerung - ################################### + # Verbraucherlegende und Steuerung generieren + ############################################### my $cnmlegend = _graphicConsumerLegend ($paref); - # Headerzeile und/oder Verbraucherlegende ausblenden - ###################################################### - if ($gsel =~ /_noHead/xs) { - $header = q{}; - } - - if ($gsel =~ /_noCons/xs) { - $cnmlegend = q{}; - } - - $ret .= "\n"; # das \n erleichtert das Lesen der debug Quelltextausgabe my $m = $paref->{modulo} % 2; + $ret .= "\n
    "; # das \n erleichtert das Lesen der debug Quelltextausgabe if ($header) { # Header ausgeben $ret .= ""; @@ -14175,10 +14168,11 @@ sub entryGraphic { $paref->{modulo}++; } - my $clegendpos = $paref->{clegendpos}; - $m = $paref->{modulo} % 2; + $m = $paref->{modulo} % 2; - if ($cnmlegend && $clegendpos eq 'top') { + # Verbraucherlegende oben + ################################################################################### + if ($cnmlegend && $paref->{clegendpos} =~ /_top$/xs) { $ret .= ""; $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= _levelSeparator ($paref); + + $paref->{modulo}++; + } + $m = $paref->{modulo} % 2; ## Balkengrafiken - ################### - + ################################################################################### ## Balkengrafik Ebene 1 ######################### - if ($gsel =~ /both/xs || $gsel =~ /forecast/xs) { + if ($gsel =~ /both|swap|forecast/xs) { my %hfcg1; $paref->{chartlvl} = 1; # Balkengrafik Ebene 1 $paref->{hfcg} = \%hfcg1; # hfcg = hash forecast graphic @@ -14321,13 +14329,13 @@ sub entryGraphic { $m = $paref->{modulo} % 2; - # Flußgrafik - ############## - if ($gsel =~ /both/xs || $gsel =~ /flow/xs) { + # Flußgrafik unterhalb Balkengrafik + ################################################################################### + if ($gsel =~ /both|flow/xs) { $ret .= ""; - my $fg = _flowGraphic ($paref); $ret .= ""; + $ret .= _flowGraphic ($paref); + $ret .= ""; $ret .= ""; $paref->{modulo}++; @@ -14335,11 +14343,10 @@ sub entryGraphic { $m = $paref->{modulo} % 2; - # Legende unten - ################# - if ($cnmlegend && ($clegendpos eq 'bottom')) { + # Verbraucherlegende unten + ################################################################################### + if ($cnmlegend && $paref->{clegendpos} =~ /_bottom$/xs) { $ret .= ""; - #$ret .= ""; $ret .= ""; @@ -14482,10 +14489,9 @@ return; # forecastGraphic Headerzeile generieren ################################################################ sub _graphicHeader { - my $paref = shift; - my $sheader = $paref->{sheader}; + my $paref = shift; - return if(!$sheader); + return q{} if($paref->{graphicselect} =~ /_noHead/xs); my $hdrDetail = $paref->{hdrDetail}; # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten my $ftui = $paref->{ftui}; @@ -15433,16 +15439,15 @@ return; # Verbraucherlegende und Steuerung ################################################################ sub _graphicConsumerLegend { - my $paref = shift; - my $name = $paref->{name}; - my ($clegendstyle, $clegend) = split '_', $paref->{clegendpos}; - my $clink = $paref->{clink}; + my $paref = shift; + my $name = $paref->{name}; + my $clink = $paref->{clink}; + my $graphicselect = $paref->{graphicselect}; # Optionen der Grafikselektion - my @consumers = sort{$a<=>$b} keys %{$data{$name}{consumers}}; # definierte Verbraucher ermitteln - $clegend = '' if($clegendstyle eq 'none' || !int @consumers); - $paref->{clegendpos} = $clegend; + my ($clstyle, $clpos) = split '_', $paref->{clegendpos}; + my @consumers = sort{$a<=>$b} keys %{$data{$name}{consumers}}; # definierte Verbraucher ermitteln - return if(!$clegend ); + return q{} if($graphicselect =~ /_noCons/xs || !scalar @consumers); my $hash = $defs{$name}; my $ftui = $paref->{ftui}; @@ -15485,7 +15490,7 @@ sub _graphicConsumerLegend { $ctable .= qq{}; - if ($clegend ne 'top') { + if ($clpos ne 'top') { $ctable .= qq{}; } @@ -15611,7 +15616,7 @@ sub _graphicConsumerLegend { } } - if ($clegendstyle eq 'icon') { + if ($clstyle eq 'icon') { $cicon = FW_makeImage($cicon); $ctable .= ""; $ctable .= ""; @@ -15645,7 +15650,7 @@ sub _graphicConsumerLegend { $ctable .= qq{} if($tro); - if ($clegend ne 'bottom') { + if ($clpos ne 'bottom') { $ctable .= qq{}; } @@ -24138,19 +24143,23 @@ to ensure that the system configuration is correct.
    "; $ret .= $cnmlegend; @@ -14188,14 +14182,28 @@ sub entryGraphic { $paref->{modulo}++; } + $m = $paref->{modulo} % 2; + + # Flußgrafik oberhalb Balkengrafik + ################################################################################### + if ($gsel =~ /swap/xs) { + $ret .= "
    "; + $ret .= _flowGraphic ($paref); + $ret .= "
    "; - $ret .= "$fg
    "; $ret .= ""; $ret .= "$cnmlegend

    $calias $cicon

    - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +
    both displays the header, consumer legend, energy flow graph and forecast graph (default)
    both_noHead displays the consumer legend, energy flow graph and forecast graph
    both_noCons displays the header, energy flow and prediction graphic
    both_noHead_noCons displays energy flow and prediction graphs
    flow displays the header, the consumer legend and energy flow graphic
    flow_noHead displays the consumer legend and the energy flow graph
    flow_noCons displays the header and the energy flow graph
    flow_noHead_noCons displays the energy flow graph
    forecast displays the header, the consumer legend and the forecast graphic
    forecast_noHead displays the consumer legend and the forecast graph
    forecast_noCons displays the header and the forecast graphic
    forecast_noHead_noCons displays the forecast graph
    none displays only the header and the consumer legend
    both displays graphic header, load panel, bar graph and energy flow graph (default)
    both_noHead displays load panel, bar graph and energy flow graph
    both_noCons displays graph header, bar graph and energy flow graph
    both_noHead_noCons displays bar graph and energy flow graph
    swap like 'both', with swapped bar and energy flow graph sequence
    swap_noHead like 'both_noHead', with swapped bar and energy flow graph sequence
    swap_noCons like 'both_noCons', with swapped bar and energy flow graph sequence
    swap_noHead_noCons like 'both_noHead_noCons', with swapped bar and energy flow graph sequence
    flow displays graphic header, load panel and energy flow graphic
    flow_noHead displays load panel and energy flow graph
    flow_noCons displays graphic header and energy flow graphic
    flow_noHead_noCons displays energy flow graph
    forecast displays graphic header, consumer panel and bar graph
    forecast_noHead displays consumer panel and bar graph
    forecast_noCons displays graphic header and bar chart
    forecast_noHead_noCons displays bar graph
    none only displays graphic header and consumer panel

    @@ -24162,6 +24171,7 @@ to ensure that the system configuration is correct. define wl.SolCast5 weblink htmlCode { FHEM::SolarForecast::pageAsHtml ('SolCast5', '-', '<argument>') }
    + 'SolCast5' is the name of the SolarForecast device to be included. <argument> is one of the above described selection options. @@ -24581,7 +24591,7 @@ to ensure that the system configuration is correct.
    The color can be specified as a hex value (e.g. #cc3300) or designation (e.g. red, blue).
    showLegend Defines the position or display method of the consumer legend if consumers are registered.
    none - the legend is hidden
    To hide the consumer panel, please use graphicSelect.
    icon_top - the legend is displayed above the bar chart with consumer icons (default)
    icon_bottom - the legend is displayed below the bar and flow chart with consumer icons
    text_top - the legend is displayed above the bar chart without consumer icons
    - - - - - -
    both displays the header, consumer legend, energy flow and prediction graph (default)
    flow displays the header, the consumer legend and energy flow graphic
    forecast displays the header, the consumer legend and the prediction graphic
    none displays only the header and the consumer legend
    + + + + + + + + + + + + + + + + + + + +
    both displays graphic header, load panel, bar graph and energy flow graph (default)
    both_noHead displays load panel, bar graph and energy flow graph
    both_noCons displays graph header, bar graph and energy flow graph
    both_noHead_noCons displays bar graph and energy flow graph
    swap like 'both', with swapped bar and energy flow graph sequence
    swap_noHead like 'both_noHead', with swapped bar and energy flow graph sequence
    swap_noCons like 'both_noCons', with swapped bar and energy flow graph sequence
    swap_noHead_noCons like 'both_noHead_noCons', with swapped bar and energy flow graph sequence
    flow displays graphic header, load panel and energy flow graphic
    flow_noHead displays load panel and energy flow graph
    flow_noCons displays graphic header and energy flow graphic
    flow_noHead_noCons displays energy flow graph
    forecast displays graphic header, consumer panel and bar graph
    forecast_noHead displays consumer panel and bar graph
    forecast_noCons displays graphic header and bar chart
    forecast_noHead_noCons displays bar graph
    none only displays graphic header and consumer panel

    @@ -26672,24 +26687,28 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Als Argument kann dem Befehl eine der folgenden Selektionen mitgegeben werden:

    - +
    Die Grafik kann abgerufen und in eigenen Code eingebettet werden. Auf einfache Weise kann dies durch die Definition @@ -27118,7 +27137,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Die Farbe kann als Hex-Wert (z.B. #cc3300) oder Bezeichnung (z.B. red, blue) angegeben werden. showLegend Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher registriert sind. - none - die Legende wird ausgeblendet + Zur Ausblendung des Verbraucherpaneels bitte graphicSelect verwenden. icon_top - die Legende wird oberhalb der Balkengrafik mit Verbrauchericons angezeigt (default) icon_bottom - die Legende wird unterhalb der Balken- und Flußgrafik mit Verbrauchericons angezeigt text_top - die Legende wird oberhalb der Balkengrafik ohne Verbrauchericons angezeigt @@ -27834,14 +27853,6 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
    - -
  • graphicHeaderShow
    - Anzeigen/Verbergen des Grafik Tabellenkopfes mit Prognosedaten sowie bestimmten aktuellen und - statistischen Werten.
    - (default: 1) -
  • -
    -
  • graphicHistoryHour
    Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden.
    @@ -27893,15 +27904,28 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. Wählt die anzuzeigenden Grafiksegmente des Moduls aus.

    -