2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 01:09:47 +00:00

76_SolarForecast.pm: contrib 0.47.0

git-svn-id: https://svn.fhem.de/fhem/trunk@24522 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2021-05-27 20:23:40 +00:00
parent e644768a59
commit 4539268113

View File

@ -116,7 +116,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
"0.47.0" => "26.05.2021 add flowGraphic, attr flowGraphicSize ",
"0.47.0" => "26.05.2021 add flowGraphic, attr flowGraphicSize, graphicSelect ",
"0.46.1" => "21.05.2021 set <> reset pvHistory <day> <hour> ",
"0.46.0" => "16.05.2021 integrate intotal, outtotal to currentBatteryDev, set maxconsumer to 9 ",
"0.45.1" => "13.05.2021 change the calc of etotal at the beginning of every hour in _transferInverterValues ".
@ -387,33 +387,35 @@ my %weather_ids = (
'100' => { s => '0', icon => 'weather_night', txtd => 'sternenklarer Himmel', txte => 'starry sky' },
);
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
my $defpvme = 16.52; # default Wirkungsgrad Solarmodule
my $definve = 98.3; # default Wirkungsgrad Wechselrichter
my $kJtokWh = 0.00027778; # Umrechnungsfaktor kJ in kWh
my $defmaxvar = 0.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor
my $definterval = 70; # Standard Abfrageintervall
my $defslidenum = 3; # max. Anzahl der Arrayelemente in Schieberegistern
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
my $defpvme = 16.52; # default Wirkungsgrad Solarmodule
my $definve = 98.3; # default Wirkungsgrad Wechselrichter
my $kJtokWh = 0.00027778; # Umrechnungsfaktor kJ in kWh
my $defmaxvar = 0.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor
my $definterval = 70; # Standard Abfrageintervall
my $defslidenum = 3; # max. Anzahl der Arrayelemente in Schieberegistern
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)
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)
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
my @dweattrmust = qw(TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
my @dweattrmust = qw(TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
my $cldampdef = 35; # Dämpfung (%) des Korrekturfaktors bzgl. effektiver Bewölkung, siehe: https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
my $cloud_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
my $cldampdef = 35; # Dämpfung (%) des Korrekturfaktors bzgl. effektiver Bewölkung, siehe: https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
my $cloud_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
my $rdampdef = 10; # Dämpfung (%) des Korrekturfaktors bzgl. Niederschlag (R101)
my $rain_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
my $rdampdef = 10; # Dämpfung (%) des Korrekturfaktors bzgl. Niederschlag (R101)
my $rain_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
my $maxconsumer = 9; # maximale Anzahl der möglichen Consumer (Attribut)
my @ctypes = qw(dishwasher dryer washingmachine heater other); # erlaubte Consumer Typen
my $defmintime = 60; # default min. Einschalt- bzw. Zykluszeit in Minuten
my $defctype = "other"; # default Verbrauchertyp
my $defcmode = "can"; # default Planungsmode der Verbraucher
my $maxconsumer = 9; # maximale Anzahl der möglichen Consumer (Attribut)
my @ctypes = qw(dishwasher dryer washingmachine heater other); # erlaubte Consumer Typen
my $defmintime = 60; # default min. Einschalt- bzw. Zykluszeit in Minuten
my $defctype = "other"; # default Verbrauchertyp
my $defcmode = "can"; # default Planungsmode der Verbraucher
my $defflowGSize = 300; # default flowGraphicSize
my %hef = ( # Energiedaktoren für Verbrauchertypen
@ -472,9 +474,10 @@ sub Initialize {
# "consumerAdviceIcon ".
"cloudFactorDamping:slider,0,1,100 ".
"disable:1,0 ".
"flowGraphicSize:slider,100,50,500 ".
"flowGraphicSize: ".
"follow70percentRule:1,dynamic,0 ".
"forcePageRefresh:1,0 ".
"graphicSelect:both,flow,forecast ".
"headerAlignment:center,left,right ".
"headerDetail:all,co,pv,pvco,statusLink ".
"historyHour:slider,-23,-1,0 ".
@ -2611,7 +2614,8 @@ sub _transferBatteryValues {
my ($pou,$pounit) = split ":", $h->{pout}; # Readingname/Unit für aktuelle Batterieentladung
my ($bin,$binunit) = split ":", $h->{intotal}; # Readingname/Unit der total in die Batterie eingespeisten Energie (Zähler)
my ($bout,$boutunit) = split ":", $h->{outtotal}; # Readingname/Unit der total aus der Batterie entnommenen Energie (Zähler)
my $batchr = $h->{charge} // ""; # Readingname Ladezustand Batterie
return if(!$pin || !$pou);
$pounit //= $piunit;
@ -2626,10 +2630,11 @@ sub _transferBatteryValues {
my $binuf = $binunit =~ /^kWh$/xi ? 1000 : 1;
my $boutuf = $boutunit =~ /^kWh$/xi ? 1000 : 1;
my $pbo = ReadingsNum ($badev, $pou, 0) * $pouf; # aktuelle Batterieentladung (W)
my $pbi = ReadingsNum ($badev, $pin, 0) * $piuf; # aktueller Batterieladung (W)
my $btotout = ReadingsNum ($badev, $bout, 0) * $boutuf; # totale Batterieentladung (Wh)
my $btotin = ReadingsNum ($badev, $bin, 0) * $binuf; # totale Batterieladung (Wh)
my $pbo = ReadingsNum ($badev, $pou, 0) * $pouf; # aktuelle Batterieentladung (W)
my $pbi = ReadingsNum ($badev, $pin, 0) * $piuf; # aktueller Batterieladung (W)
my $btotout = ReadingsNum ($badev, $bout, 0) * $boutuf; # totale Batterieentladung (Wh)
my $btotin = ReadingsNum ($badev, $bin, 0) * $binuf; # totale Batterieladung (Wh)
my $batcharge = ReadingsNum ($badev, $batchr, 50);
my $params;
@ -2678,7 +2683,7 @@ sub _transferBatteryValues {
$batinthishour = 0;
}
$data{$type}{$name}{circular}{sprintf("%02d",$nhour)}{batin} = $batinthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
$data{$type}{$name}{circular}{sprintf("%02d",$nhour)}{batin} = $batinthishour; # Ringspeicher Battery In Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
$paref->{batinthishour} = $batinthishour;
$paref->{nhour} = sprintf("%02d",$nhour);
@ -2698,7 +2703,7 @@ sub _transferBatteryValues {
setPVhistory ($paref);
delete $paref->{histname};
my $botot = CurrentVal ($hash, "batouttotal", $btotout);
my $botot = CurrentVal ($hash, "batouttotal", $btotout);
$batoutthishour = int ($btotout - $botot);
}
else {
@ -2723,11 +2728,13 @@ sub _transferBatteryValues {
push @$daref, "Today_Hour".sprintf("%02d",$nhour)."_BatOut<>".$batoutthishour." Wh";
push @$daref, "Current_PowerBatIn<>". (int $pbi)." W";
push @$daref, "Current_PowerBatOut<>".(int $pbo)." W";
push @$daref, "Current_BatCharge<>". $batcharge." %";
$data{$type}{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung
$data{$type}{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung
$data{$type}{$name}{current}{batintotal} = int $btotin; # totale Batterieladung
$data{$type}{$name}{current}{batouttotal} = int $btotout; # totale Batterieentladung
$data{$type}{$name}{current}{batcharge} = $batcharge; # aktuelle Batterieladung
return;
}
@ -3204,39 +3211,13 @@ return;
# FHEMWEB Fn
################################################################
sub FwFn {
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my $hash = $defs{$name};
my $height;
RemoveInternalTimer($hash, \&pageRefresh);
$hash->{HELPER}{FW} = $FW_wname;
my $foreg = forecastGraphic ($name);
my $flowgh = AttrVal ($name, "flowGraphicSize", 300);
my $flowg = flowGraphic ($name, $flowgh);
my $alias = AttrVal($name, "alias", $name); # Linktext als Aliasname oder Devicename setzen
my $dlink = qq{<a href="$FW_ME$FW_subdir?detail=$name">$alias</a>};
my $ret = q{};
if(IsDisabled($name)) {
$height = AttrNum($name, 'beamHeight', 200);
$ret .= "<table class='roomoverview'>";
$ret .= "<tr style='height:".$height."px'>";
$ret .= "<td>";
$ret .= qq{Solar forecast graphic device <a href="$FW_ME$FW_subdir?detail=$name">$name</a> is disabled};
$ret .= "</td>";
$ret .= "</tr>";
$ret .= "</table>";
}
else {
$ret .= "<span>$dlink </span><br>" if(AttrVal($name,"showLink",0));
$ret .= $foreg;
$ret .= "\n";
$ret .= $flowg;
}
my $ret = entryGraphic ($name);
# Autorefresh nur des aufrufenden FHEMWEB-Devices
my $al = AttrVal($name, "autoRefresh", 0);
@ -3277,40 +3258,170 @@ sub pageAsHtml {
my $hash = shift;
my $ftui = shift;
my $name = $hash->{NAME};
my $height;
my $link = forecastGraphic ($name, $ftui);
my $alias = AttrVal($name, "alias", $name); # Linktext als Aliasname oder Devicename setzen
my $dlink = "<a href=\"$FW_ME$FW_subdir?detail=$name\">$alias</a>";
my $ret = "<html>";
if(IsDisabled($name)) {
$height = AttrNum($name, 'beamHeight', 200);
$ret .= "<table class='roomoverview'>";
$ret .= "<tr style='height:".$height."px'>";
$ret .= "<td>";
$ret .= qq{Solar Forecast Device <a href="$FW_ME$FW_subdir?detail=$name">$name</a> is disabled};
$ret .= "</td>";
$ret .= "</tr>";
$ret .= "</table>";
$ret .= entryGraphic ($name);
$ret .= "</html>";
return $ret;
}
################################################################
# Einstieg Grafikanzeige
################################################################
sub entryGraphic {
my $name = shift;
my $ftui = shift // "";
my $hash = $defs{$name};
# Setup Vollständigkeit prüfen
###############################
my $incomplete = _checkSetupComplete ($hash);
return $incomplete if($incomplete);
# Parameter f. Anzeige extrahieren
###################################
my $width = AttrNum ($name, 'beamWidth', 6); # zu klein ist nicht problematisch
my $maxhours = AttrNum ($name, 'hourCount', 24);
my $colorw = AttrVal ($name, 'weatherColor', 'FFFFFF'); # Wetter Icon Farbe
my $alias = AttrVal ($name, "alias", $name); # Linktext als Aliasname oder Devicename setzen
my $gsel = AttrVal ($name, 'graphicSelect', 'both'); # Auswahl der anzuzeigenden Grafiken
my $dlink = qq{<a href="$FW_ME$FW_subdir?detail=$name">$alias</a>};
my $ret = q{};
return $ret if ($gsel eq "none");
my $params = {
hash => $hash,
name => $name,
ftui => $ftui,
maxhours => $maxhours,
offset => AttrNum ($name, 'historyHour', 0),
hourstyle => AttrVal ($name, 'hourStyle', ''),
colorfc => AttrVal ($name, 'beam1Color', '000000'),
colorc => AttrVal ($name, 'beam2Color', 'C4C4A7'),
fcolor1 => AttrVal ($name, 'beam1FontColor', 'C4C4A7'),
fcolor2 => AttrVal ($name, 'beam2FontColor', '000000'),
beam1cont => AttrVal ($name, 'beam1Content', 'pvForecast'),
beam2cont => AttrVal ($name, 'beam2Content', 'pvForecast'),
icon => AttrVal ($name, 'consumerAdviceIcon', undef),
html_start => AttrVal ($name, 'htmlStart', undef), # beliebige HTML Strings die vor der Grafik ausgegeben werden
html_end => AttrVal ($name, 'htmlEnd', undef), # beliebige HTML Strings die nach der Grafik ausgegeben werden
lotype => AttrVal ($name, 'layoutType', 'single'),
kw => AttrVal ($name, 'Wh/kWh', 'Wh'),
height => AttrNum ($name, 'beamHeight', 200),
width => $width,
w => $width * $maxhours, # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
fsize => AttrNum ($name, 'spaceSize', 24),
maxVal => AttrNum ($name, 'maxValBeam', 0), # dyn. Anpassung der Balkenhöhe oder statisch ?
show_night => AttrNum ($name, 'showNight', 0), # alle Balken (Spalten) anzeigen ?
show_diff => AttrVal ($name, 'showDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen
weather => AttrNum ($name, 'showWeather', 1),
colorw => $colorw,
colorwn => AttrVal ($name, 'weatherColorNight', $colorw), # Wetter Icon Farbe Nacht
wlalias => AttrVal ($name, 'alias', $name),
header => AttrNum ($name, 'showHeader', 1),
hdrAlign => AttrVal ($name, 'headerAlignment', 'center'), # ermöglicht per attr die Ausrichtung der Tabelle zu setzen
hdrDetail => AttrVal ($name, 'headerDetail', 'all'), # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten
lang => AttrVal ("global", 'language', 'EN'),
flowgh => AttrVal ($name, 'flowGraphicSize', $defflowGSize), # Größe Energieflußgrafik
};
if(IsDisabled($name)) {
$ret .= "<table class='roomoverview'>";
$ret .= "<tr style='height:".$params->{height}."px'>";
$ret .= "<td>";
$ret .= qq{SolarForecast device <a href="$FW_ME$FW_subdir?detail=$name">$name</a> is disabled};
$ret .= "</td>";
$ret .= "</tr>";
$ret .= "</table>";
}
else {
$ret .= "<span>$dlink </span><br>" if(AttrVal($name,"showLink",0));
$ret .= $link;
}
$ret .= "</html>";
$ret .= forecastGraphic ($params) if($gsel eq "both" || $gsel eq "forecast");
$ret .= "\n";
$ret .= flowGraphic ($params) if($gsel eq "both" || $gsel eq "flow");
}
return $ret;
}
################################################################
# Vollständigkeit Setup prüfen
################################################################
sub _checkSetupComplete {
my $hash = shift;
my $ret = q{};
my $name = $hash->{NAME};
my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
my $fcdev = ReadingsVal ($name, "currentForecastDev", undef); # Forecast Device (Wetter)
my $radev = ReadingsVal ($name, "currentRadiationDev", undef); # Forecast Device (Wetter)
my $indev = ReadingsVal ($name, "currentInverterDev", undef); # Inverter Device
my $medev = ReadingsVal ($name, "currentMeterDev", undef); # Meter Device
my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
my $pv0 = NexthoursVal ($hash, "NextHour00", "pvforecast", undef);
my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
if(!$is || !$fcdev || !$radev || !$indev || !$medev || !$peak || !defined $pv0 || !$dir || !$ta) {
my $link = qq{<a href="$FW_ME$FW_subdir?detail=$name">$name</a>};
my $height = AttrNum ($name, 'beamHeight', 200);
my $lang = AttrVal ("global", "language", "EN");
$ret .= "<table class='roomoverview'>";
$ret .= "<tr style='height:".$height."px'>";
$ret .= "<td>";
if(!$fcdev) { ## no critic 'Cascading'
$ret .= $hqtxt{cfd}{$lang};
}
elsif(!$radev) {
$ret .= $hqtxt{crd}{$lang};
}
elsif(!$indev) {
$ret .= $hqtxt{cid}{$lang};
}
elsif(!$medev) {
$ret .= $hqtxt{mid}{$lang};
}
elsif(!$is) {
$ret .= $hqtxt{ist}{$lang};
}
elsif(!$peak) {
$ret .= $hqtxt{mps}{$lang};
}
elsif(!$dir) {
$ret .= $hqtxt{mdr}{$lang};
}
elsif(!$ta) {
$ret .= $hqtxt{mta}{$lang};
}
elsif(!defined $pv0) {
$ret .= $hqtxt{awd}{$lang};
}
$ret .= "</td>";
$ret .= "</tr>";
$ret .= "</table>";
$ret =~ s/LINK/$link/gxs;
return $ret;
}
return;
}
###############################################################################
# Vorhersagegrafik
###############################################################################
sub forecastGraphic { ## no critic 'complexity'
my $name = shift;
my $ftui = shift // "";
my $hash = $defs{$name};
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
my $ftui = $paref->{ftui};
my $ret = "";
@ -3324,12 +3435,6 @@ sub forecastGraphic {
$hash->{HELPER}{SPGROOM} = $FW_room ? $FW_room : ""; # Raum aus dem das SMAPortalSPG-Device die Funktion aufrief
$hash->{HELPER}{SPGDETAIL} = $FW_detail ? $FW_detail : ""; # Name des SMAPortalSPG-Devices (wenn Detailansicht)
# Setup Vollständigkeit prüfen
###############################
my $incomplete = _checkSetupComplete ($hash);
return $incomplete if($incomplete);
# Verbraucherlegende und Steuerung
###################################
my $legend_txt;
@ -3377,35 +3482,35 @@ sub forecastGraphic {
# Parameter f. Anzeige extrahieren
###################################
my $maxhours = AttrNum ($name, 'hourCount', 24);
my $offset = AttrNum ($name, 'historyHour', 0);
my $hourstyle = AttrVal ($name, 'hourStyle', '');
my $colorfc = AttrVal ($name, 'beam1Color', '000000');
my $colorc = AttrVal ($name, 'beam2Color', 'C4C4A7');
my $fcolor1 = AttrVal ($name, 'beam1FontColor', 'C4C4A7');
my $fcolor2 = AttrVal ($name, 'beam2FontColor', '000000');
my $beam1cont = AttrVal ($name, 'beam1Content', 'pvForecast');
my $beam2cont = AttrVal ($name, 'beam2Content', 'pvForecast');
my $icon = AttrVal ($name, 'consumerAdviceIcon', undef);
my $html_start = AttrVal ($name, 'htmlStart', undef); # beliebige HTML Strings die vor der Grafik ausgegeben werden
my $html_end = AttrVal ($name, 'htmlEnd', undef); # beliebige HTML Strings die nach der Grafik ausgegeben werden
my $lotype = AttrVal ($name, 'layoutType', 'single');
my $kw = AttrVal ($name, 'Wh/kWh', 'Wh');
my $height = AttrNum ($name, 'beamHeight', 200);
my $width = AttrNum ($name, 'beamWidth', 6); # zu klein ist nicht problematisch
my $w = $width*$maxhours; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
my $fsize = AttrNum ($name, 'spaceSize', 24);
my $maxVal = AttrNum ($name, 'maxValBeam', 0); # dyn. Anpassung der Balkenhöhe oder statisch ?
my $show_night = AttrNum ($name, 'showNight', 0); # alle Balken (Spalten) anzeigen ?
my $show_diff = AttrVal ($name, 'showDiff', 'no'); # zusätzliche Anzeige $di{} in allen Typen
my $weather = AttrNum ($name, 'showWeather', 1);
my $colorw = AttrVal ($name, 'weatherColor', 'FFFFFF'); # Wetter Icon Farbe
my $colorwn = AttrVal ($name, 'weatherColorNight', $colorw); # Wetter Icon Farbe Nacht
my $wlalias = AttrVal ($name, 'alias', $name);
my $header = AttrNum ($name, 'showHeader', 1);
my $hdrAlign = AttrVal ($name, 'headerAlignment', 'center'); # ermöglicht per attr die Ausrichtung der Tabelle zu setzen
my $hdrDetail = AttrVal ($name, 'headerDetail', 'all'); # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten
my $lang = AttrVal ("global", 'language', 'EN');
my $maxhours = $paref->{maxhours};
my $offset = $paref->{offset};
my $hourstyle = $paref->{hourstyle};
my $colorfc = $paref->{colorfc};
my $colorc = $paref->{colorc};
my $fcolor1 = $paref->{fcolor1};
my $fcolor2 = $paref->{fcolor2};
my $beam1cont = $paref->{beam1cont};
my $beam2cont = $paref->{beam2cont};
my $icon = $paref->{icon};
my $html_start = $paref->{html_start}; # beliebige HTML Strings die vor der Grafik ausgegeben werden
my $html_end = $paref->{html_end}; # beliebige HTML Strings die nach der Grafik ausgegeben werden
my $lotype = $paref->{lotype};
my $kw = $paref->{kw};
my $height = $paref->{height};
my $width = $paref->{width}; # zu klein ist nicht problematisch
my $w = $paref->{w}; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
my $fsize = $paref->{fsize};
my $maxVal = $paref->{maxVal}; # dyn. Anpassung der Balkenhöhe oder statisch ?
my $show_night = $paref->{show_night}; # alle Balken (Spalten) anzeigen ?
my $show_diff = $paref->{show_diff}; # zusätzliche Anzeige $di{} in allen Typen
my $weather = $paref->{weather};
my $colorw = $paref->{colorw}; # Wetter Icon Farbe
my $colorwn = $paref->{colorwn}; # Wetter Icon Farbe Nacht
my $wlalias = $paref->{wlalias};
my $header = $paref->{header};
my $hdrAlign = $paref->{hdrAlign}; # ermöglicht per attr die Ausrichtung der Tabelle zu setzen
my $hdrDetail = $paref->{hdrDetail}; # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten
my $lang = $paref->{lang};
# Icon Erstellung, mit @<Farbe> ergänzen falls einfärben
# Beispiel mit Farbe: $icon = FW_makeImage('light_light_dim_100.svg@green');
@ -4079,202 +4184,141 @@ sub forecastGraphic {
return $ret;
}
################################################################
# Vollständigkeit Setup prüfen
################################################################
sub _checkSetupComplete {
my $hash = shift;
my $ret = q{};
my $name = $hash->{NAME};
my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
my $fcdev = ReadingsVal ($name, "currentForecastDev", undef); # Forecast Device (Wetter)
my $radev = ReadingsVal ($name, "currentRadiationDev", undef); # Forecast Device (Wetter)
my $indev = ReadingsVal ($name, "currentInverterDev", undef); # Inverter Device
my $medev = ReadingsVal ($name, "currentMeterDev", undef); # Meter Device
my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
my $pv0 = NexthoursVal ($hash, "NextHour00", "pvforecast", undef);
my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
if(!$is || !$fcdev || !$radev || !$indev || !$medev || !$peak || !defined $pv0 || !$dir || !$ta) {
my $link = qq{<a href="$FW_ME$FW_subdir?detail=$name">$name</a>};
my $height = AttrNum ($name, 'beamHeight', 200);
my $lang = AttrVal ("global", "language", "EN");
$ret .= "<table class='roomoverview'>";
$ret .= "<tr style='height:".$height."px'>";
$ret .= "<td>";
if(!$fcdev) { ## no critic 'Cascading'
$ret .= $hqtxt{cfd}{$lang};
}
elsif(!$radev) {
$ret .= $hqtxt{crd}{$lang};
}
elsif(!$indev) {
$ret .= $hqtxt{cid}{$lang};
}
elsif(!$medev) {
$ret .= $hqtxt{mid}{$lang};
}
elsif(!$is) {
$ret .= $hqtxt{ist}{$lang};
}
elsif(!$peak) {
$ret .= $hqtxt{mps}{$lang};
}
elsif(!$dir) {
$ret .= $hqtxt{mdr}{$lang};
}
elsif(!$ta) {
$ret .= $hqtxt{mta}{$lang};
}
elsif(!defined $pv0) {
$ret .= $hqtxt{awd}{$lang};
}
$ret .= "</td>";
$ret .= "</tr>";
$ret .= "</table>";
$ret =~ s/LINK/$link/gxs;
return $ret;
}
return;
}
################################################################
# Energieflußgrafik
################################################################
sub flowGraphic {
my $name = shift;
my $h = shift;
my $paref = shift;
my $name = $paref->{name};
my $flowgh = $paref->{flowgh};
my $fs = ($h < 300) ? '48px' : '32px';
my $style = 'width:'.$h.'px; height:'.$h.'px;';
my $style = 'width:'.$flowgh.'px; height:'.$flowgh.'px;';
my $fs = ($flowgh < 300) ? '48px' : '32px';
my $inactive = 'stroke-dashoffset: 20; stroke-dasharray: 10; opacity: 0.2;';
my $active = 'stroke-dashoffset: 20; stroke-dasharray: 10; animation: dash 0.5s linear; animation-iteration-count: infinite; opacity: 0.8;' ;
my $inactive = 'stroke-dashoffset: 20; stroke-dasharray: 10; opacity: 0.2;';
my $active = 'stroke-dashoffset: 20; stroke-dasharray: 10; animation: dash 0.5s linear; animation-iteration-count: infinite; opacity: 0.8;' ;
my $cpv = ReadingsNum($name, 'Current_PV', 0);
my $sun_color = ($cpv) ? 'orange' : 'gray';
my $cpv = ReadingsNum($name, 'Current_PV', 0);
my $sun_color = ($cpv) ? 'orange' : 'gray';
my $cgc = ReadingsNum($name, 'Current_GridConsumption', 0);
my $cgc_style = ($cgc) ? $active : $inactive;
my $cgc_color = ($cgc) ? 'red' : 'gray';
my $cgc = ReadingsNum($name, 'Current_GridConsumption', 0);
my $cgc_style = ($cgc) ? $active : $inactive;
my $cgc_color = ($cgc) ? 'red' : 'gray';
my $cgfi = ReadingsNum($name, 'Current_GridFeedIn', 0);
my $cgfi_style = ($cgfi) ? $active : $inactive;
my $cgfi_color = ($cgfi) ? 'yellow' : 'gray';
my $cgfi = ReadingsNum($name, 'Current_GridFeedIn', 0);
my $cgfi_style = ($cgfi) ? $active : $inactive;
my $cgfi_color = ($cgfi) ? 'yellow' : 'gray';
my $csc = ReadingsNum($name, 'Current_SelfConsumption', 0);
my $csc_style = ($csc) ? $active : $inactive;
my $csc_color = ($csc) ? 'yellow' : 'gray';
my $csc = ReadingsNum($name, 'Current_SelfConsumption', 0);
my $csc_style = ($csc) ? $active : $inactive;
my $csc_color = ($csc) ? 'yellow' : 'gray';
my $batin = ReadingsNum($name, 'Current_PowerBatIn', 0);
my $batin_style = ($batin) ? $active : $inactive;
my $batin_color = ($batin) ? 'yellow' : 'gray';
my $batin = ReadingsNum($name, 'Current_PowerBatIn', undef);
my $batout = ReadingsNum($name, 'Current_PowerBatOut', undef);
my $soc = ReadingsNum($name, 'Current_BatCharge', 100);
my $batcolor = ($soc > 10) ? 'green' : 'red';
my $hasbat = 1;
my $batout = ReadingsNum($name, 'Current_PowerBatOut' , 0);
my $batout_style = ($batout) ? $active : $inactive;
my $batout_color = ($batout) ? 'yellow' : 'gray';
if (!defined($batin) && !defined($batout)) {
$hasbat = 0;
$batin = 0;
$batout = 0;
$soc = 0;
}
my $grid_color = ($cgfi) ? 'green' : 'red';
$grid_color = 'gray' if (!$cgfi && !$cgc && $batout); # dritte Farbe
my $batin_style = ($batin) ? $active : $inactive;
my $batin_color = ($batin) ? 'yellow' : 'gray';
my $batout_style = ($batout) ? $active : $inactive;
my $batout_color = ($batout) ? 'yellow' : 'gray';
my $ret = qq{
<table class="roomoverview">
<tr><td><table class="block fbcalllist"><tr align="center"><td>
my $grid_color = ($cgfi) ? 'green' : 'red';
$grid_color = 'gray' if (!$cgfi && !$cgc && $batout); # dritte Farbe
my $ret = qq{
<table class="roomoverview">
<tr><td><table class="block"><tr align="center"><td>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" style="$style">
<g transform="translate(200,50)">
<g>
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(45)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(90)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(135)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(180)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(225)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(270)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(315)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<circle cx="0" cy="0" fill="$sun_color" r="16" stroke="orange" stroke-width="2"/>
</g>
<g id="home" fill="grey" transform="translate(0,150),scale(4)">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</g>
<g id="grid" fill="$grid_color" transform="translate(150,310),scale(3.5)">
<path d="M15.3,2H8.7L2,6.46V10H4V8H8v2.79l-4,9V22H6V20.59l6-3.27,6,3.27V22h2V19.79l-4-9V8h4v2h2V6.46ZM14,4V6H10V4ZM6.3,6,8,4.87V6Zm8,6L15,13.42,12,15,9,13.42,9.65,12ZM7.11,17.71,8.2,15.25l1.71.93Zm8.68-2.46,1.09,2.46-2.8-1.53ZM14,10H10V8h4Zm2-5.13L17.7,6H16Z"/>
</g>
};
if ($hasbat) {
$ret .= qq{
<g fill="$batcolor" stroke="$batcolor" transform="translate(270,135),scale(.33)">
<path d="m 134.65625,89.15625 c -6.01649,0 -11,4.983509 -11,11 l 0,180 c 0,6.01649 4.98351,11 11,11 l 95.5,0 c 6.01631,0 11,-4.9825 11,-11 l 0,-180 c 0,-6.016491 -4.98351,-11 -11,-11 l -95.5,0 z m 0,10 95.5,0 c 0.60951,0 1,0.390491 1,1 l 0,180 c 0,0.6085 -0.39231,1 -1,1 l -95.5,0 c -0.60951,0 -1,-0.39049 -1,-1 l 0,-180 c 0,-0.609509 0.39049,-1 1,-1 z"/>
<path d="m 169.625,69.65625 c -6.01649,0 -11,4.983509 -11,11 l 0,14 10,0 0,-14 c 0,-0.609509 0.39049,-1 1,-1 l 25.5,0 c 0.60951,0 1,0.390491 1,1 l 0,14 10,0 0,-14 c 0,-6.016491 -4.98351,-11 -11,-11 l -25.5,0 z"/>
};
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" style="$style">
<g fill="$sun_color" transform="translate(150,90) scale(0.03,-0.03)" stroke="none">
<path d="M715 2608 c-28 -15 -45 -38 -45 -62 0 -12 63 -83 167 -188 179 -180 199 -192 243 -148 43 43 31 63 -142 236 -90 89 -172 165 -183 168 -11 3 -29 0 -40 -6z"/>
<path d="M1207 2609 c-38 -22 -39 -55 -5 -136 35 -86 57 -113 91 -113 31 0 67 35 67 65 0 36 -49 147 -77 173 -26 24 -48 27 -76 11z"/>
<path d="M1373 2236 c-103 -33 -194 -114 -241 -214 l-27 -57 0 -295 0 -295 33 -67 c39 -81 121 -158 202 -190 51 -21 73 -23 328 -26 229 -3 282 -1 330 13 125 36 226 134 263 255 19 63 20 88 17 337 l-3 269 -32 65 c-39 80 -111 150 -191 187 l-57 27 -290 2 c-220 2 -300 -1 -332 -11z m633 -143 c57 -30 111 -97 129 -157 21 -71 21 -461 0 -532 -19 -63 -72 -126 -133 -156 -46 -22 -54 -23 -312 -23 -258 0 -266 1 -312 23 -27 13 -64 42 -83 65 -60 70 -67 114 -63 385 3 261 5 270 72 340 71 76 98 81 406 79 242 -2 257 -3 296 -24z"/>
<path d="M585 2130 c-23 -25 -22 -67 1 -90 31 -30 264 -119 288 -111 33 12 52 54 41 87 -9 24 -29 36 -135 81 -135 58 -168 63 -195 33z"/>
<path d="M20 1720 c-27 -27 -25 -66 5 -96 l25 -25 416 3 c398 3 416 4 430 22 20 28 17 73 -6 96 -19 19 -33 20 -435 20 -402 0 -416 -1 -435 -20z"/>
<path d="M2400 1380 c-25 -25 -26 -64 -2 -88 18 -18 159 -82 180 -82 24 0 62 43 62 71 0 37 -21 54 -105 90 -79 34 -108 36 -135 9z"/>
<path d="M725 1325 c-128 -54 -155 -72 -155 -106 0 -27 39 -69 65 -69 37 0 248 91 273 118 35 37 18 91 -33 106 -12 3 -70 -15 -150 -49z"/>
<path d="M733 817 c-260 -260 -293 -296 -293 -324 0 -35 38 -73 73 -73 14 0 119 97 314 292 262 262 293 296 293 325 0 35 -38 73 -74 73 -14 0 -116 -95 -313 -293z"/>
<path d="M2225 1085 c-14 -13 -25 -34 -25 -46 0 -16 51 -74 167 -191 145 -146 171 -168 199 -168 37 0 67 29 67 66 0 22 -35 61 -170 195 -118 118 -176 169 -192 169 -12 0 -33 -11 -46 -25z"/>
<path d="M1970 932 c-28 -9 -50 -35 -50 -59 0 -32 88 -243 114 -271 27 -31 72 -26 99 10 l20 27 -49 122 c-63 156 -86 186 -134 171z"/>
<path d="M1288 913 c-16 -17 -118 -254 -118 -271 0 -5 9 -21 21 -36 25 -32 70 -35 97 -6 22 23 113 246 112 276 0 48 -80 73 -112 37z"/>
<path d="M1620 902 l-25 -20 0 -415 c0 -394 1 -416 19 -436 24 -26 77 -28 99 -3 15 17 17 61 17 433 0 317 -3 419 -12 432 -21 27 -70 32 -98 9z"/>
</g>
<g transform="translate(200,50)">
<g>
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(45)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(90)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(135)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(180)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(225)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(270)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<g transform="rotate(315)">
<line fill="none" stroke="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
<circle cx="0" cy="0" fill="$sun_color" r="16" stroke="orange" stroke-width="2"/>
</g>
<g id="home" fill="grey" transform="translate(0,150),scale(4)">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</g>
<g id="grid" fill="$grid_color" transform="translate(150,310),scale(3.5)">
<path d="M15.3,2H8.7L2,6.46V10H4V8H8v2.79l-4,9V22H6V20.59l6-3.27,6,3.27V22h2V19.79l-4-9V8h4v2h2V6.46ZM14,4V6H10V4ZM6.3,6,8,4.87V6Zm8,6L15,13.42,12,15,9,13.42,9.65,12ZM7.11,17.71,8.2,15.25l1.71.93Zm8.68-2.46,1.09,2.46-2.8-1.53ZM14,10H10V8h4Zm2-5.13L17.7,6H16Z"/>
</g>
<g id="battery" fill="#090" stroke="#090" transform="translate(300,170),scale(.2)">
<line x1="75" y1="30" x2="75" y2="280" style="stroke-width: 12px;"></line>
<line x1="225" y1="30" x2="225" y2="280" style="stroke-width: 12px;"></line>
<line x1="69" y1="30" x2="231" y2="30" style="stroke-width: 12px;"></line>
<line x1="69" y1="284" x2="231" y2="285" style="stroke-width: 12px;"></line>
<line x1="105" y1="20" x2="195" y2="20" style="stroke-width: 25px;"></line>
<rect id="bat25" x="92" y="221" width="116" height="48" style="stroke-width:0px;"></rect>
<rect id="bat50" x="92" y="163" width="116" height="48" style="stroke-width:0px;"></rect>
<rect id="bat75" x="92" y="105" width="116" height="48" style="stroke-width:0px;"></rect>
<rect id="bat100" x="92" y="47" width="116" height="48" style="stroke-width:0px;"></rect>
</g>
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none">
$ret .= '<path d="m 221.141,266.334 c 0,3.313 -2.688,6 -6,6 h -65.5 c -3.313,0 -6,-2.688 -6,-6 v -6 c 0,-3.314 2.687,-6 6,-6 l 65.5,-20 c 3.313,0 6,2.686 6,6 v 26 z"/>' if ($soc > 24);
$ret .= '<path d="m 221.141,213.667 c 0,3.313 -2.688,6 -6,6 l -65.5,20 c -3.313,0 -6,-2.687 -6,-6 v -20 c 0,-3.313 2.687,-6 6,-6 l 65.5,-20 c 3.313,0 6,2.687 6,6 v 20 z"/>' if ($soc > 49);
$ret .= '<path d="m 221.141,166.667 c 0,3.313 -2.688,6 -6,6 l -65.5,20 c -3.313,0 -6,-2.687 -6,-6 v -20 c 0,-3.313 2.687,-6 6,-6 l 65.5,-20 c 3.313,0 6,2.687 6,6 v 20 z"/>' if ($soc > 74);
$ret .= '<path d="m 221.141,120 c 0,3.313 -2.688,6 -6,6 l -65.5,20 c -3.313,0 -6,-2.687 -6,-6 v -26 c 0,-3.313 2.687,-6 6,-6 h 65.5 c 3.313,0 6,2.687 6,6 v 6 z"/>' if ($soc > 90);
$ret .= '</g>';
}
$ret .= qq{
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none">
<path id="pv-home" style="$csc_style" d="M270,100 L270,180 C270,270,270,270,180,270 L100,270" stroke="$csc_color" />
<text id="pv-home-txt" x="210" y="240" style="fill: #ccc; font-size: $fs; text-anchor: end;">$csc</text>
<path id="pv-grid" style="$cgfi_style" d="M300,100 L300,500" stroke="$cgfi_color" />
<text id="pv-grid-txt" x="330" y="490" style="fill: #ccc; font-size: $fs; text-anchor: start;">$cgfi</text>
<text id="pv-grid-txt" x="330" y="490" style="fill: #ccc; font-size: $fs; text-anchor: '
};
#"
$ret .= (!$hasbat) ? 'middle;" transform="translate(-120,620) rotate(-90)"' : 'start;"';
$ret .= qq{
>$cgfi</text>
<path id="grid-home" style="$cgc_style" d="M270,500 L270,420 C270,330,270,330,180,330 L100,330" stroke="$cgc_color" />
<text id="grid-home-txt" x="210" y="390" style="fill: #ccc; font-size: $fs; text-anchor: end;">$cgc</text>
};
$ret .= qq{
<path id="bat-home" style="$batout_style" d="M500,300 L100,300" stroke="$batout_color" />
<text id="bat-home-txt" x="390" y="351" style="fill: #ccc; font-size: $fs; text-anchor: start;">$batout</text>
<path id="pv-bat" style="$batin_style" d="M330,100 L330,180 C330,270,330,270,420,270 L500,270" stroke="$batin_color" />
<text id="pv-bat-txt" x="390" y="245" style="fill: #ccc; font-size: $fs; text-anchor: start;">$batin</text>
</g>
</svg></td></tr></table></td></tr></table>
};
<text x="0" y="500" style="fill: #ccc; font-size: $fs; text-anchor: middle;" transform="translate(150,300) rotate(-90)">$soc %</text>
} if ($hasbat);
$ret .= qq{</g></svg></td></tr></table></td></tr></table>};
return $ret;
}
@ -5750,7 +5794,7 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
<ul>
<a id="SolarForecast-set-currentBatteryDev"></a>
<li><b>currentBatteryDev &lt;Meter Device Name&gt; pin=&lt;Readingname&gt;:&lt;Einheit&gt; pout=&lt;Readingname&gt;:&lt;Einheit&gt; [intotal=&lt;Readingname&gt;:&lt;Einheit&gt; outtotal=&lt;Readingname&gt;:&lt;Einheit&gt;] </b> <br><br>
<li><b>currentBatteryDev &lt;Meter Device Name&gt; pin=&lt;Readingname&gt;:&lt;Einheit&gt; pout=&lt;Readingname&gt;:&lt;Einheit&gt; [intotal=&lt;Readingname&gt;:&lt;Einheit&gt; outtotal=&lt;Readingname&gt;:&lt;Einheit&gt; charge=&lt;Readingname&gt;] </b> <br><br>
Legt ein beliebiges Device und seine Readings zur Lieferung der Batterie Leistungsdaten fest.
Das Modul geht davon aus dass der numerische Wert der Readings immer positiv ist.
@ -5764,6 +5808,7 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
<tr><td> <b>pout</b> </td><td>Reading welches die aktuelle Batterieentladung liefert </td></tr>
<tr><td> <b>intotal</b> </td><td>Reading welches die totale Batterieladung liefert (fortlaufender Zähler) </td></tr>
<tr><td> <b>outtotal</b> </td><td>Reading welches die totale Batterieentladung liefert (fortlaufender Zähler) </td></tr>
<tr><td> <b>charge</b> </td><td>Reading welches den aktuellen Ladezustand (in Prozent) liefert </td></tr>
<tr><td> <b>Einheit</b> </td><td>die jeweilige Einheit (W,Wh,kW,kWh) </td></tr>
</table>
</ul>
@ -6376,6 +6421,13 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
</li>
<br>
<a id="SolarForecast-attr-flowGraphicSize"></a>
<li><b>flowGraphicSize &lt;Pixel&gt; </b><br>
Größe der Energieflußgrafik sofern angezeigt. Siehe auch Attribut <a href="#SolarForecast-attr-graphicSelect">graphicSelect</a>. <br>
(default: 300)
</li>
<br>
<a id="SolarForecast-attr-follow70percentRule"></a>
<li><b>follow70percentRule</b><br>
Wenn gesetzt, wird die prognostizierte Leistung entsprechend der 70% Regel begrenzt. <br><br>
@ -6400,6 +6452,21 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
</li>
<br>
<a id="SolarForecast-attr-graphicSelect"></a>
<li><b>graphicSelect </b><br>
Wählt die anzuzeigende interne Grafik des Moduls aus. <br><br>
<ul>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td> <b>flow</b> </td><td>zeigt die Energieflußgrafik an </td></tr>
<tr><td> <b>forecast</b> </td><td>zeigt die Verhersagegrafik an </td></tr>
<tr><td> <b>both</b> </td><td>zeigt Energiefluß- und Vorhersagegrafik an (default) </td></tr>
</table>
</ul>
</li>
<br>
<a id="SolarForecast-attr-headerAlignment"></a>
<li><b>headerAlignment &lt;center | left | right&gt; </b><br>
Ausrichtung der Kopfzeilen. <br>