2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-28 08:54:51 +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

View File

@ -50,8 +50,7 @@ use HttpUtils;
eval "use JSON;1;" or my $jsonabs = 'JSON'; ## no critic 'eval' # Debian: sudo apt-get install libjson-perl 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' eval "use AI::DecisionTree;1;" or my $aidtabs = 'AI::DecisionTree'; ## no critic 'eval'
use FHEM::SynoModules::SMUtils qw( use FHEM::SynoModules::SMUtils qw (checkModVer
checkModVer
evaljson evaljson
getClHash getClHash
delClHash delClHash
@ -68,8 +67,7 @@ use MIME::Base64;
BEGIN { BEGIN {
# Import from main:: # Import from main::
GP_Import( GP_Import(
qw( qw (attr
attr
asyncOutput asyncOutput
AnalyzePerlCommand AnalyzePerlCommand
AnalyzeCommandChain AnalyzeCommandChain
@ -162,7 +160,9 @@ my %vNotesIntern = (
"note in Reading pvCorrectionFactor_XX if AI prediction was used in relevant hour ". "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 ". "AI usage depending either of available number of rules or difference to api forecast ".
"minor fix in ___readCandQ, new experimental attribute ctrlAreaFactorUsage ". "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 ". "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)", "AI use (aiAccTRNMin, aiSpreadTRNMin)",
"1.33.0" => "26.09.2024 substitute area factor hash by ___areaFactorFix function ", "1.33.0" => "26.09.2024 substitute area factor hash by ___areaFactorFix function ",
@ -1205,7 +1205,7 @@ sub Initialize {
"ctrlBatSocManagement:textField-long ". "ctrlBatSocManagement:textField-long ".
"ctrlConsRecommendReadings:multiple-strict,$allcs ". "ctrlConsRecommendReadings:multiple-strict,$allcs ".
"ctrlDebug:multiple-strict,$dm,#14 ". "ctrlDebug:multiple-strict,$dm,#14 ".
"ctrlAreaFactorUsage:fix,flex,flexShared ". "ctrlAreaFactorUsage:fix,trackFull,trackShared ".
"ctrlGenPVdeviation:daily,continuously ". "ctrlGenPVdeviation:daily,continuously ".
"ctrlInterval ". "ctrlInterval ".
"ctrlLanguage:DE,EN ". "ctrlLanguage:DE,EN ".
@ -3315,13 +3315,9 @@ return;
################################################################################################## ##################################################################################################
# Abruf DWD Strahlungsdaten und Rohdaten ohne Korrektur # Abruf DWD Strahlungsdaten und Rohdaten ohne Korrektur
# speichern in solcastapi Hash
# #
# !!!! NACHFOLGENDE INFO GILT NUR BEI DWD RAD1H VERWENDUNG !!!! # Berechnung nach Formel 1 aus http://www.ing-büro-junge.de/html/photovoltaik.html
# ############################################################# # als Jahreserträge:
#
# PV Forecast Rad1h in kWh / Wh
# Berechnung nach Formel 1 aus http://www.ing-büro-junge.de/html/photovoltaik.html:
# #
# * Faktor für Umwandlung kJ in kWh: 0.00027778 # * Faktor für Umwandlung kJ in kWh: 0.00027778
# * Eigene Modulfläche in qm z.B.: 31,04 # * Eigene Modulfläche in qm z.B.: 31,04
@ -3348,7 +3344,7 @@ return;
# hier beschrieben: # hier beschrieben:
# https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden # https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
# #
# !!! PV Berechnungsgrundlagen !!! # PV Berechnungsgrundlagen
# https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/ertrag # https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/ertrag
# http://www.ing-büro-junge.de/html/photovoltaik.html # http://www.ing-büro-junge.de/html/photovoltaik.html
# #
@ -3417,7 +3413,7 @@ sub __getDWDSolarData {
my ($af, $pv, $sdr, $wcc); 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, ($af, $sdr, $wcc) = ___areaFactorTrack ( { name => $name,
day => $day, day => $day,
dday => $dday, dday => $dday,
@ -3429,6 +3425,7 @@ sub __getDWDSolarData {
); );
$wcc = 0 if(!isNumeric($wcc)); $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") debugLog ($paref, "apiProcess", "DWD API - Value of sunaz/sunalt not stored in pvHistory, workaround using 1.00/0.75")
if(!isNumeric($af)); if(!isNumeric($af));
@ -3436,7 +3433,7 @@ sub __getDWDSolarData {
$af = 1.00 if(!isNumeric($af)); $af = 1.00 if(!isNumeric($af));
$sdr = 0.75 if(!isNumeric($sdr)); $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 $dirrad = $rad * $sdr; # Anteil Direktstrahlung an Globalstrahlung
my $difrad = $rad - $dirrad; # Anteil Diffusstrahlung an Globalstrahlung my $difrad = $rad - $dirrad; # Anteil Diffusstrahlung an Globalstrahlung
@ -5682,7 +5679,10 @@ sub __delProducerValues {
deleteReadingspec ($hash, ".*_PPreal".$prn); deleteReadingspec ($hash, ".*_PPreal".$prn);
readingsDelete ($hash, 'Current_PP'.$prn); readingsDelete ($hash, 'Current_PP'.$prn);
delete $data{$type}{$name}{current}{'generationp'.$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}}) { for my $hod (keys %{$data{$type}{$name}{circular}}) {
delete $data{$type}{$name}{circular}{$hod}{'pprl'.$prn}; 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 $dy (sort keys %{$data{$type}{$name}{pvhist}}) {
for my $hr (sort keys %{$data{$type}{$name}{pvhist}{$dy}}) { 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}; delete $data{$type}{$name}{pvhist}{$dy}{$hr}{'etotalp'.$prn};
} }
} }
@ -8455,9 +8455,9 @@ sub _transferProducerValues {
my $pu = $pcunit =~ /^kW$/xi ? 1000 : 1; my $pu = $pcunit =~ /^kW$/xi ? 1000 : 1;
my $p = ReadingsNum ($prdev, $pcread, 0) * $pu; # aktuelle Erzeugung (W) 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; $data{$type}{$name}{current}{'generationp'.$prn} = $p;
my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1; my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1;
@ -8482,6 +8482,8 @@ sub _transferProducerValues {
} }
$data{$type}{$name}{current}{'etotalp'.$prn} = $etotal; # aktuellen etotal des WR speichern $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) { if ($ethishour < 0) {
$ethishour = 0; $ethishour = 0;
@ -13878,6 +13880,7 @@ return $ret;
sub _flowGraphic { sub _flowGraphic {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $type = $paref->{type};
my $flowgsize = $paref->{flowgsize}; my $flowgsize = $paref->{flowgsize};
my $flowgani = $paref->{flowgani}; my $flowgani = $paref->{flowgani};
my $flowgshift = $paref->{flowgshift}; # Verschiebung der Flußgrafikbox (muß negiert werden) my $flowgshift = $paref->{flowgshift}; # Verschiebung der Flußgrafikbox (muß negiert werden)
@ -13888,80 +13891,114 @@ sub _flowGraphic {
my $consDist = $paref->{flowgconsDist}; my $consDist = $paref->{flowgconsDist};
my $css = $paref->{css}; 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 $hash = $defs{$name};
my $style = 'width:98%; height:'.$flowgsize.'px;'; my $style = 'width:98%; height:'.$flowgsize.'px;';
my $animation = $flowgani ? '@keyframes dash { to { stroke-dashoffset: 0; } }' : ''; # Animation Ja/Nein my $animation = $flowgani ? '@keyframes dash { to { stroke-dashoffset: 0; } }' : ''; # Animation Ja/Nein
my $cpv = ReadingsNum ($name, 'Current_PV', 0);
my $cgc = ReadingsNum ($name, 'Current_GridConsumption', 0); my $cgc = ReadingsNum ($name, 'Current_GridConsumption', 0);
my $cgfi = ReadingsNum ($name, 'Current_GridFeedIn', 0); my $cgfi = ReadingsNum ($name, 'Current_GridFeedIn', 0);
my $csc = ReadingsNum ($name, 'Current_SelfConsumption', 0); my $csc = ReadingsNum ($name, 'Current_SelfConsumption', 0);
my $cc = CurrentVal ($hash, 'consumption', 0); my $cc = CurrentVal ($hash, 'consumption', 0);
my $gp01 = CurrentVal ($hash, 'generationp01', 0); my $cpv = ReadingsNum ($name, 'Current_PV', 0);
my $gp02 = CurrentVal ($hash, 'generationp02', 0);
my $gp03 = CurrentVal ($hash, 'generationp03', 0);
my $cc_dummy = $cc;
my $batin = ReadingsNum ($name, 'Current_PowerBatIn', undef); my $batin = ReadingsNum ($name, 'Current_PowerBatIn', undef);
my $batout = ReadingsNum ($name, 'Current_PowerBatOut', undef); my $batout = ReadingsNum ($name, 'Current_PowerBatOut', undef);
my $soc = ReadingsNum ($name, 'Current_BatCharge', 100); 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);
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;
}
$flowgcons = 0 if(!$consumercount); # Consumer Anzeige ausschalten wenn keine Consumer definiert
## Batterie + Werte festlegen
###############################
my $bat_color = $soc < 26 ? 'flowg bat25' : my $bat_color = $soc < 26 ? 'flowg bat25' :
$soc < 76 ? 'flowg bat50' : $soc < 76 ? 'flowg bat50' :
'flowg bat75'; 'flowg bat75';
my $hasbat = 1;
if (!defined($batin) && !defined($batout)) { if (!defined($batin) && !defined($batout)) {
$hasbat = 0; $hasbat = 0;
$batin = 0; $batin = 0;
$batout = 0; $batout = 0;
$soc = 0; $soc = 0;
} }
else {
#$csc -= $batout;
}
my $grid_color = $cgfi ? 'flowg grid_color1' : 'flowg grid_color2'; 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 $cgc_style = $cgc ? 'flowg active_in' : 'flowg inactive_in';
my $batout_style = $batout ? 'flowg active_out active_bat_out' : '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) { # Batterie wird entladen
if ($batout) {
my $cgfo = $cgfi - $cpv; my $cgfo = $cgfi - $cpv;
if($cgfo > 1) { if ($cgfo > 1) {
$cgc_style = 'flowg active_out'; $cgc_style = 'flowg active_out';
$cgc_direction = 'M670,510 L490,305'; $cgc_direction = 'M670,590 L490,515';
$cgfi -= $cgfo; $cgfi -= $cgfo;
$cgc = $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; my $gbi = $batin - $cpv;
if ($gbi > 1) { if ($gbi > 1) { # Batterieladung anteilig aus Hausnetz geladen
$batin -= $gbi; $batin -= $gbi;
$batout_style = 'flowg active_in'; $batout_style = 'flowg active_in';
$batout_direction = 'M730,510 L902,305'; $batout_direction = 'M730,590 L902,515';
$batout = $gbi; $batout = $gbi;
} }
} }
## SVG Box initialisieren
###########################
my $sun_color = $cpv ? 'flowg sun_active' : 'flowg sun_inactive'; my $sun_color = $cpv ? 'flowg sun_active' : 'flowg sun_inactive';
my $batin_style = $batin ? 'flowg active_in active_bat_in' : 'flowg inactive_out'; 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 $csc_style = $csc && ($cpv || $ppall) ? 'flowg active_out' : 'flowg inactive_out';
my $cgfi_style = $cgfi ? 'flowg active_out' : 'flowg inactive_out'; my $cgfi_style = $cgfi ? 'flowg active_out' : 'flowg inactive_out';
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 $vbwidth = 800; # width and height specify the viewBox size
my $vbhight = !$flowgcons ? 480 : my $vbminx = -10 * $flowgshift; # min-x and min-y represent the smallest X and Y coordinates that the viewBox may have
$flowgconTime ? 700 : my $vbminy = $flowgprods ? -25 : 100;
680;
my $vbhight = !$flowgcons ? 380 :
!$flowgconTime ? 590 :
610;
$vbhight += 100 if($flowgprods);
my $vbox = "$vbminx $vbminy $vbwidth $vbhight"; my $vbox = "$vbminx $vbminy $vbwidth $vbhight";
@ -13973,7 +14010,7 @@ sub _flowGraphic {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="$vbox" style="$style" id="SVGPLOT"> <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> <g>
<line class="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" /> <line class="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
</g> </g>
@ -14001,33 +14038,50 @@ sub _flowGraphic {
<circle cx="0" cy="0" class="$sun_color" r="16" stroke-width="2"/> <circle cx="0" cy="0" class="$sun_color" r="16" stroke-width="2"/>
</g> </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"/> <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</g> </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"/> <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>
END0 END0
## get consumer list and display in Graphics ## Producer Liste und Icons in Grafik anzeigen
############################################## ################################################
my $pos_left = 0; my $pos_left = 0;
my $consumercount = 0; my $producer_start = 0;
my $consumer_start = 0; my $producerPower = 0;
my $currentPower = 0;
my @consumers;
if ($flowgcons) { if ($flowgprods) {
my $type = $paref->{type}; if ($producercount % 2) {
$producer_start = 350 - ($consDist * (($producercount -1) / 2));
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 else {
push @consumers, $c; $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) { if ($consumercount % 2) {
$consumer_start = 350 - ($consDist * (($consumercount -1) / 2)); $consumer_start = 350 - ($consDist * (($consumercount -1) / 2));
} }
@ -14051,9 +14105,12 @@ END0
} }
} }
## Batterie, PV, Netz Laufketten
##################################
if ($hasbat) { if ($hasbat) {
$ret .= << "END1"; $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 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"/> <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 END1
@ -14067,36 +14124,69 @@ END1
if ($flowgconX) { # Dummy Consumer if ($flowgconX) { # Dummy Consumer
my $dumcol = $cc_dummy <= 0 ? '@grey' : q{}; # Einfärbung Consumer Dummy 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 .= "<title>consumer_X</title>".FW_makeImage('light_light_dim_100'.$dumcol, '');
$ret .= '</g> '; $ret .= '</g> ';
} }
$ret .= << "END2"; $ret .= << "END2";
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none"> <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-home" class="$csc_style" d="M700,400 L700,580" />
<path id="pv-grid" class="$cgfi_style" d="M670,100 L490,270" /> <path id="pv-grid" class="$cgfi_style" d="M670,400 L490,480" />
<path id="grid-home" class="$cgc_style" d="$cgc_direction" /> <path id="grid-home" class="$cgc_style" d="$cgc_direction" />
END2 END2
if ($hasbat) { if ($hasbat) {
$ret .= << "END3"; $ret .= << "END3";
<path id="bat-home" class="$batout_style" d="$batout_direction" /> <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 END3
} }
if ($flowgconX) { # Dummy Consumer ## Dummy Consumer Laufketten
##############################
if ($flowgconX) {
my $consumer_style = 'flowg inactive_out'; my $consumer_style = 'flowg inactive_out';
$consumer_style = 'flowg active_in' if($cc_dummy > 1); $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) { 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: #'.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;"'; #$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 ## Consumer Laufketten
@ -14133,27 +14223,75 @@ END3
#$chain_color = 'style="stroke: #DF0101;"'; #$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 += ($consDist * 2);
$pos_left_start += $distance; $pos_left_start += $distance;
} }
} }
## Angaben Dummy-Verbraucher
#############################
$cc_dummy = sprintf("%.0f",$cc_dummy);
## Textangaben an Grafikelementen ## Textangaben an Grafikelementen
################################### ###################################
$ret .= qq{<text class="flowg text" id="pv-txt" x="800" y="15" style="text-anchor: start;">$cpv</text>} if ($cpv); $cc_dummy = sprintf("%.0f", $cc_dummy); # Verbrauch Dummy-Consumer
$ret .= qq{<text class="flowg text" id="bat-txt" x="1110" y="300" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Ladungs Text my $csc_ppall = $csc + $ppall;
$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-txt" x="800" y="320" style="text-anchor: start;">$cpv</text>} if ($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="bat-txt" x="1110" y="520" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Text Batterieladungszustand
$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="pv_home-txt" x="730" y="520" style="text-anchor: start;">$csc_ppall</text>} if ($csc_ppall);
$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="pv-grid-txt" x="525" y="420" style="text-anchor: end;">$cgfi</text>} if ($cgfi);
$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="grid-home-txt" x="515" y="610" style="text-anchor: end;">$cgc</text>} if ($cgc);
$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="batout-txt" x="880" y="610" style="text-anchor: start;">$batout</text>} if ($batout && $hasbat);
$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 $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 ## Consumer Anzeige
##################### #####################
@ -19873,11 +20011,11 @@ to ensure that the system configuration is correct.
<ul> <ul>
<table> <table>
<colgroup> <col width="15%"> <col width="85%"> </colgroup> <colgroup> <col width="12%"> <col width="88%"> </colgroup>
<tr><td> <b>fix</b> </td><td>a uniquely determined factor is used (default) </td></tr> <tr><td> <b>fix</b> </td><td>a uniquely determined area 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>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>flexShared</b> </td><td>as 'flex', additionally the proportion of direct radiation in the 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>is approximated and the area factor is only applied to this proportion </td></tr> <tr><td> <b> </td><td>proportion of the direct radiation in the global radiation </td></tr>
</table> </table>
</ul> </ul>
</li> </li>
@ -22219,11 +22357,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<ul> <ul>
<table> <table>
<colgroup> <col width="15%"> <col width="85%"> </colgroup> <colgroup> <col width="12%"> <col width="88%"> </colgroup>
<tr><td> <b>fix</b> </td><td>es wird ein einmalig ermittelter Faktor verwendet (default) </td></tr> <tr><td> <b>fix</b> </td><td>es wird ein einmalig ermittelter Flächenfaktor 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>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>flexShared</b> </td><td>wie 'flex', zusätzlich wird der Antei der Direktstrahlung an der Globalstrahlung </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>approximiert und der Flächenfaktor nur auf diesen Anteil angewendet </td></tr> <tr><td> <b> </td><td>Direktstrahlung an der Globalstrahlung angewendet </td></tr>
</table> </table>
</ul> </ul>
</li> </li>