From 215b300200f8be8b78e3c82ba0b9c950ff0ddc25 Mon Sep 17 00:00:00 2001 From: nasseeder1 <nasseeder1@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:03:00 +0000 Subject: [PATCH] 76_SolarForecast: graphicHeaderOwnspec can use set-commands and attributes of other devices git-svn-id: https://svn.fhem.de/fhem/trunk@28228 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/76_SolarForecast.pm | 138 ++++++++++++-------- fhem/contrib/DS_Starter/76_SolarForecast.pm | 138 ++++++++++++-------- 3 files changed, 168 insertions(+), 110 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index b5e8a65d7..7d611de14 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. + - feature: 76_SolarForecast: graphicHeaderOwnspec can show set-commands and + attributes of other devices - feature: 72_FRITZBOX: neue set <name> energyMode <default|eco> ledSetting <led:on|off> und/oder <bright:1..3> und/oder <env:on|off> diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 502ffa00e..4473ac0a7 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -151,6 +151,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.4.0" => "29.11.2023 graphicHeaderOwnspec: can manage attr / sets of other devs by <attr|set>@<dev> ", "1.3.0" => "27.11.2023 new Attr graphicHeaderOwnspecValForm ", "1.2.0" => "25.11.2023 graphicHeaderOwnspec: show readings of other devs by <reaging>@<dev>, Set/reset batteryTrigger ", "1.1.3" => "24.11.2023 rename reset arguments according possible adjustable textField width ", @@ -456,7 +457,7 @@ my $defmaxvar = 0.5; my $definterval = 70; # Standard Abfrageintervall my $defslidenum = 3; # max. Anzahl der Arrayelemente in Schieberegistern my $webCmdFn = 'FW_widgetFallbackFn'; # FHEMWEB Widgets Funktion -my @attrreadings = (); # Array der Hilfsreadings als Attributspeicher +my @widgetreadings = (); # Array der Hilfsreadings als Attributspeicher my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_"; # Filename-Fragment für PV History (wird mit Devicename ergänzt) my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt) @@ -5103,8 +5104,8 @@ sub _specialActivities { deleteReadingspec ($hash, "Today_PVdeviation"); deleteReadingspec ($hash, "Today_PVreal"); - for my $atr (@attrreadings) { - deleteReadingspec ($hash, $atr); + for my $wdr (@widgetreadings) { + deleteReadingspec ($hash, $wdr); } for my $n (1..24) { @@ -9142,7 +9143,6 @@ return $aiicon; ################################################################ sub __createOwnSpec { my $paref = shift; - my $hash = $paref->{hash}; my $name = $paref->{name}; my $dstyle = $paref->{dstyle}; # TD-Style @@ -9155,8 +9155,8 @@ sub __createOwnSpec { return if(!$spec || !$show); - my $allsets = FW_widgetOverride($name, getAllSets ($name), "set")." "; - my $allattrs = FW_widgetOverride($name, getAllAttr ($name), "set")." "; # Leerzeichen am Ende wichtig für Regexvergleich + my $allsets = FW_widgetOverride ($name, getAllSets ($name), 'set')." "; + my $allattrs = FW_widgetOverride ($name, getAllAttr ($name), 'attr')." "; # Leerzeichen am Ende wichtig für Regexvergleich my @fields = split (/\s+/sx, $spec); @@ -9179,7 +9179,12 @@ sub __createOwnSpec { my ($h, $v, $u); for (my $k = 0 ; $k < $vinr; $k++) { - ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]); + ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]); # Label und darzustellendes Element + + $h->{$k}{elm} //= ''; + my ($elm, $dev) = split "@", $h->{$k}{elm}; # evtl. anderes Devices + $dev //= $name; + $col++; if (!$h->{$k}{label}) { @@ -9187,37 +9192,37 @@ sub __createOwnSpec { next; } - if ($h->{$k}{elm} !~ /@/xs) { - my $setcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allsets, 'set'); + my $setcmd = ___getFWwidget ($name, $dev, $elm, $allsets, 'set'); # Set-Kommandos identifizieren + + if ($setcmd) { + $v->{$k} = $setcmd; + $u->{$k} = q{}; - if ($setcmd) { - $v->{$k} = $setcmd; - $u->{$k} = q{}; - next; - } - - my $attrcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allattrs, 'attr'); - - if ($attrcmd) { - $v->{$k} = $attrcmd; - $u->{$k} = q{}; - next; - } + debugLog ($paref, 'graphic', "graphicHeaderOwnspec - set-command genereated:\n$setcmd"); + next; } - my ($rdg, $dev) = split "@", $h->{$k}{elm}; - $dev //= $name; - $v->{$k} = ReadingsVal ($dev, $rdg, ''); + my $attrcmd = ___getFWwidget ($name, $dev, $elm, $allattrs, 'attr'); # Attr-Kommandos identifizieren - if ($v->{$k} =~ /(-?\d+(\.\d+)?)/xs) { - ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $rdg, ''); # Value und Unit trennen wenn Value numerisch + if ($attrcmd) { + $v->{$k} = $attrcmd; + $u->{$k} = q{}; + + debugLog ($paref, 'graphic', "graphicHeaderOwnspec - attr-command genereated:\n$attrcmd"); + next; + } + + $v->{$k} = ReadingsVal ($dev, $elm, ''); + + if ($v->{$k} =~ /^\s*(-?\d+(\.\d+)?)/xs) { + ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $elm, ''); # Value und Unit trennen wenn Value numerisch } $v->{$k} //= q{}; $u->{$k} //= q{}; $paref->{dev} = $dev; - $paref->{rdg} = $rdg; + $paref->{rdg} = $elm; $paref->{val} = $v->{$k}; $paref->{unit} = $u->{$k}; @@ -9266,15 +9271,26 @@ return $ownv; ################################################################ sub ___getFWwidget { my $name = shift; + my $dev = shift // $name; # Device des Elements, default=$name my $elm = shift; # zu prüfendes Element my $allc = shift; # Kommandovorrat -> ist Element enthalten? my $ctyp = shift // 'set'; # Kommandotyp: set/attr - my $widget = ''; + return if(!$elm); + my $widget = ''; my ($current, $reading); + + if ($dev ne $name) { # Element eines anderen Devices verarbeiten + if ($ctyp eq 'set') { + $allc = FW_widgetOverride ($dev, getAllSets($dev), 'set')." "; # Leerzeichen am Ende wichtig für Regexvergleich + } + elsif ($ctyp eq 'attr') { + $allc = FW_widgetOverride ($dev, getAllAttr($dev), 'attr')." "; + } + } - if ($allc =~ /$elm:?(.*?)\s/xs) { + if ($allc =~ /$elm:?(.*?)\s/xs) { # Element in allen Sets oder Attr enthalten my $arg = $1; $arg = 'textFieldNL' if(!$arg); @@ -9282,40 +9298,51 @@ sub ___getFWwidget { $arg = '#,'.$arg; } - if ($ctyp eq 'attr') { - $current = AttrVal ($name, $elm, ''); - $reading = '.'.$elm; - - push @attrreadings, $reading; + if ($ctyp eq 'attr') { # Attributwerte als verstecktes Reading abbilden + $current = AttrVal ($dev, $elm, ''); + $reading = '.'.$dev.'_'.$elm; + } + else { # leeren Dummy-Wert als verstecktes Reading abbilden wenn Set-Kommando nicht als gleichnamiges Reading existiert + $current = ReadingsVal ($dev, $elm, ''); + $reading = '.'.$dev.'_'.$elm if(!$current); + } + + if ($reading && $reading =~ /^\./xs) { # verstecktes Reading für spätere Löschung merken + push @widgetreadings, $reading; readingsSingleUpdate ($defs{$name}, $reading, $current, 0); } - no strict "refs"; ## no critic 'NoStrict' - $widget = &{$webCmdFn} ($FW_wname, $name, "", $elm, $arg); + no strict "refs"; ## no critic 'NoStrict' + $widget = &{$webCmdFn} ($FW_wname, $dev, "",$elm, $arg); use strict "refs"; if ($widget) { - $widget =~ s,^<td[^>]*>(.*)</td>$,$1,x; - $widget =~ s,></div>, type='$ctyp'></div>,x; + my ($wc) = $widget =~ /current='((<td|<div|<\/div>).*?)'/xs; # Eleminierung von störenden HTML Elementen aus aktuellem Readingwert + + if ($wc) { + $widget = (split "current=", $widget)[0]; + $widget .= qq{ current='^ESC^'></div></td>}; + } + + $widget =~ s,^<td[^>]*>(.*)</td>$,$1,xs; + $widget =~ s,></div>, type='$ctyp'></div>,xs; } else { - $widget = FW_pH ("cmd=$ctyp $name $elm", $elm, 0, "", 1, 1); + $widget = FW_pH ("cmd=$ctyp $dev $elm", $elm, 0, "", 1, 1); } - if ($ctyp eq 'attr') { - eval { - my ($sc) = $widget =~ /current='(.*?)'/xs; - my ($sr) = $widget =~ /reading='(.*?)'/xs; - $widget =~ s/$sc/$current/ if(defined $sc); - $widget =~ s/$sr/$reading/ if(defined $sr); - }; - } + eval { # Vorbelegung der Anzeige korrigieren/sublimieren + my ($sc) = $widget =~ /current='(.*?)'/xs; + my ($sr) = $widget =~ /reading='(.*?)'/xs; + $widget =~ s/$sc/$current/ if(defined $sc && defined $current); + $widget =~ s/$sr/$reading/ if(defined $sr && defined $reading); + }; - if ($arg eq 'textField' || $arg eq 'textField-long') { # Label (Reading) ausblenden -> siehe fhemweb.js function FW_createTextField Zeile 1657 + if ($arg eq 'textField' || $arg eq 'textField-long') { # Label (Reading) ausblenden -> siehe fhemweb.js function FW_createTextField Zeile 1657 $widget =~ s/arg='textField/arg='textFieldNL/xs; } - if ($arg =~ 'slider') { # Widget slider in selectnumbers für Kopfgrafik umsetzen + if ($arg =~ 'slider') { # Widget slider in selectnumbers für Kopfgrafik umsetzen my ($wid, $min, $step, $max, $float) = split ",", $arg; $widget =~ s/arg='(.*?)'/arg='selectnumbers,$min,$step,$max,0,lin'/xs; } @@ -9388,8 +9415,8 @@ sub ___ghoValForm { } } - if ($val =~ /(-?\d+(\.\d+)?)/xs) { - ($val, my $u1) = split /\s+/, $val; # Value und Unit trennen + if ($val =~ /^\s*(-?\d+(\.\d+)?)/xs) { # Value und Unit numerischer Werte trennen + ($val, my $u1) = split /\s+/, $val; $unit = $u1 ? $u1 : $unit; } @@ -16237,8 +16264,9 @@ to ensure that the system configuration is correct. <br> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a> - <li><b>graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ... </b><br> + <li><b>graphicHeaderOwnspec <Label>:<Reading>[@Device] <Label>:<Set>[@Device] <Label>:<Attr>[@Device] ... </b><br> Display of any readings, set commands and attributes of the device in the graphic header. <br> + Readings, set commands and attributes of other devices can be displayed by specifying the optional [@Device]. <br> The values to be displayed are separated by spaces. Four values (fields) are displayed per line. <br> The input can be made in multiple lines. Values with the units "Wh" or "kWh" are converted according to the @@ -18186,9 +18214,9 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. <br> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a> - <li><b>graphicHeaderOwnspec <Label>:<Reading[@Device]> <Label>:<Reading[@Device]> ... </b><br> + <li><b>graphicHeaderOwnspec <Label>:<Reading>[@Device] <Label>:<Set>[@Device] <Label>:<Attr>[@Device] ... </b><br> Anzeige beliebiger Readings, Set-Kommandos und Attribute des SolarForecast Devices im Grafikkopf. <br> - Durch Angabe des optionalen [@Device] können Readings anderer Devices angezeigt werden. <br> + Durch Angabe des optionalen [@Device] können Readings, Set-Kommandos und Attribute anderer Devices angezeigt werden. <br> Die anzuzeigenden Werte werden durch Leerzeichen getrennt. Es werden vier Werte (Felder) pro Zeile dargestellt. <br> Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten "Wh" bzw. "kWh" werden entsprechend der Einstellung diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 502ffa00e..4473ac0a7 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -151,6 +151,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.4.0" => "29.11.2023 graphicHeaderOwnspec: can manage attr / sets of other devs by <attr|set>@<dev> ", "1.3.0" => "27.11.2023 new Attr graphicHeaderOwnspecValForm ", "1.2.0" => "25.11.2023 graphicHeaderOwnspec: show readings of other devs by <reaging>@<dev>, Set/reset batteryTrigger ", "1.1.3" => "24.11.2023 rename reset arguments according possible adjustable textField width ", @@ -456,7 +457,7 @@ my $defmaxvar = 0.5; my $definterval = 70; # Standard Abfrageintervall my $defslidenum = 3; # max. Anzahl der Arrayelemente in Schieberegistern my $webCmdFn = 'FW_widgetFallbackFn'; # FHEMWEB Widgets Funktion -my @attrreadings = (); # Array der Hilfsreadings als Attributspeicher +my @widgetreadings = (); # Array der Hilfsreadings als Attributspeicher my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_"; # Filename-Fragment für PV History (wird mit Devicename ergänzt) my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt) @@ -5103,8 +5104,8 @@ sub _specialActivities { deleteReadingspec ($hash, "Today_PVdeviation"); deleteReadingspec ($hash, "Today_PVreal"); - for my $atr (@attrreadings) { - deleteReadingspec ($hash, $atr); + for my $wdr (@widgetreadings) { + deleteReadingspec ($hash, $wdr); } for my $n (1..24) { @@ -9142,7 +9143,6 @@ return $aiicon; ################################################################ sub __createOwnSpec { my $paref = shift; - my $hash = $paref->{hash}; my $name = $paref->{name}; my $dstyle = $paref->{dstyle}; # TD-Style @@ -9155,8 +9155,8 @@ sub __createOwnSpec { return if(!$spec || !$show); - my $allsets = FW_widgetOverride($name, getAllSets ($name), "set")." "; - my $allattrs = FW_widgetOverride($name, getAllAttr ($name), "set")." "; # Leerzeichen am Ende wichtig für Regexvergleich + my $allsets = FW_widgetOverride ($name, getAllSets ($name), 'set')." "; + my $allattrs = FW_widgetOverride ($name, getAllAttr ($name), 'attr')." "; # Leerzeichen am Ende wichtig für Regexvergleich my @fields = split (/\s+/sx, $spec); @@ -9179,7 +9179,12 @@ sub __createOwnSpec { my ($h, $v, $u); for (my $k = 0 ; $k < $vinr; $k++) { - ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]); + ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]); # Label und darzustellendes Element + + $h->{$k}{elm} //= ''; + my ($elm, $dev) = split "@", $h->{$k}{elm}; # evtl. anderes Devices + $dev //= $name; + $col++; if (!$h->{$k}{label}) { @@ -9187,37 +9192,37 @@ sub __createOwnSpec { next; } - if ($h->{$k}{elm} !~ /@/xs) { - my $setcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allsets, 'set'); + my $setcmd = ___getFWwidget ($name, $dev, $elm, $allsets, 'set'); # Set-Kommandos identifizieren + + if ($setcmd) { + $v->{$k} = $setcmd; + $u->{$k} = q{}; - if ($setcmd) { - $v->{$k} = $setcmd; - $u->{$k} = q{}; - next; - } - - my $attrcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allattrs, 'attr'); - - if ($attrcmd) { - $v->{$k} = $attrcmd; - $u->{$k} = q{}; - next; - } + debugLog ($paref, 'graphic', "graphicHeaderOwnspec - set-command genereated:\n$setcmd"); + next; } - my ($rdg, $dev) = split "@", $h->{$k}{elm}; - $dev //= $name; - $v->{$k} = ReadingsVal ($dev, $rdg, ''); + my $attrcmd = ___getFWwidget ($name, $dev, $elm, $allattrs, 'attr'); # Attr-Kommandos identifizieren - if ($v->{$k} =~ /(-?\d+(\.\d+)?)/xs) { - ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $rdg, ''); # Value und Unit trennen wenn Value numerisch + if ($attrcmd) { + $v->{$k} = $attrcmd; + $u->{$k} = q{}; + + debugLog ($paref, 'graphic', "graphicHeaderOwnspec - attr-command genereated:\n$attrcmd"); + next; + } + + $v->{$k} = ReadingsVal ($dev, $elm, ''); + + if ($v->{$k} =~ /^\s*(-?\d+(\.\d+)?)/xs) { + ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $elm, ''); # Value und Unit trennen wenn Value numerisch } $v->{$k} //= q{}; $u->{$k} //= q{}; $paref->{dev} = $dev; - $paref->{rdg} = $rdg; + $paref->{rdg} = $elm; $paref->{val} = $v->{$k}; $paref->{unit} = $u->{$k}; @@ -9266,15 +9271,26 @@ return $ownv; ################################################################ sub ___getFWwidget { my $name = shift; + my $dev = shift // $name; # Device des Elements, default=$name my $elm = shift; # zu prüfendes Element my $allc = shift; # Kommandovorrat -> ist Element enthalten? my $ctyp = shift // 'set'; # Kommandotyp: set/attr - my $widget = ''; + return if(!$elm); + my $widget = ''; my ($current, $reading); + + if ($dev ne $name) { # Element eines anderen Devices verarbeiten + if ($ctyp eq 'set') { + $allc = FW_widgetOverride ($dev, getAllSets($dev), 'set')." "; # Leerzeichen am Ende wichtig für Regexvergleich + } + elsif ($ctyp eq 'attr') { + $allc = FW_widgetOverride ($dev, getAllAttr($dev), 'attr')." "; + } + } - if ($allc =~ /$elm:?(.*?)\s/xs) { + if ($allc =~ /$elm:?(.*?)\s/xs) { # Element in allen Sets oder Attr enthalten my $arg = $1; $arg = 'textFieldNL' if(!$arg); @@ -9282,40 +9298,51 @@ sub ___getFWwidget { $arg = '#,'.$arg; } - if ($ctyp eq 'attr') { - $current = AttrVal ($name, $elm, ''); - $reading = '.'.$elm; - - push @attrreadings, $reading; + if ($ctyp eq 'attr') { # Attributwerte als verstecktes Reading abbilden + $current = AttrVal ($dev, $elm, ''); + $reading = '.'.$dev.'_'.$elm; + } + else { # leeren Dummy-Wert als verstecktes Reading abbilden wenn Set-Kommando nicht als gleichnamiges Reading existiert + $current = ReadingsVal ($dev, $elm, ''); + $reading = '.'.$dev.'_'.$elm if(!$current); + } + + if ($reading && $reading =~ /^\./xs) { # verstecktes Reading für spätere Löschung merken + push @widgetreadings, $reading; readingsSingleUpdate ($defs{$name}, $reading, $current, 0); } - no strict "refs"; ## no critic 'NoStrict' - $widget = &{$webCmdFn} ($FW_wname, $name, "", $elm, $arg); + no strict "refs"; ## no critic 'NoStrict' + $widget = &{$webCmdFn} ($FW_wname, $dev, "",$elm, $arg); use strict "refs"; if ($widget) { - $widget =~ s,^<td[^>]*>(.*)</td>$,$1,x; - $widget =~ s,></div>, type='$ctyp'></div>,x; + my ($wc) = $widget =~ /current='((<td|<div|<\/div>).*?)'/xs; # Eleminierung von störenden HTML Elementen aus aktuellem Readingwert + + if ($wc) { + $widget = (split "current=", $widget)[0]; + $widget .= qq{ current='^ESC^'></div></td>}; + } + + $widget =~ s,^<td[^>]*>(.*)</td>$,$1,xs; + $widget =~ s,></div>, type='$ctyp'></div>,xs; } else { - $widget = FW_pH ("cmd=$ctyp $name $elm", $elm, 0, "", 1, 1); + $widget = FW_pH ("cmd=$ctyp $dev $elm", $elm, 0, "", 1, 1); } - if ($ctyp eq 'attr') { - eval { - my ($sc) = $widget =~ /current='(.*?)'/xs; - my ($sr) = $widget =~ /reading='(.*?)'/xs; - $widget =~ s/$sc/$current/ if(defined $sc); - $widget =~ s/$sr/$reading/ if(defined $sr); - }; - } + eval { # Vorbelegung der Anzeige korrigieren/sublimieren + my ($sc) = $widget =~ /current='(.*?)'/xs; + my ($sr) = $widget =~ /reading='(.*?)'/xs; + $widget =~ s/$sc/$current/ if(defined $sc && defined $current); + $widget =~ s/$sr/$reading/ if(defined $sr && defined $reading); + }; - if ($arg eq 'textField' || $arg eq 'textField-long') { # Label (Reading) ausblenden -> siehe fhemweb.js function FW_createTextField Zeile 1657 + if ($arg eq 'textField' || $arg eq 'textField-long') { # Label (Reading) ausblenden -> siehe fhemweb.js function FW_createTextField Zeile 1657 $widget =~ s/arg='textField/arg='textFieldNL/xs; } - if ($arg =~ 'slider') { # Widget slider in selectnumbers für Kopfgrafik umsetzen + if ($arg =~ 'slider') { # Widget slider in selectnumbers für Kopfgrafik umsetzen my ($wid, $min, $step, $max, $float) = split ",", $arg; $widget =~ s/arg='(.*?)'/arg='selectnumbers,$min,$step,$max,0,lin'/xs; } @@ -9388,8 +9415,8 @@ sub ___ghoValForm { } } - if ($val =~ /(-?\d+(\.\d+)?)/xs) { - ($val, my $u1) = split /\s+/, $val; # Value und Unit trennen + if ($val =~ /^\s*(-?\d+(\.\d+)?)/xs) { # Value und Unit numerischer Werte trennen + ($val, my $u1) = split /\s+/, $val; $unit = $u1 ? $u1 : $unit; } @@ -16237,8 +16264,9 @@ to ensure that the system configuration is correct. <br> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a> - <li><b>graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ... </b><br> + <li><b>graphicHeaderOwnspec <Label>:<Reading>[@Device] <Label>:<Set>[@Device] <Label>:<Attr>[@Device] ... </b><br> Display of any readings, set commands and attributes of the device in the graphic header. <br> + Readings, set commands and attributes of other devices can be displayed by specifying the optional [@Device]. <br> The values to be displayed are separated by spaces. Four values (fields) are displayed per line. <br> The input can be made in multiple lines. Values with the units "Wh" or "kWh" are converted according to the @@ -18186,9 +18214,9 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. <br> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a> - <li><b>graphicHeaderOwnspec <Label>:<Reading[@Device]> <Label>:<Reading[@Device]> ... </b><br> + <li><b>graphicHeaderOwnspec <Label>:<Reading>[@Device] <Label>:<Set>[@Device] <Label>:<Attr>[@Device] ... </b><br> Anzeige beliebiger Readings, Set-Kommandos und Attribute des SolarForecast Devices im Grafikkopf. <br> - Durch Angabe des optionalen [@Device] können Readings anderer Devices angezeigt werden. <br> + Durch Angabe des optionalen [@Device] können Readings, Set-Kommandos und Attribute anderer Devices angezeigt werden. <br> Die anzuzeigenden Werte werden durch Leerzeichen getrennt. Es werden vier Werte (Felder) pro Zeile dargestellt. <br> Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten "Wh" bzw. "kWh" werden entsprechend der Einstellung