2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-27 20:34:52 +00:00

76_SolarForecast: contrib 1.34.0

git-svn-id: https://svn.fhem.de/fhem/trunk@29182 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2024-10-02 11:33:19 +00:00
parent 245e7c7889
commit 5e1596dfb6

@ -50,14 +50,13 @@ use HttpUtils;
eval "use JSON;1;" or my $jsonabs = 'JSON'; ## no critic 'eval' # Debian: sudo apt-get install libjson-perl
eval "use AI::DecisionTree;1;" or my $aidtabs = 'AI::DecisionTree'; ## no critic 'eval'
use FHEM::SynoModules::SMUtils qw(
checkModVer
use FHEM::SynoModules::SMUtils qw (checkModVer
evaljson
getClHash
delClHash
moduleVersion
trim
); # Hilfsroutinen Modul
); # Hilfsroutinen Modul
use Data::Dumper;
use Blocking;
@ -68,8 +67,7 @@ use MIME::Base64;
BEGIN {
# Import from main::
GP_Import(
qw(
attr
qw (attr
asyncOutput
AnalyzePerlCommand
AnalyzeCommandChain
@ -137,7 +135,7 @@ BEGIN {
FW_widgetOverride
FW_wname
readyfnlist
)
)
);
# Export to main context with different name
@ -162,7 +160,9 @@ my %vNotesIntern = (
"note in Reading pvCorrectionFactor_XX if AI prediction was used in relevant hour ".
"AI usage depending either of available number of rules or difference to api forecast ".
"minor fix in ___readCandQ, new experimental attribute ctrlAreaFactorUsage ".
"optional icon in attr setupOtherProducerXX ",
"optional icon in attr setupOtherProducerXX, integrate Producer to _flowGraphic (kask) ".
"don't show Consumer or Producer if it isn't defined any kind of it ".
"Optimization of space in the flow chart above generators and below consumers ",
"1.33.1" => "27.09.2024 bugfix of 1.33.0, add aiRulesNumber to pvCircular, limits of AI trained datasets for ".
"AI use (aiAccTRNMin, aiSpreadTRNMin)",
"1.33.0" => "26.09.2024 substitute area factor hash by ___areaFactorFix function ",
@ -1205,7 +1205,7 @@ sub Initialize {
"ctrlBatSocManagement:textField-long ".
"ctrlConsRecommendReadings:multiple-strict,$allcs ".
"ctrlDebug:multiple-strict,$dm,#14 ".
"ctrlAreaFactorUsage:fix,flex,flexShared ".
"ctrlAreaFactorUsage:fix,trackFull,trackShared ".
"ctrlGenPVdeviation:daily,continuously ".
"ctrlInterval ".
"ctrlLanguage:DE,EN ".
@ -3314,14 +3314,10 @@ return;
}
##################################################################################################
# Abruf DWD Strahlungsdaten und Rohdaten ohne Korrektur
# speichern in solcastapi Hash
# Abruf DWD Strahlungsdaten und Rohdaten ohne Korrektur
#
# !!!! NACHFOLGENDE INFO GILT NUR BEI DWD RAD1H VERWENDUNG !!!!
# #############################################################
#
# PV Forecast Rad1h in kWh / Wh
# Berechnung nach Formel 1 aus http://www.ing-büro-junge.de/html/photovoltaik.html:
# Berechnung nach Formel 1 aus http://www.ing-büro-junge.de/html/photovoltaik.html
# als Jahreserträge:
#
# * Faktor für Umwandlung kJ in kWh: 0.00027778
# * Eigene Modulfläche in qm z.B.: 31,04
@ -3329,8 +3325,8 @@ return;
# * Wirkungsgrad WR in % z.B.: 98,3
# * Korrekturwerte wegen Ausrichtung/Verschattung etc.
#
# Die Formel wäre dann:
# Ertrag in Wh = Rad1h * 0.00027778 * 31,04 qm * 16,52% * 98,3% * 100% * 1000
# Die Formel wäre dann:
# Ertrag in Wh = Rad1h * 0.00027778 * 31,04 qm * 16,52% * 98,3% * 100% * 1000
#
# Berechnung nach Formel 2 aus http://www.ing-büro-junge.de/html/photovoltaik.html:
#
@ -3348,7 +3344,7 @@ return;
# hier beschrieben:
# https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
#
# !!! PV Berechnungsgrundlagen !!!
# PV Berechnungsgrundlagen
# https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/ertrag
# http://www.ing-büro-junge.de/html/photovoltaik.html
#
@ -3417,7 +3413,7 @@ sub __getDWDSolarData {
my ($af, $pv, $sdr, $wcc);
if ($cafd =~ /flex/xs) { # Flächenfaktor Sonnenstand geführt
if ($cafd =~ /track/xs) { # Flächenfaktor Sonnenstand geführt
($af, $sdr, $wcc) = ___areaFactorTrack ( { name => $name,
day => $day,
dday => $dday,
@ -3429,6 +3425,7 @@ sub __getDWDSolarData {
);
$wcc = 0 if(!isNumeric($wcc));
$wcc = cloud2bin($wcc);
debugLog ($paref, "apiProcess", "DWD API - Value of sunaz/sunalt not stored in pvHistory, workaround using 1.00/0.75")
if(!isNumeric($af));
@ -3436,7 +3433,7 @@ sub __getDWDSolarData {
$af = 1.00 if(!isNumeric($af));
$sdr = 0.75 if(!isNumeric($sdr));
if ($cafd eq 'flexShared') { # Direktstrahlung + Diffusstrahlung
if ($cafd eq 'trackShared') { # Direktstrahlung + Diffusstrahlung
my $dirrad = $rad * $sdr; # Anteil Direktstrahlung an Globalstrahlung
my $difrad = $rad - $dirrad; # Anteil Diffusstrahlung an Globalstrahlung
@ -5682,7 +5679,10 @@ sub __delProducerValues {
deleteReadingspec ($hash, ".*_PPreal".$prn);
readingsDelete ($hash, 'Current_PP'.$prn);
delete $data{$type}{$name}{current}{'generationp'.$prn};
delete $data{$type}{$name}{current}{'etotalp'.$prn};
delete $data{$type}{$name}{current}{'etotalp' .$prn};
delete $data{$type}{$name}{current}{'iconp' .$prn};
delete $data{$type}{$name}{current}{'namep' .$prn};
delete $data{$type}{$name}{current}{'aliasp' .$prn};
for my $hod (keys %{$data{$type}{$name}{circular}}) {
delete $data{$type}{$name}{circular}{$hod}{'pprl'.$prn};
@ -5690,7 +5690,7 @@ sub __delProducerValues {
for my $dy (sort keys %{$data{$type}{$name}{pvhist}}) {
for my $hr (sort keys %{$data{$type}{$name}{pvhist}{$dy}}) {
delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'pprl'.$prn};
delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'pprl' .$prn};
delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'etotalp'.$prn};
}
}
@ -8455,9 +8455,9 @@ sub _transferProducerValues {
my $pu = $pcunit =~ /^kW$/xi ? 1000 : 1;
my $p = ReadingsNum ($prdev, $pcread, 0) * $pu; # aktuelle Erzeugung (W)
$p = $p < 0 ? 0 : sprintf("%.0f", $p);
$p = $p < 0 ? 0 : $p;
storeReading ('Current_PP'.$prn, $p.' W');
storeReading ('Current_PP'.$prn, sprintf("%.1f", $p).' W');
$data{$type}{$name}{current}{'generationp'.$prn} = $p;
my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1;
@ -8482,7 +8482,9 @@ sub _transferProducerValues {
}
$data{$type}{$name}{current}{'etotalp'.$prn} = $etotal; # aktuellen etotal des WR speichern
$data{$type}{$name}{current}{'namep' .$prn} = $prdev; # Name des Producerdevices
$data{$type}{$name}{current}{'aliasp' .$prn} = AttrVal ($prdev, 'alias', $prdev); # Alias Producer
if ($ethishour < 0) {
$ethishour = 0;
my $vl = 3;
@ -13878,6 +13880,7 @@ return $ret;
sub _flowGraphic {
my $paref = shift;
my $name = $paref->{name};
my $type = $paref->{type};
my $flowgsize = $paref->{flowgsize};
my $flowgani = $paref->{flowgani};
my $flowgshift = $paref->{flowgshift}; # Verschiebung der Flußgrafikbox (muß negiert werden)
@ -13888,27 +13891,60 @@ sub _flowGraphic {
my $consDist = $paref->{flowgconsDist};
my $css = $paref->{css};
my $hasbat = 1; # initial Batterie vorhanden
my $flowgprods = 1; # Producer in der Energieflußgrafik anzeigen per default
my $hash = $defs{$name};
my $style = 'width:98%; height:'.$flowgsize.'px;';
my $animation = $flowgani ? '@keyframes dash { to { stroke-dashoffset: 0; } }' : ''; # Animation Ja/Nein
my $cpv = ReadingsNum ($name, 'Current_PV', 0);
my $animation = $flowgani ? '@keyframes dash { to { stroke-dashoffset: 0; } }' : ''; # Animation Ja/Nein
my $cgc = ReadingsNum ($name, 'Current_GridConsumption', 0);
my $cgfi = ReadingsNum ($name, 'Current_GridFeedIn', 0);
my $csc = ReadingsNum ($name, 'Current_SelfConsumption', 0);
my $cc = CurrentVal ($hash, 'consumption', 0);
my $gp01 = CurrentVal ($hash, 'generationp01', 0);
my $gp02 = CurrentVal ($hash, 'generationp02', 0);
my $gp03 = CurrentVal ($hash, 'generationp03', 0);
my $cc_dummy = $cc;
my $cpv = ReadingsNum ($name, 'Current_PV', 0);
my $batin = ReadingsNum ($name, 'Current_PowerBatIn', undef);
my $batout = ReadingsNum ($name, 'Current_PowerBatOut', undef);
my $soc = ReadingsNum ($name, 'Current_BatCharge', 100);
my $cc_dummy = $cc;
## definierte Producer ermitteln und deren
## aktuelle Leistung bestimmen
############################################
my $producercount = 0;
my $ppall = 0; # Summe Erzeugung alle Poducer
my @producers;
for my $i (1..$maxproducer) {
my $p = CurrentVal ($hash, 'generationp'.(sprintf "%02d", ($i)), undef);
my $bat_color = $soc < 26 ? 'flowg bat25' :
$soc < 76 ? 'flowg bat50' :
'flowg bat75';
if (defined $p) {
push @producers, sprintf "%02d", $i;
$producercount += 1;
$ppall += $p;
}
}
$ppall = sprintf("%.0f", $ppall);
$flowgprods = 0 if(!$producercount); # Producer Anzeige ausschalten wenn keine Producer definiert
## definierte Verbraucher ermitteln
#####################################
my $consumercount = 0;
my @consumers;
for my $c (sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}) { # definierte Verbraucher ermitteln
next if(isConsumerNoshow ($hash, $c) =~ /^[13]$/xs); # auszublendende Consumer nicht berücksichtigen
push @consumers, $c;
$consumercount += 1;
}
my $hasbat = 1;
$flowgcons = 0 if(!$consumercount); # Consumer Anzeige ausschalten wenn keine Consumer definiert
## Batterie + Werte festlegen
###############################
my $bat_color = $soc < 26 ? 'flowg bat25' :
$soc < 76 ? 'flowg bat50' :
'flowg bat75';
if (!defined($batin) && !defined($batout)) {
$hasbat = 0;
@ -13916,55 +13952,56 @@ sub _flowGraphic {
$batout = 0;
$soc = 0;
}
else {
#$csc -= $batout;
}
my $grid_color = $cgfi ? 'flowg grid_color1' : 'flowg grid_color2';
$grid_color = 'flowg grid_color3' if (!$cgfi && !$cgc && $batout); # dritte Farbe
my $cgc_style = $cgc ? 'flowg active_in' : 'flowg inactive_in';
my $batout_style = $batout ? 'flowg active_out active_bat_out' : 'flowg inactive_in';
$grid_color = 'flowg grid_color3' if(!$cgfi && !$cgc && $batout); # dritte Farbe
my $cgc_direction = 'M490,515 L670,590'; # Batterientladung ins Netz
my $cgc_direction = 'M490,305 L670,510'; # Batterientladung ins Netz
if ($batout) {
if ($batout) { # Batterie wird entladen
my $cgfo = $cgfi - $cpv;
if($cgfo > 1) {
$cgc_style = 'flowg active_out';
$cgc_direction = 'M670,510 L490,305';
$cgfi -= $cgfo;
$cgc = $cgfo;
if ($cgfo > 1) {
$cgc_style = 'flowg active_out';
$cgc_direction = 'M670,590 L490,515';
$cgfi -= $cgfo;
$cgc = $cgfo;
}
}
my $batout_direction = 'M902,305 L730,510'; # Batterientladung aus Netz
my $batout_direction = 'M902,515 L730,590';
if ($batin) {
if ($batin) { # Batterie wird geladen
my $gbi = $batin - $cpv;
if ($gbi > 1) {
if ($gbi > 1) { # Batterieladung anteilig aus Hausnetz geladen
$batin -= $gbi;
$batout_style = 'flowg active_in';
$batout_direction = 'M730,510 L902,305';
$batout_direction = 'M730,590 L902,515';
$batout = $gbi;
}
}
my $sun_color = $cpv ? 'flowg sun_active' : 'flowg sun_inactive';
my $batin_style = $batin ? 'flowg active_in active_bat_in' : 'flowg inactive_out';
my $csc_style = $csc && $cpv ? 'flowg active_out' : 'flowg inactive_out';
my $cgfi_style = $cgfi ? 'flowg active_out' : 'flowg inactive_out';
## SVG Box initialisieren
###########################
my $sun_color = $cpv ? 'flowg sun_active' : 'flowg sun_inactive';
my $batin_style = $batin ? 'flowg active_in active_bat_in' : 'flowg inactive_out';
my $csc_style = $csc && ($cpv || $ppall) ? 'flowg active_out' : 'flowg inactive_out';
my $cgfi_style = $cgfi ? 'flowg active_out' : 'flowg inactive_out';
my $vbwidth = 800; # width and height specify the viewBox size
my $vbminx = -10 * $flowgshift; # min-x and min-y represent the smallest X and Y coordinates that the viewBox may have
my $vbminy = $flowgprods ? -25 : 100;
my $vbhight = !$flowgcons ? 380 :
!$flowgconTime ? 590 :
610;
$vbhight += 100 if($flowgprods);
my $vbminx = -10 * $flowgshift; # min-x and min-y represent the smallest X and Y coordinates that the viewBox may have
my $vbminy = -25;
my $vbwidth = 800; # width and height specify the viewBox size
my $vbhight = !$flowgcons ? 480 :
$flowgconTime ? 700 :
680;
my $vbox = "$vbminx $vbminy $vbwidth $vbhight";
my $ret = << "END0";
<style>
$css
@ -13973,7 +14010,7 @@ sub _flowGraphic {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="$vbox" style="$style" id="SVGPLOT">
<g transform="translate(400,50)">
<g transform="translate(400,200)">
<g>
<line class="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g>
@ -14001,33 +14038,50 @@ sub _flowGraphic {
<circle cx="0" cy="0" class="$sun_color" r="16" stroke-width="2"/>
</g>
<g id="home" fill="grey" transform="translate(352,310),scale(4)">
<g id="home" fill="grey" transform="translate(352,340),scale(4)">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</g>
<g id="grid" class="$grid_color" transform="translate(215,150),scale(3.0)">
<g id="grid" class="$grid_color" transform="translate(215,260),scale(3.0)">
<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>
END0
## get consumer list and display in Graphics
##############################################
## Producer Liste und Icons in Grafik anzeigen
################################################
my $pos_left = 0;
my $consumercount = 0;
my $consumer_start = 0;
my $currentPower = 0;
my @consumers;
if ($flowgcons) {
my $type = $paref->{type};
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;
my $producer_start = 0;
my $producerPower = 0;
if ($flowgprods) {
if ($producercount % 2) {
$producer_start = 350 - ($consDist * (($producercount -1) / 2));
}
else {
$producer_start = 350 - (($consDist / 2) * ($producercount-1));
}
$consumercount = scalar @consumers;
$pos_left = $producer_start + 25;
for my $prnxnum (@producers) {
my $palias = CurrentVal ($hash, 'aliasp'.$prnxnum, 'Producer'.$prnxnum);
my $picon = CurrentVal ($hash, 'iconp'.$prnxnum, $prodicondef); # Icon des Producerdevices
$ret .= '<g id="producer_'.$prnxnum.'" fill="grey" transform="translate('.$pos_left.',0),scale(0.15)">';
$ret .= "<title>$palias</title>".FW_makeImage($picon, '');
$ret .= '</g> ';
$pos_left += $consDist;
}
}
## Consumer Liste und Icons in Grafik anzeigen
###############################################
$pos_left = 0;
my $consumer_start = 0;
my $currentPower = 0;
if ($flowgcons) {
if ($consumercount % 2) {
$consumer_start = 350 - ($consDist * (($consumercount -1) / 2));
}
@ -14050,10 +14104,13 @@ END0
$pos_left += $consDist;
}
}
## Batterie, PV, Netz Laufketten
##################################
if ($hasbat) {
$ret .= << "END1";
<g class="$bat_color" transform="translate(610,135),scale(.30) rotate (90)">
<g class="$bat_color" transform="translate(610,245),scale(.30) rotate (90)">
<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"/>
END1
@ -14067,38 +14124,71 @@ END1
if ($flowgconX) { # Dummy Consumer
my $dumcol = $cc_dummy <= 0 ? '@grey' : q{}; # Einfärbung Consumer Dummy
$ret .= '<g id="consumer_X" fill="grey" transform="translate(520,325),scale(0.09)">';
$ret .= '<g id="consumer_X" fill="grey" transform="translate(520,360),scale(0.09)">';
$ret .= "<title>consumer_X</title>".FW_makeImage('light_light_dim_100'.$dumcol, '');
$ret .= '</g> ';
}
}
$ret .= << "END2";
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none">
<path id="pv-home" class="$csc_style" d="M700,100 L700,510" />
<path id="pv-grid" class="$cgfi_style" d="M670,100 L490,270" />
<path id="grid-home" class="$cgc_style" d="$cgc_direction" />
$ret .= << "END2";
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none">
<path id="pv-home" class="$csc_style" d="M700,400 L700,580" />
<path id="pv-grid" class="$cgfi_style" d="M670,400 L490,480" />
<path id="grid-home" class="$cgc_style" d="$cgc_direction" />
END2
if ($hasbat) {
$ret .= << "END3";
<path id="bat-home" class="$batout_style" d="$batout_direction" />
<path id="pv-bat" class="$batin_style" d="M730,100 L910,270" />
<path id="pv-bat" class="$batin_style" d="M730,400 L910,480" />
END3
}
if ($flowgconX) { # Dummy Consumer
## Dummy Consumer Laufketten
##############################
if ($flowgconX) {
my $consumer_style = 'flowg inactive_out';
$consumer_style = 'flowg active_in' if($cc_dummy > 1);
my $chain_color = ""; # Farbe der Laufkette Consumer-Dummy
my $chain_color = ""; # Farbe der Laufkette Consumer-Dummy
if ($cc_dummy > 0.5) {
$chain_color = 'style="stroke: #'.substr(Color::pahColor(0,500,1000,$cc_dummy,[0,255,0, 127,255,0, 255,255,0, 255,127,0, 255,0,0]),0,6).';"';
#$chain_color = 'style="stroke: #DF0101;"';
}
$ret .= qq{<path id="home-consumer_X" class="$consumer_style" $chain_color d="M790,620 L930,620" />};
$ret .= qq{<path id="home-consumer_X" class="$consumer_style" $chain_color d="M790,690 L930,690" />};
}
## Producer Laufketten
########################
if ($flowgprods) {
$pos_left = $producer_start * 2;
my $pos_left_start_con = 0;
my $distance_con = 25;
if ($producercount % 2) {
$pos_left_start_con = 700 - ($distance_con * (($producercount -1) / 2));
}
else {
$pos_left_start_con = 700 - ((($distance_con ) / 2) * ($producercount-1));
}
for my $producer (@producers) {
my $power = CurrentVal ($hash, 'generationp'.$producer, 0);
my $consumer_style = 'flowg inactive_out';
$consumer_style = 'flowg active_out' if($power > 0);
my $chain_color = ""; # Farbe der Laufkette des Producers
if ($power > 0) {
#$chain_color = 'style="stroke: #'.substr(Color::pahColor(0,50,100,$power,[0,255,0, 127,255,0, 255,255,0, 255,127,0, 255,0,0]),0,6).';"';
$chain_color = 'style="stroke: darkorange;"';
}
$ret .= qq{<path id="genproducer_$producer " class="$consumer_style" $chain_color d=" M$pos_left,130 L$pos_left_start_con,200" />}; # Design Consumer Laufkette
$pos_left += ($consDist * 2);
$pos_left_start_con += $distance_con;
}
}
## Consumer Laufketten
########################
if ($flowgcons) {
@ -14129,32 +14219,80 @@ END3
my $chain_color = ""; # Farbe der Laufkette des Consumers
if ($p > 0.5) {
$chain_color = 'style="stroke: #'.substr(Color::pahColor(0,50,100,$p,[0,255,0, 127,255,0, 255,255,0, 255,127,0, 255,0,0]),0,6).';"';
$chain_color = 'style="stroke: #'.substr(Color::pahColor(0,50,100,$p,[0,255,0, 127,255,0, 255,255,0, 255,127,0, 255,0,0]),0,6).';"';
#$chain_color = 'style="stroke: #DF0101;"';
}
$ret .= qq{<path id="home-consumer_$c" class="$consumer_style" $chain_color d="M$pos_left_start,700 L$pos_left,850" />}; # Design Consumer Laufkette
$ret .= qq{<path id="home-consumer_$c" class="$consumer_style" $chain_color d="M$pos_left_start,780 L$pos_left,850" />}; # Design Consumer Laufkette
$pos_left += ($consDist * 2);
$pos_left_start += $distance;
}
}
## Angaben Dummy-Verbraucher
#############################
$cc_dummy = sprintf("%.0f",$cc_dummy);
## Textangaben an Grafikelementen
###################################
$ret .= qq{<text class="flowg text" id="pv-txt" x="800" y="15" style="text-anchor: start;">$cpv</text>} if ($cpv);
$ret .= qq{<text class="flowg text" id="bat-txt" x="1110" y="300" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Ladungs Text
$ret .= qq{<text class="flowg text" id="pv_home-txt" x="730" y="300" style="text-anchor: start;">$csc</text>} if ($csc && $cpv);
$ret .= qq{<text class="flowg text" id="pv-grid-txt" x="525" y="200" style="text-anchor: end;">$cgfi</text>} if ($cgfi);
$ret .= qq{<text class="flowg text" id="grid-home-txt" x="515" y="420" style="text-anchor: end;">$cgc</text>} if ($cgc);
$ret .= qq{<text class="flowg text" id="batout-txt" x="880" y="420" style="text-anchor: start;">$batout</text>} if ($batout && $hasbat);
$ret .= qq{<text class="flowg text" id="batin-txt" x="880" y="200" style="text-anchor: start;">$batin</text>} if ($batin && $hasbat);
$ret .= qq{<text class="flowg text" id="home-txt" x="600" y="640" style="text-anchor: end;">$cc</text>}; # Current_Consumption Anlage
$ret .= qq{<text class="flowg text" id="dummy-txt" x="1085" y="640" style="text-anchor: start;">$cc_dummy</text>} if ($flowgconX && $flowgconPower); # Current_Consumption Dummy
$cc_dummy = sprintf("%.0f", $cc_dummy); # Verbrauch Dummy-Consumer
my $csc_ppall = $csc + $ppall;
$ret .= qq{<text class="flowg text" id="pv-txt" x="800" y="320" style="text-anchor: start;">$cpv</text>} if ($cpv);
$ret .= qq{<text class="flowg text" id="bat-txt" x="1110" y="520" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Text Batterieladungszustand
$ret .= qq{<text class="flowg text" id="pv_home-txt" x="730" y="520" style="text-anchor: start;">$csc_ppall</text>} if ($csc_ppall);
$ret .= qq{<text class="flowg text" id="pv-grid-txt" x="525" y="420" style="text-anchor: end;">$cgfi</text>} if ($cgfi);
$ret .= qq{<text class="flowg text" id="grid-home-txt" x="515" y="610" style="text-anchor: end;">$cgc</text>} if ($cgc);
$ret .= qq{<text class="flowg text" id="batout-txt" x="880" y="610" style="text-anchor: start;">$batout</text>} if ($batout && $hasbat);
$ret .= qq{<text class="flowg text" id="batin-txt" x="880" y="420" style="text-anchor: start;">$batin</text>} if ($batin && $hasbat);
$ret .= qq{<text class="flowg text" id="home-txt" x="600" y="710" style="text-anchor: end;">$cc</text>}; # Current_Consumption Anlage
$ret .= qq{<text class="flowg text" id="dummy-txt" x="1085" y="710" style="text-anchor: start;">$cc_dummy</text>} if ($flowgconX && $flowgconPower); # Current_Consumption Dummy
## Textangabe Producer
########################
if ($flowgprods) {
$pos_left = ($producer_start * 2) - 50; # -XX -> Start Lage producer Beschriftung
for my $prnxnum (@producers) {
$currentPower = sprintf "%.0f", CurrentVal ($hash, 'generationp'.$prnxnum, 0);
# Leistungszahl abhängig von der Größe entsprechend auf der x-Achse verschieben
###############################################################################
if (length($currentPower) >= 5) {
$pos_left -= 40;
}
elsif (length($currentPower) >= 4) {
$pos_left -= 25;
}
elsif (length($currentPower) >= 3 and $currentPower ne "0.0") {
$pos_left -= 5;
}
elsif (length($currentPower) >= 2 and $currentPower ne "0.0") {
$pos_left += 7;
}
elsif (length($currentPower) == 1) {
$pos_left += 25;
}
$ret .= qq{<text class="flowg text" id="producer-txt_$prnxnum" x="$pos_left" y="80">$currentPower</text>} if($flowgconPower); # Lage producer Consumption
# Leistungszahl abhängig von der Größe entsprechend auf der x-Achse wieder zurück an den Ursprungspunkt
#######################################################################################################
if (length($currentPower) >= 5) {
$pos_left += 40;
}
elsif (length($currentPower) >= 4) {
$pos_left += 25;
}
elsif (length($currentPower) >= 3 and $currentPower ne "0.0") {
$pos_left += 5;
}
elsif (length($currentPower) >= 2 and $currentPower ne "0.0") {
$pos_left -= 7;
}
elsif (length($currentPower) == 1) {
$pos_left -= 25;
}
$pos_left += ($consDist * 2);
}
}
## Consumer Anzeige
#####################
if ($flowgcons) {
@ -19873,11 +20011,11 @@ to ensure that the system configuration is correct.
<ul>
<table>
<colgroup> <col width="15%"> <col width="85%"> </colgroup>
<tr><td> <b>fix</b> </td><td>a uniquely determined factor is used (default) </td></tr>
<tr><td> <b>flex</b> </td><td>the factor is determined continuously on the basis of the sun's orbit </td></tr>
<tr><td> <b>flexShared</b> </td><td>as 'flex', additionally the proportion of direct radiation in the global radiation </td></tr>
<tr><td> <b> </td><td>is approximated and the area factor is only applied to this proportion </td></tr>
<colgroup> <col width="12%"> <col width="88%"> </colgroup>
<tr><td> <b>fix</b> </td><td>a uniquely determined area factor is used (default) </td></tr>
<tr><td> <b>trackFull</b> </td><td>the area factor is calculated continuously depending on the position of the sun and applied to the total global radiation </td></tr>
<tr><td> <b>trackShared</b> </td><td>the area factor is calculated continuously depending on the position of the sun and applied to an approximated </td></tr>
<tr><td> <b> </td><td>proportion of the direct radiation in the global radiation </td></tr>
</table>
</ul>
</li>
@ -22219,11 +22357,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<ul>
<table>
<colgroup> <col width="15%"> <col width="85%"> </colgroup>
<tr><td> <b>fix</b> </td><td>es wird ein einmalig ermittelter Faktor verwendet (default) </td></tr>
<tr><td> <b>flex</b> </td><td>der Faktor wird auf Grundlage der Sonnenlaufbahn kontinuierlich ermittelt </td></tr>
<tr><td> <b>flexShared</b> </td><td>wie 'flex', zusätzlich wird der Antei der Direktstrahlung an der Globalstrahlung </td></tr>
<tr><td> <b> </td><td>approximiert und der Flächenfaktor nur auf diesen Anteil angewendet </td></tr>
<colgroup> <col width="12%"> <col width="88%"> </colgroup>
<tr><td> <b>fix</b> </td><td>es wird ein einmalig ermittelter Flächenfaktor verwendet (default) </td></tr>
<tr><td> <b>trackFull</b> </td><td>der Flächenfaktor wird kontinuierlich abhängig vom Sonnenstand berechnet und auf die gesamte Globalstrahlung angewendet </td></tr>
<tr><td> <b>trackShared</b> </td><td>der Flächenfaktor wird kontinuierlich abhängig vom Sonnenstand berechnet und auf einen approximierten Anteil der </td></tr>
<tr><td> <b> </td><td>Direktstrahlung an der Globalstrahlung angewendet </td></tr>
</table>
</ul>
</li>