76_SolarForecast: contrib V1.57.3

git-svn-id: https://svn.fhem.de/fhem/trunk@30217 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
DS_Starter
2025-08-25 20:42:49 +00:00
parent fcab6bad04
commit 8eef75f26e

View File

@@ -160,8 +160,10 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.57.3" => "24.08.2025 set default Performance Ratio PRDEF to 0.9, prevent crash when Victron API does not return an Array ". "1.57.3" => "25.08.2025 set default Performance Ratio PRDEF to 0.9, prevent crash when Victron API does not return an Array ".
"check global attribute dnsServer in all SF Models, expand plantControl->genPVdeviation for perspective change ", "check global attribute dnsServer in all SF Models, expand plantControl->genPVdeviation for perspective change ".
"Household consumption calculation uniformly converted to vector calculation ".
"new ctrlSpecialReadings->dummyConsumption ",
"1.57.2" => "15.08.2025 _attrconsumer: The validity of the components of the key etotal is checked ". "1.57.2" => "15.08.2025 _attrconsumer: The validity of the components of the key etotal is checked ".
"_transferMeterValues: modul accept meter reset > 0 at day start ", "_transferMeterValues: modul accept meter reset > 0 at day start ",
"1.57.1" => "10.08.2025 fix warning, Forum: https://forum.fhem.de/index.php?msg=1346055 ", "1.57.1" => "10.08.2025 fix warning, Forum: https://forum.fhem.de/index.php?msg=1346055 ",
@@ -972,10 +974,10 @@ my %hqtxt = ( # H
DE => qq{produziert wie vorhergesagt 😊} }, DE => qq{produziert wie vorhergesagt 😊} },
pltp => { EN => qq{produced less than predicted 😓}, pltp => { EN => qq{produced less than predicted 😓},
DE => qq{weniger produziert als vorhergesagt 😓} }, DE => qq{weniger produziert als vorhergesagt 😓} },
wusond => { EN => qq{wait until sunset}, wusond => { EN => qq{waiting for data ...},
DE => qq{bis zum Sonnenuntergang warten} }, DE => qq{warte auf Daten ...} },
snbefb => { EN => qq{Should not be empty. Maybe the device has just been redefined.}, snbefb => { EN => qq{the data will be available tomorrow},
DE => qq{Sollte nicht leer sein. Vielleicht wurde das Device erst neu definiert.} }, DE => qq{die Daten werden morgen verfügbar sein} },
scnp => { EN => qq{Scheduling of the consumer is not provided}, scnp => { EN => qq{Scheduling of the consumer is not provided},
DE => qq{Die Einplanung des Verbrauchers ist nicht vorgesehen} }, DE => qq{Die Einplanung des Verbrauchers ist nicht vorgesehen} },
vrmcr => { EN => qq{Please set the Victron VRM Portal credentials with "set LINK vrmCredentials".}, vrmcr => { EN => qq{Please set the Victron VRM Portal credentials with "set LINK vrmCredentials".},
@@ -1133,8 +1135,8 @@ my %htitles = (
DE => qq{nicht bewertet} }, DE => qq{nicht bewertet} },
aimstt => { EN => qq{Perl module AI::DecisionTree is missing}, aimstt => { EN => qq{Perl module AI::DecisionTree is missing},
DE => qq{Perl Modul AI::DecisionTree ist nicht vorhanden} }, DE => qq{Perl Modul AI::DecisionTree ist nicht vorhanden} },
dumtxt => { EN => qq{Consumption that cannot be allocated to registered consumers}, dumtxt => { EN => qq{unassignable consumption (takes into account any hidden consumers)},
DE => qq{Verbrauch der den registrierten Verbrauchern nicht zugeordnet werden kann} }, DE => qq{nicht zuordenbarer Verbrauch (berücksichtigt evtl. versteckte Verbraucher)} },
rdcactiv => { EN => qq{Plant derating active}, rdcactiv => { EN => qq{Plant derating active},
DE => qq{Anlagenabregelung aktiv} }, DE => qq{Anlagenabregelung aktiv} },
rdcnoact => { EN => qq{no Plant derating}, rdcnoact => { EN => qq{no Plant derating},
@@ -1383,6 +1385,7 @@ my %hcsr = (
runTimeLastAPIAnswer => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => '-' }, runTimeLastAPIAnswer => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => '-' },
runTimeLastAPIProc => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => '-' }, runTimeLastAPIProc => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => '-' },
allStringsFullfilled => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => 0 }, allStringsFullfilled => { fnr => 2, fn => \&CurrentVal, par => '', par1 => '', unit => '', def => 0 },
dummyConsumption => { fnr => 2, fn => \&CurrentVal, par => 'dummyConsumption', par1 => '', unit => ' W', def => 0 },
todayConForecastTillSunset => { fnr => 2, fn => \&CurrentVal, par => 'tdConFcTillSunset', par1 => '', unit => ' Wh', def => 0 }, todayConForecastTillSunset => { fnr => 2, fn => \&CurrentVal, par => 'tdConFcTillSunset', par1 => '', unit => ' Wh', def => 0 },
runTimeTrainAI => { fnr => 3, fn => \&CircularVal, par => 99, par1 => '', unit => ' s', def => '-' }, runTimeTrainAI => { fnr => 3, fn => \&CircularVal, par => 99, par1 => '', unit => ' s', def => '-' },
todayConsumption => { fnr => 3, fn => \&CircularVal, par => 99, par1 => '', unit => ' Wh', def => 0 }, todayConsumption => { fnr => 3, fn => \&CircularVal, par => 99, par1 => '', unit => ' Wh', def => 0 },
@@ -12015,22 +12018,35 @@ sub _createSummaries {
$node2inv2dc += $pac2dc if($ifeed eq 'hybrid' || ($ifeed eq 'default' && $isource eq 'bat')); # AC->DC (Batterie- oder Hybrid-Wechselrichter) $node2inv2dc += $pac2dc if($ifeed eq 'hybrid' || ($ifeed eq 'default' && $isource eq 'bat')); # AC->DC (Batterie- oder Hybrid-Wechselrichter)
} }
my $othprod = 0; # Summe Otherproducer my $ppall = 0; # Summe Otherproducer
for my $pn (1..MAXPRODUCER) { # Erzeugung sonstiger Producer hinzufügen for my $pn (1..MAXPRODUCER) { # Erzeugung sonstiger Producer hinzufügen
$pn = sprintf "%02d", $pn; $pn = sprintf "%02d", $pn;
$othprod += ProducerVal ($name, $pn, 'pgeneration', 0); $ppall += ProducerVal ($name, $pn, 'pgeneration', 0);
} }
my $consumption = sprintf "%.0f", ($pv2node + $pv2bat + $othprod - $gfeedin + $gcon - $batin + $batout); # ohne PV2Grid my $vector = __calcVectorConsumption ( { name => $name,
batout => $batout,
batin => $batin,
pv2bat => $pv2bat,
pv2node => $pv2node,
dc2inv2node => $dc2inv2node,
node2inv2dc => $node2inv2dc,
ppall => $ppall,
gfeedin => $gfeedin,
gcon => $gcon
}
);
my $consumption = $vector->{vectorconsumption};
my $selfconsumption = sprintf "%.0f", ($pv2node + $pv2bat - $gfeedin - $batin); my $selfconsumption = sprintf "%.0f", ($pv2node + $pv2bat - $gfeedin - $batin);
$selfconsumption = $selfconsumption < 0 ? 0 : $selfconsumption; $selfconsumption = $selfconsumption < 0 ? 0 : $selfconsumption;
my $surplus = sprintf "%.0f", ($pv2node - $pv2grid + $othprod - $consumption); # aktueller Überschuß my $surplus = sprintf "%.0f", ($pv2node - $pv2grid + $ppall - $consumption); # aktueller Überschuß
$surplus = 0 if($surplus < 0); # wegen Vergleich nompower vs. surplus $surplus = 0 if($surplus < 0); # wegen Vergleich nompower vs. surplus
if ($debug =~ /collectData/xs) { if ($debug =~ /collectData/xs) {
Log3 ($name, 1, "$name DEBUG> current Power values -> PV2Node: $pv2node W, PV2Bat: $pv2bat, PV2Grid: $pv2grid W, Other: $othprod W, GridIn: $gfeedin W, GridCon: $gcon W"); Log3 ($name, 1, "$name DEBUG> current Power values -> PV2Node: $pv2node W, PV2Bat: $pv2bat, PV2Grid: $pv2grid W, Other: $ppall W, GridIn: $gfeedin W, GridCon: $gcon W");
Log3 ($name, 1, "$name DEBUG> current Power Battery -> BatIn: $batin W (Node2Inv2DC: $node2inv2dc W), BatOut: $batout W (DC2Inv2Node: $dc2inv2node W)"); Log3 ($name, 1, "$name DEBUG> current Power Battery -> BatIn: $batin W (Node2Inv2DC: $node2inv2dc W), BatOut: $batout W (DC2Inv2Node: $dc2inv2node W)");
Log3 ($name, 1, "$name DEBUG> current Consumption result -> $consumption W"); Log3 ($name, 1, "$name DEBUG> current Consumption result -> $consumption W");
} }
@@ -12052,8 +12068,8 @@ sub _createSummaries {
push @{$data{$name}{current}{surplusslidereg}}, $surplus; # Schieberegister PV Überschuß push @{$data{$name}{current}{surplusslidereg}}, $surplus; # Schieberegister PV Überschuß
limitArray ($data{$name}{current}{surplusslidereg}, SPLSLIDEMAX); limitArray ($data{$name}{current}{surplusslidereg}, SPLSLIDEMAX);
storeReading ('Current_GridFeedIn', (int $gfeedin). ' W'); # V 1.37.0 storeReading ('Current_GridFeedIn', (sprintf "%.0f", $gfeedin). ' W');
storeReading ('Current_GridConsumption', (int $gcon). ' W'); # V 1.37.0 storeReading ('Current_GridConsumption', (sprintf "%.0f", $gcon). ' W');
storeReading ('Current_Consumption', $consumption. ' W'); storeReading ('Current_Consumption', $consumption. ' W');
storeReading ('Current_SelfConsumption', $selfconsumption. ' W'); storeReading ('Current_SelfConsumption', $selfconsumption. ' W');
storeReading ('Current_SelfConsumptionRate', $selfconsumptionrate. ' %'); storeReading ('Current_SelfConsumptionRate', $selfconsumptionrate. ' %');
@@ -12062,19 +12078,81 @@ sub _createSummaries {
storeReading ('Today_PVreal', $pvre. ' Wh'); storeReading ('Today_PVreal', $pvre. ' Wh');
storeReading ('Tomorrow_ConsumptionForecast', $tconsum. ' Wh') if(defined $tconsum); storeReading ('Tomorrow_ConsumptionForecast', $tconsum. ' Wh') if(defined $tconsum);
storeReading ('NextHours_Sum01_PVforecast', (int $next1HoursSum->{PV}). ' Wh'); storeReading ('NextHours_Sum01_PVforecast', (sprintf "%.0f", $next1HoursSum->{PV}). ' Wh');
storeReading ('NextHours_Sum02_PVforecast', (int $next2HoursSum->{PV}). ' Wh'); storeReading ('NextHours_Sum02_PVforecast', (sprintf "%.0f", $next2HoursSum->{PV}). ' Wh');
storeReading ('NextHours_Sum03_PVforecast', (int $next3HoursSum->{PV}). ' Wh'); storeReading ('NextHours_Sum03_PVforecast', (sprintf "%.0f", $next3HoursSum->{PV}). ' Wh');
storeReading ('NextHours_Sum04_PVforecast', (int $next4HoursSum->{PV}). ' Wh'); storeReading ('NextHours_Sum04_PVforecast', (sprintf "%.0f", $next4HoursSum->{PV}). ' Wh');
storeReading ('RestOfDayPVforecast', (int $restOfDaySum->{PV}). ' Wh'); storeReading ('RestOfDayPVforecast', (sprintf "%.0f", $restOfDaySum->{PV}). ' Wh');
storeReading ('Tomorrow_PVforecast', (int $tomorrowSum->{PV}). ' Wh'); storeReading ('Tomorrow_PVforecast', (sprintf "%.0f", $tomorrowSum->{PV}). ' Wh');
storeReading ('Today_PVforecast', (int $todaySumFc->{PV}). ' Wh'); storeReading ('Today_PVforecast', (sprintf "%.0f", $todaySumFc->{PV}). ' Wh');
storeReading ('NextHours_Sum04_ConsumptionForecast', (int $next4HoursSum->{Consumption}).' Wh'); storeReading ('NextHours_Sum04_ConsumptionForecast', (sprintf "%.0f", $next4HoursSum->{Consumption}).' Wh');
storeReading ('RestOfDayConsumptionForecast', (int $restOfDaySum->{Consumption}). ' Wh'); storeReading ('RestOfDayConsumptionForecast', (sprintf "%.0f", $restOfDaySum->{Consumption}). ' Wh');
return; return;
} }
################################################################
# Hausverbrauch aus dem Leistungsfluß in/aus Knoten ermitteln
# (erfasst auch Verlustleistung in den Batteriewechselrichtern)
# und alternativ linear
# alles ohne PV2Grid
################################################################
sub __calcVectorConsumption {
my $paref = shift;
my $name = $paref->{name};
my $batout = $paref->{batout};
my $batin = $paref->{batin};
my $pv2bat = $paref->{pv2bat};
my $pv2node = $paref->{pv2node};
my $dc2inv2node = $paref->{dc2inv2node};
my $node2inv2dc = $paref->{node2inv2dc};
my $ppall = $paref->{ppall};
my $gfeedin = $paref->{gfeedin};
my $gcon = $paref->{gcon};
my $vector;
$vector->{batDischarge2HomeNode} = 0;
my $node2bat = 0; # Verbindung Inv.Knoten <-> Batterie ((-) Bat -> Knoten, (+) Knoten -> Bat)
my $bat2home = 0;
## Vectorverbrauch
####################
if ($batout || $batin) { # Batterie wird geladen oder entladen
$node2bat = ($batin - $batout) - $pv2bat + $dc2inv2node - $node2inv2dc; # positiv: Richtung Inverter Knoten -> Bat, negativ: Richtung Bat -> Inverter Knoten
$node2bat = 0 if(($dc2inv2node || $node2inv2dc) && $node2bat != 0);
if ($node2bat < 0 && !$dc2inv2node && !$pv2bat) { # Batterieentladung direkt ins Hausnetz wenn kein Batterie- / Hybridwechselrichter und kein Batterieladegerät aktiv
$bat2home = abs $node2bat;
$node2bat = 0;
$vector->{batDischarge2HomeNode} = 1;
}
}
else {
$node2bat = $dc2inv2node - $pv2bat; # falls Batterie Idle und Smartloader arbeitet
$node2bat = 0 if($dc2inv2node && $node2bat > 0); # muß negativ (0) sein: Richtung Bat -> Inv.Knoten, wichtig zur Festlegung Richtung und Inv. Knoten Summierung
}
my $pnodesum = $ppall + $pv2node + $dc2inv2node - $node2inv2dc; # Erzeugung Summe im Inverter-Knoten
$pnodesum += $node2bat < 0 ? abs $node2bat : 0; # z.B. Batterie ist voll und SolarLader liefert an Knoten
$pnodesum = __normDecPlaces ($pnodesum);
my $node2home = $pnodesum - $gfeedin - ($node2bat > 0 ? $node2bat : 0); # Energiefluß vom Knoten zum Haus
$node2home = __normDecPlaces ($node2home);
$vector->{vectorconsumption} = sprintf "%.0f", ($gcon + $node2home + $bat2home); # V 1.52.0 Anpassung Consumption wegen Verlustleistungsdifferenzen
## Linearverbrauch
####################
$vector->{linearconsumption} = sprintf "%.0f", ($pv2node + $pv2bat + $ppall - $gfeedin + $gcon - $batin + $batout);
$vector->{bat2home} = $bat2home;
$vector->{pnodesum} = $pnodesum;
$vector->{node2home} = $node2home;
$vector->{node2bat} = $node2bat;
return $vector;
}
################################################################ ################################################################
# Consumer - Energieverbrauch aufnehmen # Consumer - Energieverbrauch aufnehmen
# - Masterdata ergänzen # - Masterdata ergänzen
@@ -12091,6 +12169,8 @@ sub _manageConsumerData {
my $nhour = $chour + 1; my $nhour = $chour + 1;
$paref->{nhour} = sprintf "%02d", $nhour; $paref->{nhour} = sprintf "%02d", $nhour;
my $pcurrsum = 0;
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) {
$paref->{consumer} = $c; $paref->{consumer} = $c;
my $consumer = ConsumerVal ($hash, $c, 'name', ''); my $consumer = ConsumerVal ($hash, $c, 'name', '');
@@ -12105,8 +12185,6 @@ sub _manageConsumerData {
if ($paread) { if ($paread) {
my $eup = $up =~ /^kW$/xi ? 1000 : 1; my $eup = $up =~ /^kW$/xi ? 1000 : 1;
$pcurr = ReadingsNum ($consumer, $paread, 0) * $eup; $pcurr = ReadingsNum ($consumer, $paread, 0) * $eup;
storeReading ("consumer${c}_currentPower", $pcurr.' W');
} }
## Verbrauch auslesen + speichern ## Verbrauch auslesen + speichern
@@ -12130,8 +12208,6 @@ sub _manageConsumerData {
$data{$name}{consumers}{$c}{old_etotal} = $etot; $data{$name}{consumers}{$c}{old_etotal} = $etot;
$data{$name}{consumers}{$c}{old_etottime} = $t; $data{$name}{consumers}{$c}{old_etottime} = $t;
storeReading ("consumer${c}_currentPower", $pcurr.' W');
} }
if (defined $ehist && $etot >= $ehist && ($etot - $ehist) >= $ethreshold) { if (defined $ehist && $etot >= $ehist && ($etot - $ehist) >= $ethreshold) {
@@ -12169,8 +12245,16 @@ sub _manageConsumerData {
delete $paref->{val}; delete $paref->{val};
} }
readingsDelete ($hash, "consumer${c}_currentPower") if(!$etotread && !$paread); if (!$etotread && !$paread) {
delete $data{$name}{consumers}{$c}{currpower};
readingsDelete ($hash, "consumer${c}_currentPower");
}
else {
$data{$name}{consumers}{$c}{currpower} = $pcurr;
storeReading ("consumer${c}_currentPower", $pcurr.' W');
}
$pcurrsum += $pcurr;
$paref->{pcurr} = $pcurr; $paref->{pcurr} = $pcurr;
__getAutomaticState ($paref); # Automatic Status des Consumers abfragen __getAutomaticState ($paref); # Automatic Status des Consumers abfragen
@@ -12232,6 +12316,8 @@ sub _manageConsumerData {
storeReading ("consumer${c}_planned_stop", $stoptime) if($stoptime); # Consumer Stop geplant storeReading ("consumer${c}_planned_stop", $stoptime) if($stoptime); # Consumer Stop geplant
} }
$data{$name}{current}{dummyConsumption} = CurrentVal ($name, 'consumption', 0) - $pcurrsum; # aktueller Verbrauch - Summe aller ConsumerPower
delete $paref->{consumer}; delete $paref->{consumer};
delete $paref->{nhour}; delete $paref->{nhour};
@@ -17898,13 +17984,11 @@ sub _flowGraphic {
my $exth2cdist = $paref->{flowgh2cDist}; # vertikaler Abstand Home -> Consumer Zeile my $exth2cdist = $paref->{flowgh2cDist}; # vertikaler Abstand Home -> Consumer Zeile
my $lang = $paref->{lang}; my $lang = $paref->{lang};
my $gconMetered = ReadingsNum ($name, 'Current_GridConsumption', 0); my $gconMetered = CurrentVal ($name, 'gridconsumption', 0);
my $node2gridMetered = ReadingsNum ($name, 'Current_GridFeedIn', 0); # vom Inverter-Knoten zum Grid my $node2gridMetered = CurrentVal ($name, 'gridfeedin', 0); # vom Inverter-Knoten zum Grid
my $cselfMetered = ReadingsNum ($name, 'Current_SelfConsumption', 0); my $cselfMetered = CurrentVal ($name, 'selfconsumption', 0);
my $consptn = CurrentVal ($name, 'consumption', 0);
my $showgenerators = CurrentVal ($name, 'showGenerators', 0); # Generatoren-Zeile anzeigen my $showgenerators = CurrentVal ($name, 'showGenerators', 0); # Generatoren-Zeile anzeigen
my $cons_dmy = $consptn;
my $scale = FGSCALEDEF; my $scale = FGSCALEDEF;
my $stna = $name; my $stna = $name;
$stna .= int (rand (1500)); $stna .= int (rand (1500));
@@ -17925,8 +18009,8 @@ sub _flowGraphic {
($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } ); ($err) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
next if($err); next if($err);
my $batinpow = ReadingsNum ($name, 'Current_PowerBatIn_'.$bn, undef); my $batinpow = BatteryVal ($name, $bn, 'bpowerin', undef);
my $batoutpow = ReadingsNum ($name, 'Current_PowerBatOut_'.$bn, undef); my $batoutpow = BatteryVal ($name, $bn, 'bpowerout', undef);
$batin += $batinpow if(defined $batinpow); $batin += $batinpow if(defined $batinpow);
$batout += $batoutpow if(defined $batoutpow); $batout += $batoutpow if(defined $batoutpow);
} }
@@ -18027,45 +18111,45 @@ sub _flowGraphic {
my $gconMetered_direction = "M250,515 L670,590"; my $gconMetered_direction = "M250,515 L670,590";
my $bat2home_direction = "M1200,515 L730,590"; my $bat2home_direction = "M1200,515 L730,590";
my $node2bat = 0; # Verbindung Inv.Knoten <-> Batterie ((-) Bat -> Knoten, (+) Knoten -> Bat) ## Knotensummen Erzeuger - Batterie - Home ermitteln -> Hausverbrauch ermitteln
my $bat2home = 0; #################################################################################
my $vector = __calcVectorConsumption ( { name => $name,
batout => $batout,
batin => $batin,
pv2bat => $pv2bat,
pv2node => $pv2node,
dc2inv2node => $dc2inv2node,
node2inv2dc => $node2inv2dc,
ppall => $ppall,
gfeedin => $node2gridMetered,
gcon => $gconMetered
}
);
if ($batout || $batin) { # Batterie wird geladen oder entladen my $consptn = $vector->{vectorconsumption};
$node2bat = ($batin - $batout) - $pv2bat + $dc2inv2node - $node2inv2dc; # positiv: Richtung Knoten -> Bat, negativ: Richtung Bat -> Inv.Knoten
$node2bat = 0 if(($dc2inv2node || $node2inv2dc) && $node2bat != 0);
if ($node2bat < 0 && !$dc2inv2node && !$pv2bat) { # Batterieentladung direkt ins Hausnetz wenn kein Batterie- / Hybridwechselrichter und kein Batterieladegerät aktiv if ($vector->{batDischarge2HomeNode}) {
$bat2home = abs $node2bat;
$node2bat = 0;
$bat2home_style = "$stna active_normal"; $bat2home_style = "$stna active_normal";
$bat2home_direction = "M1200,515 L730,590"; $bat2home_direction = "M1200,515 L730,590";
} }
}
else {
$node2bat = $dc2inv2node - $pv2bat; # falls Batterie Idle und Smartloader arbeitet
$node2bat = 0 if($dc2inv2node && $node2bat > 0); # muß negativ (0) sein: Richtung Bat -> Inv.Knoten, wichtig zur Festlegung Richtung und Inv. Knoten Summierung
}
## Knotensummen Erzeuger - Batterie - Home ermitteln my $bat2home = $vector->{bat2home}; # Batterie -> Hausknoten
###################################################### my $pnodesum = $vector->{pnodesum}; # Summe Inverterknoten
my $pnodesum = $ppall + $pv2node + $dc2inv2node - $node2inv2dc; # Erzeugung Summe im Inverter-Knoten my $node2home = $vector->{node2home}; # Inverterknoten -> Haus
$pnodesum += $node2bat < 0 ? abs $node2bat : 0; # z.B. Batterie ist voll und SolarLader liefert an Knoten my $node2bat = $vector->{node2bat}; # Inverterknoten -> Batterie
$pnodesum = __normDecPlaces ($pnodesum);
my $node2home = $pnodesum - $node2gridMetered - ($node2bat > 0 ? $node2bat : 0); # Energiefluß vom Knoten zum Haus
$node2home = __normDecPlaces ($node2home);
$consptn = $gconMetered + $node2home + $bat2home; # V 1.52.0 Anpassung Consumption wegen Verlustleistungsdifferenzen
## definierte Verbraucher ermitteln ## definierte Verbraucher ermitteln
##################################### #####################################
my $cnsmr = {}; # Consumer Hilfshash Referenz my $cnsmr = {}; # Consumer Hilfshash Referenz
my $concurpsum = 0; # Summierung aller Consumerverbräuche
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # definierte Verbraucher ermitteln for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # definierte Verbraucher ermitteln
next if(isConsumerNoshow ($hash, $c) =~ /[13]/xs); # auszublendende Consumer nicht berücksichtigen next if(isConsumerNoshow ($hash, $c) =~ /[13]/xs); # auszublendende Consumer nicht berücksichtigen
$cnsmr->{$c}{p} = ReadingsNum ($name, "consumer${c}_currentPower", 0); $cnsmr->{$c}{p} = ConsumerVal ($name, $c, 'currpower', 0);
$cnsmr->{$c}{shortalias} = ConsumerVal ($name, $c, 'aliasshort', ''); # Consumer Kurzalias $cnsmr->{$c}{shortalias} = ConsumerVal ($name, $c, 'aliasshort', ''); # Consumer Kurzalias
$cnsmr->{$c}{ptyp} = 'consumer'; $cnsmr->{$c}{ptyp} = 'consumer';
$concurpsum += $cnsmr->{$c}{p};
} }
my $consumercount = keys %{$cnsmr}; my $consumercount = keys %{$cnsmr};
@@ -18077,6 +18161,9 @@ sub _flowGraphic {
} }
values %{$cnsmr}; values %{$cnsmr};
## Verbrauch Dummy bestimmen
##############################
my $cons_dmy = $consptn - $concurpsum;
## Producer / Inverter Koordinaten Steuerhash ## Producer / Inverter Koordinaten Steuerhash
############################################### ###############################################
@@ -18222,7 +18309,6 @@ END0
} }
); );
$cons_dmy -= $cnsmrpower;
$cicon = FW_makeImage ($cicon, ''); $cicon = FW_makeImage ($cicon, '');
($scale, $cicon) = __normIconScale ($name, $cicon); ($scale, $cicon) = __normIconScale ($name, $cicon);
@@ -26744,6 +26830,7 @@ to ensure that the system configuration is correct.
<tr><td> <b>currentRunMtsConsumer_XX</b> </td><td>the running time (minutes) of the consumer "XX" since the last switch-on. (last running cycle) </td></tr> <tr><td> <b>currentRunMtsConsumer_XX</b> </td><td>the running time (minutes) of the consumer "XX" since the last switch-on. (last running cycle) </td></tr>
<tr><td> <b>dayAfterTomorrowPVforecast</b> </td><td>provides the forecast of PV generation for the day after tomorrow (if available) without autocorrection (raw data) </td></tr> <tr><td> <b>dayAfterTomorrowPVforecast</b> </td><td>provides the forecast of PV generation for the day after tomorrow (if available) without autocorrection (raw data) </td></tr>
<tr><td> <b>daysUntilBatteryCare_XX</b> </td><td>Days until the next battery XX maintenance (reaching the charge 'maxSoC' from attribute ctrlBatSocManagementXX) </td></tr> <tr><td> <b>daysUntilBatteryCare_XX</b> </td><td>Days until the next battery XX maintenance (reaching the charge 'maxSoC' from attribute ctrlBatSocManagementXX) </td></tr>
<tr><td> <b>dummyConsumption</b> </td><td>Provides the current household consumption that cannot be attributed to consumers. Also includes power loss components. </td></tr>
<tr><td> <b>lastretrieval_time</b> </td><td>the last retrieval time of the selected radiation data API </td></tr> <tr><td> <b>lastretrieval_time</b> </td><td>the last retrieval time of the selected radiation data API </td></tr>
<tr><td> <b>lastretrieval_timestamp</b> </td><td>the timestamp of the last retrieval time of the selected radiation data API </td></tr> <tr><td> <b>lastretrieval_timestamp</b> </td><td>the timestamp of the last retrieval time of the selected radiation data API </td></tr>
<tr><td> <b>remainingSurplsHrsMinPwrBat_XX</b> </td><td>the remaining number of hours on the current day in which the PV surplus (Wh) is higher than the </td></tr> <tr><td> <b>remainingSurplsHrsMinPwrBat_XX</b> </td><td>the remaining number of hours on the current day in which the PV surplus (Wh) is higher than the </td></tr>
@@ -27257,7 +27344,7 @@ to ensure that the system configuration is correct.
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>genPVdeviation</b> </td><td>Defines the method for calculating the deviation between forecast and actual PV generation. </td></tr> <tr><td> <b>genPVdeviation</b> </td><td>Defines the method for calculating the deviation between forecast and actual PV generation. </td></tr>
<tr><td> </td><td>The reading <b>Today_PVdeviation</b> is created depending on this setting. </td></tr> <tr><td> </td><td>The reading <b>Today_PVdeviation</b> is created depending on this setting. </td></tr>
<tr><td> </td><td>The optional addition :reverse specifies that PV generation > forecast is displayed as a positive value instead of a negative value (change of perspective). </td></tr> <tr><td> </td><td>The optional addition ':reverse' specifies that PV generation > forecast is evaluated as a positive value instead of a negative value (change of perspective). </td></tr>
<tr><td> </td><td><b>daily[:reverse]</b> - Calculation and creation of Today_PVdeviation takes place after sunset (default) </td></tr> <tr><td> </td><td><b>daily[:reverse]</b> - Calculation and creation of Today_PVdeviation takes place after sunset (default) </td></tr>
<tr><td> </td><td><b>continuously[:reverse]</b> - Calculation and creation of Today_PVdeviation is continuous </td></tr> <tr><td> </td><td><b>continuously[:reverse]</b> - Calculation and creation of Today_PVdeviation is continuous </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
@@ -29400,7 +29487,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> <b>conForecastTillNextSunrise</b> </td><td>Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang </td></tr> <tr><td> <b>conForecastTillNextSunrise</b> </td><td>Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang </td></tr>
<tr><td> <b>currentAPIinterval</b> </td><td>das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden </td></tr> <tr><td> <b>currentAPIinterval</b> </td><td>das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden </td></tr>
<tr><td> <b>currentRunMtsConsumer_XX</b> </td><td>die Laufzeit (Minuten) des Verbrauchers "XX" seit dem letzten Einschalten. (letzter Laufzyklus) </td></tr> <tr><td> <b>currentRunMtsConsumer_XX</b> </td><td>die Laufzeit (Minuten) des Verbrauchers "XX" seit dem letzten Einschalten. (letzter Laufzyklus) </td></tr>
<tr><td> <b>dayAfterTomorrowPVforecast</b> </td><td>liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten). </td></tr> <tr><td> <b>dayAfterTomorrowPVforecast</b> </td><td>Liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten). </td></tr>
<tr><td> <b>dummyConsumption</b> </td><td>Liefert den aktuellen, Verbrauchern nicht zuordenbaren Hausverbrauch. Enthält auch Verlustleistungsanteile. </td></tr>
<tr><td> <b>daysUntilBatteryCare_XX</b> </td><td>Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung 'maxSoC' aus Attribut ctrlBatSocManagementXX) </td></tr> <tr><td> <b>daysUntilBatteryCare_XX</b> </td><td>Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung 'maxSoC' aus Attribut ctrlBatSocManagementXX) </td></tr>
<tr><td> <b>lastretrieval_time</b> </td><td>der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API </td></tr> <tr><td> <b>lastretrieval_time</b> </td><td>der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API </td></tr>
<tr><td> <b>lastretrieval_timestamp</b> </td><td>der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API </td></tr> <tr><td> <b>lastretrieval_timestamp</b> </td><td>der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API </td></tr>
@@ -29913,7 +30001,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>genPVdeviation</b> </td><td>Legt die Methode zur Berechnung der Abweichung von prognostizierter und realer PV Erzeugung fest. </td></tr> <tr><td> <b>genPVdeviation</b> </td><td>Legt die Methode zur Berechnung der Abweichung von prognostizierter und realer PV Erzeugung fest. </td></tr>
<tr><td> </td><td>Das Reading <b>Today_PVdeviation</b> wird in Abhängigkeit dieser Einstellung erstellt. </td></tr> <tr><td> </td><td>Das Reading <b>Today_PVdeviation</b> wird in Abhängigkeit dieser Einstellung erstellt. </td></tr>
<tr><td> </td><td>Der optionale Zusatz ':reverse' legt fest, dass PV-Erzeugung > Prognose als positiver statt negativer Wert dargestellt wird (Perspektivwechsel). </td></tr> <tr><td> </td><td>Der optionale Zusatz ':reverse' legt fest, dass PV-Erzeugung > Prognose als positiver statt negativer Wert gewertet wird (Perspektivwechsel). </td></tr>
<tr><td> </td><td><b>daily[:reverse]</b> - Berechnung und Erstellung von Today_PVdeviation erfolgt nach Sonnenuntergang (default) </td></tr> <tr><td> </td><td><b>daily[:reverse]</b> - Berechnung und Erstellung von Today_PVdeviation erfolgt nach Sonnenuntergang (default) </td></tr>
<tr><td> </td><td><b>continuously[:reverse]</b> - Berechnung und Erstellung von Today_PVdeviation erfolgt fortlaufend </td></tr> <tr><td> </td><td><b>continuously[:reverse]</b> - Berechnung und Erstellung von Today_PVdeviation erfolgt fortlaufend </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>