2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-25 03:44:52 +00:00

76_SolarForecast: max. possible inverters set to 4

git-svn-id: https://svn.fhem.de/fhem/trunk@29678 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2025-02-19 20:46:07 +00:00
parent c9498a0e9f
commit eb4023db4d
3 changed files with 150 additions and 109 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it # Do not insert empty lines here, update check depends on it
- feature: 76_SolarForecast: max. possible inverters set to 4
- feature: 98_vitoconnect.pm: enhanced error mapping - feature: 98_vitoconnect.pm: enhanced error mapping
now also language dependent now also language dependent
- bugfix: 98_vitoconnect.pm: closing of file_handles, removed JSON::XS - bugfix: 98_vitoconnect.pm: closing of file_handles, removed JSON::XS

View File

@ -159,6 +159,8 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.46.2" => "19.02.2025 aiAddRawData: save original data and sort to bin in sub aiAddInstancePV instead, _calcConsForecast_circular: include epiecAVG ".
"fix NOTIFYDEV for consumers, change MAXINVERTER to 4 ",
"1.46.1" => "18.02.2025 improve temp2bin, correct Log output to consumptionHistory, set setupStringDeclination can be free integer between 0..90 ", "1.46.1" => "18.02.2025 improve temp2bin, correct Log output to consumptionHistory, set setupStringDeclination can be free integer between 0..90 ",
"1.46.0" => "17.02.2025 Notification System: print out last/next file pull if no messages are present, improvements and activation of ". "1.46.0" => "17.02.2025 Notification System: print out last/next file pull if no messages are present, improvements and activation of ".
"_calcConsForecast_circular, checkPlantConfig: add Data Memory check pvHistory 'con' ". "_calcConsForecast_circular, checkPlantConfig: add Data Memory check pvHistory 'con' ".
@ -385,7 +387,7 @@ use constant {
MAXBATTERIES => 3, # maximale Anzahl der möglichen Batterien MAXBATTERIES => 3, # maximale Anzahl der möglichen Batterien
MAXCONSUMER => 16, # maximale Anzahl der möglichen Consumer (Attribut) MAXCONSUMER => 16, # maximale Anzahl der möglichen Consumer (Attribut)
MAXPRODUCER => 3, # maximale Anzahl der möglichen anderen Produzenten (Attribut) MAXPRODUCER => 3, # maximale Anzahl der möglichen anderen Produzenten (Attribut)
MAXINVERTER => 3, # maximale Anzahl der möglichen Inverter MAXINVERTER => 4, # maximale Anzahl der möglichen Inverter
MAXSOCDEF => 95, # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt MAXSOCDEF => 95, # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt
CARECYCLEDEF => 20, # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen CARECYCLEDEF => 20, # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen
@ -1765,8 +1767,8 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
return; return;
} }
my $startts = time; my $startts = time;
my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME); my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME);
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
@ -5892,7 +5894,7 @@ sub _attrctrlDebug { ## no critic "not used"
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $aName = $paref->{aName}; my $aName = $paref->{aName};
my $aVal = $paref->{aVal}; my $aVal = $paref->{aVal} // '';
my $te = 'consumerSwitching'; my $te = 'consumerSwitching';
@ -11820,15 +11822,15 @@ sub __getCyclesAndRuntime {
if (isConsumerLogOn ($hash, $c, $pcurr)) { # Verbraucher ist logisch "an" if (isConsumerLogOn ($hash, $c, $pcurr)) { # Verbraucher ist logisch "an"
if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'off') { # Status im letzen Zyklus war "off" if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'off') { # Status im letzen Zyklus war "off"
$data{$name}{consumers}{$c}{onoff} = 'on'; $data{$name}{consumers}{$c}{onoff} = 'on';
$data{$name}{consumers}{$c}{startTime} = $t; # startTime ist nicht von "Automatic" abhängig -> nicht identisch mit planswitchon !!! $data{$name}{consumers}{$c}{startTime} = $t; # startTime ist nicht von "Automatic" abhängig -> nicht identisch mit planswitchon !!!
$data{$name}{consumers}{$c}{cycleStarttime} = $t; $data{$name}{consumers}{$c}{cycleStarttime} = $t;
$data{$name}{consumers}{$c}{cycleTime} = 0; $data{$name}{consumers}{$c}{cycleTime} = 0;
$data{$name}{consumers}{$c}{lastMinutesOn} = ConsumerVal ($hash, $c, 'minutesOn', 0); $data{$name}{consumers}{$c}{lastMinutesOn} = ConsumerVal ($hash, $c, 'minutesOn', 0);
$data{$name}{consumers}{$c}{cycleDayNum}++; # Anzahl der On-Schaltungen am Tag $data{$name}{consumers}{$c}{cycleDayNum}++; # Anzahl der On-Schaltungen am Tag
} }
else { else {
$data{$name}{consumers}{$c}{cycleTime} = (($t - ConsumerVal ($hash, $c, 'cycleStarttime', $t)) / 60); # Minuten $data{$name}{consumers}{$c}{cycleTime} = (($t - ConsumerVal ($hash, $c, 'cycleStarttime', $t)) / 60); # Minuten
} }
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', $t)); $starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', $t));
@ -11838,14 +11840,14 @@ sub __getCyclesAndRuntime {
my $runtime = (($t - ConsumerVal ($hash, $c, 'startTime', $t)) / 60); # in Minuten ! (gettimeofday sind ms !) my $runtime = (($t - ConsumerVal ($hash, $c, 'startTime', $t)) / 60); # in Minuten ! (gettimeofday sind ms !)
$data{$name}{consumers}{$c}{minutesOn} = ConsumerVal ($hash, $c, 'lastMinutesOn', 0) + $runtime; $data{$name}{consumers}{$c}{minutesOn} = ConsumerVal ($hash, $c, 'lastMinutesOn', 0) + $runtime;
} }
else { # Stundenwechsel else { # Stundenwechsel
if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'on') { # Status im letzen Zyklus war "on" if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'on') { # Status im letzen Zyklus war "on"
my $newst = timestringToTimestamp ($date.' '.sprintf("%02d", $chour).':00:00'); my $newst = timestringToTimestamp ($date.' '.sprintf("%02d", $chour).':00:00');
$data{$name}{consumers}{$c}{startTime} = $newst; $data{$name}{consumers}{$c}{startTime} = $newst;
$data{$name}{consumers}{$c}{minutesOn} = ($t - ConsumerVal ($hash, $c, 'startTime', $newst)) / 60; # in Minuten ! (gettimeofday sind ms !) $data{$name}{consumers}{$c}{minutesOn} = ($t - ConsumerVal ($hash, $c, 'startTime', $newst)) / 60; # in Minuten ! (gettimeofday sind ms !)
$data{$name}{consumers}{$c}{lastMinutesOn} = 0; $data{$name}{consumers}{$c}{lastMinutesOn} = 0;
if ($day ne $startday) { # Tageswechsel if ($day ne $startday) { # Tageswechsel
$data{$name}{consumers}{$c}{cycleDayNum} = 1; $data{$name}{consumers}{$c}{cycleDayNum} = 1;
} }
} }
@ -11853,13 +11855,13 @@ sub __getCyclesAndRuntime {
} }
else { # Verbraucher soll nicht aktiv sein else { # Verbraucher soll nicht aktiv sein
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', 1)); $starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', 1));
$startday = strftime "%d", localtime(ConsumerVal ($hash, $c, 'startTime', 1)); # aktueller Tag (range 01 to 31) $startday = strftime "%d", localtime(ConsumerVal ($hash, $c, 'startTime', 1)); # aktueller Tag (range 01 to 31)
if ($chour ne $starthour) { # Stundenwechsel if ($chour ne $starthour) { # Stundenwechsel
$data{$name}{consumers}{$c}{minutesOn} = 0; $data{$name}{consumers}{$c}{minutesOn} = 0;
} }
if ($day ne $startday) { # Tageswechsel if ($day ne $startday) { # Tageswechsel
$data{$name}{consumers}{$c}{cycleDayNum} = 0; $data{$name}{consumers}{$c}{cycleDayNum} = 0;
} }
@ -11998,13 +12000,13 @@ return ($simpCstat, $starttime, $stoptime, $supplmnt);
# Energieverbrauch Vorhersage kalkulieren (Median) # Energieverbrauch Vorhersage kalkulieren (Median)
################################################################ ################################################################
sub _calcConsForecast_circular { sub _calcConsForecast_circular {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $t = $paref->{t}; my $t = $paref->{t};
my $date = $paref->{date}; # aktuelles Datum my $date = $paref->{date}; # aktuelles Datum
my $day = $paref->{day}; # aktuelles Tagdatum (01...31) my $day = $paref->{day}; # aktuelles Tagdatum (01...31)
my $dayname = $paref->{dayname}; # aktueller Tagname my $todayname = $paref->{dayname}; # aktueller Tagname
my $hash = $defs{$name}; my $hash = $defs{$name};
my $acref = $data{$name}{consumers}; my $acref = $data{$name}{consumers};
@ -12018,14 +12020,19 @@ sub _calcConsForecast_circular {
my (@cona, $exconfc, $csme, %usage); my (@cona, $exconfc, $csme, %usage);
$usage{tom}{con} = 0; $usage{tom}{con} = 0;
debugLog ($paref, 'consumption|consumption_long', "################### Start Consumption forecast ###################");
debugLog ($paref, 'consumption_long', "Basics - installed locale: ".LOCALE_TIME.", used scheme: $lct");
## Verbrauch der hod-Stunden 01..24 u. gesamten Tag ermitteln ## Verbrauch der hod-Stunden 01..24 u. gesamten Tag ermitteln
############################################################### ###############################################################
for my $h (1..24) { # Median für jede Stunde / Tag berechnen for my $h (1..24) { # Median für jede Stunde / Tag berechnen
my $dt = timestringsFromOffset ($st, $h * 3559); # eine Sek. weniger als 1 Stunde $dt = timestringsFromOffset ($st, $h * 3559); # eine Sek. weniger als 1 Stunde
my $dayname = $dt->{dayname}; my $dayname = $dt->{dayname};
my $hh = sprintf "%02d", $h; my $hh = sprintf "%02d", $h;
debugLog ($paref, 'consumption_long', "process Today dayname: $dayname, Tomorrow dayname: $tomdayname") if($h == 1);
my (@conh, @conhtom); my (@conh, @conhtom);
my $mix = 0; my $mix = 0;
@ -12081,19 +12088,18 @@ sub _calcConsForecast_circular {
for my $n (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) { for my $n (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) {
next if ($n eq $day); # aktuellen (unvollständigen) Tag nicht berücksichtigen next if ($n eq $day); # aktuellen (unvollständigen) Tag nicht berücksichtigen
my $do = 1;
for my $c (sort{$a<=>$b} keys %{$acref}) { # historischer Verbrauch aller registrierten Verbraucher aufaddieren for my $c (sort{$a<=>$b} keys %{$acref}) { # historischer Verbrauch aller registrierten Verbraucher aufaddieren
$exconfc = ConsumerVal ($hash, $c, 'exconfc', 0); $exconfc = ConsumerVal ($hash, $c, 'exconfc', 0);
if ($exconfc) { if ($exconfc) {
## Tageswert Excludes finden und summieren ## Tageswert Excludes finden und summieren
############################################ ############################################
if ($exconfc == 1) { # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen if ($do && $exconfc == 1) { # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen
my $do = 1;
if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen
my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef); my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef);
$do = 0 if(!$hdn || $hdn ne $tomdayname); $do = 0 if(!$hdn || $hdn ne $tomdayname);
} }
if ($do) { if ($do) {
@ -12108,26 +12114,47 @@ sub _calcConsForecast_circular {
} }
} }
## hist. On-Stunden aller Tage aufnehmen ## Stundenweise exkludes und inkludes aufnehmen
########################################## #################################################
for my $h (1..24) { # excludieren ob exconfc 1 oder 2 $do = 1;
my $hh = sprintf "%02d", $h; if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen
$csme = HistoryVal ($hash, $n, $hh, "csme${c}", 0); my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef);
$do = 0 if(!$hdn || $hdn ne $todayname);
}
if ($csme) { if ($do) {
$usage{$hh}{histcon} += $csme; my $epiecelem = 1;
$usage{$hh}{histnum}++;
}
if ($exconfc == 2 && $lap == 1) { # Planungsdaten des Consumers inkludieren for my $h (1..24) { # excludieren ob exconfc 1 oder 2
my $ehp = $data{$name}{consumers}{$c}{ehodpieces}{$hh}; my $hh = sprintf "%02d", $h;
$csme = HistoryVal ($hash, $n, $hh, "csme${c}", 0);
if ($csme) {
$csme = sprintf "%.2f", $csme;
$usage{$hh}{histcon} += $csme;
$usage{$hh}{histnum}++;
debugLog ($paref, 'consumption_long', "consumer '$c' register for exclude day $n, hod: $hh - ".$csme." Wh");
}
if (defined $ehp) { if ($exconfc == 2 && $lap == 1) { # AVG-Daten des Consumers inkludieren
$usage{$hh}{plancon} += $ehp; my $rt = $st + (3600 * ($h - 1)); # Schleifenlaufzeit
$usage{$hh}{plannum}++; my $plson = ConsumerVal ($name, $c, 'planswitchon', $st + 86400); # geplante Switch-on Zeit des Consumers
} my $plsoff = ConsumerVal ($name, $c, 'planswitchoff', 0); # geplante Switch-off Zeit des Consumers
if ($rt >= $plson && $rt <= $plsoff) {
if (defined $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}) {
$usage{$hh}{plancon} += $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem};
$usage{$hh}{plannum}++;
debugLog ($paref, 'consumption_long', "consumer '$c' register epiecAVG: ".$data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}." Wh for include in Hour $hh");
$epiecelem++;
}
}
}
} }
} }
} }
} }
@ -12143,7 +12170,7 @@ sub _calcConsForecast_circular {
if (defined $usage{$hh}{histnum}) { # historische Stundenverbräuche exkludieren if (defined $usage{$hh}{histnum}) { # historische Stundenverbräuche exkludieren
my $exhcon = sprintf "%.0f", ($usage{$hh}{histcon} / $usage{$hh}{histnum}); # durchschnittlichen Verbrauchswert my $exhcon = sprintf "%.0f", ($usage{$hh}{histcon} / $usage{$hh}{histnum}); # durchschnittlichen Verbrauchswert
$usage{$hh}{con} -= $exhcon; $usage{$hh}{con} -= $exhcon if($usage{$hh}{con} > $exhcon);
debugLog ($paref, 'consumption_long', "excl. hist $exhcon Wh for Hour $hh, Considered value numbers: ".$usage{$hh}{histnum}); debugLog ($paref, 'consumption_long', "excl. hist $exhcon Wh for Hour $hh, Considered value numbers: ".$usage{$hh}{histnum});
} }
@ -17052,10 +17079,14 @@ sub aiAddInstancePV { ## no critic "not used"
my $wcc = AiRawdataVal ($hash, $idx, 'wcc', undef); my $wcc = AiRawdataVal ($hash, $idx, 'wcc', undef);
my $rr1c = AiRawdataVal ($hash, $idx, 'rr1c', undef); my $rr1c = AiRawdataVal ($hash, $idx, 'rr1c', undef);
my $sunalt = AiRawdataVal ($hash, $idx, 'sunalt', 0); my $sunalt = AiRawdataVal ($hash, $idx, 'sunalt', 0);
my $tbin = temp2bin ($temp) if(defined $temp);
my $cbin = cloud2bin ($wcc) if(defined $wcc);
my $sabin = sunalt2bin ($sunalt);
eval { $dtree->add_instance (attributes => { rad1h => $rad1h, eval { $dtree->add_instance (attributes => { rad1h => $rad1h,
temp => $temp, temp => $tbin,
wcc => $wcc, wcc => $cbin,
rr1c => $rr1c, rr1c => $rr1c,
sunalt => $sunalt, sunalt => $sunalt,
hod => $hod hod => $hod
@ -17400,21 +17431,17 @@ sub aiAddRawData {
my $con = HistoryVal ($hash, $pvd, $hod, 'con', undef); my $con = HistoryVal ($hash, $pvd, $hod, 'con', undef);
my $wcc = HistoryVal ($hash, $pvd, $hod, 'wcc', undef); my $wcc = HistoryVal ($hash, $pvd, $hod, 'wcc', undef);
my $rr1c = HistoryVal ($hash, $pvd, $hod, 'rr1c', undef); my $rr1c = HistoryVal ($hash, $pvd, $hod, 'rr1c', undef);
my $rad1h = HistoryVal ($hash, $pvd, $hod, 'rad1h', undef); my $rad1h = HistoryVal ($hash, $pvd, $hod, 'rad1h', undef);
my $tbin = temp2bin ($temp) if(defined $temp); $data{$name}{aidectree}{airaw}{$ridx}{sunalt} = $sunalt;
my $cbin = cloud2bin ($wcc) if(defined $wcc);
my $sabin = sunalt2bin ($sunalt);
$data{$name}{aidectree}{airaw}{$ridx}{sunalt} = $sabin;
$data{$name}{aidectree}{airaw}{$ridx}{sunaz} = $sunaz; $data{$name}{aidectree}{airaw}{$ridx}{sunaz} = $sunaz;
$data{$name}{aidectree}{airaw}{$ridx}{dayname} = $dayname; $data{$name}{aidectree}{airaw}{$ridx}{dayname} = $dayname;
$data{$name}{aidectree}{airaw}{$ridx}{hod} = $hod; $data{$name}{aidectree}{airaw}{$ridx}{hod} = $hod;
$data{$name}{aidectree}{airaw}{$ridx}{temp} = $tbin if(defined $tbin); $data{$name}{aidectree}{airaw}{$ridx}{temp} = sprintf "%.0f", $temp if(defined $temp);
$data{$name}{aidectree}{airaw}{$ridx}{con} = $con if(defined $con && $con >= 0); $data{$name}{aidectree}{airaw}{$ridx}{con} = $con if(defined $con && $con >= 0);
$data{$name}{aidectree}{airaw}{$ridx}{wcc} = $cbin if(defined $cbin); $data{$name}{aidectree}{airaw}{$ridx}{wcc} = $wcc if(defined $wcc);
$data{$name}{aidectree}{airaw}{$ridx}{rr1c} = $rr1c if(defined $rr1c); $data{$name}{aidectree}{airaw}{$ridx}{rr1c} = $rr1c if(defined $rr1c);
$data{$name}{aidectree}{airaw}{$ridx}{rad1h} = $rad1h if(defined $rad1h && $rad1h > 0); $data{$name}{aidectree}{airaw}{$ridx}{rad1h} = $rad1h if(defined $rad1h && $rad1h > 0);
$dosave++; $dosave++;
@ -17428,7 +17455,7 @@ sub aiAddRawData {
my $pvrl = HistoryVal ($hash, $pvd, $hod, 'pvrl', undef); my $pvrl = HistoryVal ($hash, $pvd, $hod, 'pvrl', undef);
$data{$name}{aidectree}{airaw}{$ridx}{pvrl} = $pvrl if(defined $pvrl && $pvrl > 0); $data{$name}{aidectree}{airaw}{$ridx}{pvrl} = $pvrl if(defined $pvrl && $pvrl > 0);
debugLog ($paref, 'aiProcess', "AI raw add - idx: $ridx, day: $pvd, hod: $hod, sunalt: $sabin, sunaz: $sunaz, rad1h: ".(defined $rad1h ? $rad1h : '-').", pvrl: ".(defined $pvrl ? $pvrl : '-').", con: ".(defined $con ? $con : '-').", wcc: ".(defined $cbin ? $cbin : '-').", rr1c: ".(defined $rr1c ? $rr1c : '-').", temp: ".(defined $tbin ? $tbin : '-'), 4); debugLog ($paref, 'aiProcess', "AI raw add - idx: $ridx, day: $pvd, hod: $hod, sunalt: $sunalt, sunaz: $sunaz, rad1h: ".(defined $rad1h ? $rad1h : '-').", pvrl: ".(defined $pvrl ? $pvrl : '-').", con: ".(defined $con ? $con : '-').", wcc: ".(defined $wcc ? $wcc : '-').", rr1c: ".(defined $rr1c ? $rr1c : '-').", temp: ".(defined $temp ? $temp : '-'), 4);
} }
} }
@ -19803,10 +19830,10 @@ sub createAssociatedWith {
push @cd, $medev; push @cd, $medev;
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices
my $consumer = AttrVal ($name, "consumer${c}", ""); my $consumer = AttrVal ($name, "consumer${c}", "");
my ($ac,$hc) = parseParams ($consumer); my ($ac,$hc) = parseParams ($consumer);
my $codev = $ac->[0] // ''; my ($codev) = split ":", ($ac->[0] // '');
my $dswitch = $hc->{switchdev} // ''; # alternatives Schaltdevice my ($dswitch) = split ":", ($hc->{switchdev} // ''); # alternatives Schaltdevice
push @cd, $codev if($codev); push @cd, $codev if($codev);
push @cd, $dswitch if($dswitch); push @cd, $dswitch if($dswitch);
} }
@ -21777,7 +21804,7 @@ return $def;
################################################################################################################### ###################################################################################################################
# Wert des consumer-Hash zurückliefern # Wert des consumer-Hash zurückliefern
# Usage: # Usage:
# ConsumerVal ($hash or $name, $co, $key, $def) # ConsumerVal ($hash or $name, $co, $key, $def)
# #
# $co: Consumer Nummer (01,02,03,...) # $co: Consumer Nummer (01,02,03,...)
# $key: name - Name des Verbrauchers (Device) # $key: name - Name des Verbrauchers (Device)
@ -21809,6 +21836,8 @@ return $def;
# ehodpieces - geplante Energiescheiben nach Tagesstunde (hour of day) (Hash) # ehodpieces - geplante Energiescheiben nach Tagesstunde (hour of day) (Hash)
# dswoncond - Device zur Lieferung einer zusätzliche Einschaltbedingung # dswoncond - Device zur Lieferung einer zusätzliche Einschaltbedingung
# planstate - Planungsstatus # planstate - Planungsstatus
# planswitchon - geplante Switch-On Zeit
# planswitchoff - geplante Switch-Off Zeit
# planSupplement - Ergänzung zum Planungsstatus # planSupplement - Ergänzung zum Planungsstatus
# rswoncond - Reading zur Lieferung einer zusätzliche Einschaltbedingung # rswoncond - Reading zur Lieferung einer zusätzliche Einschaltbedingung
# swoncondregex - Regex einer zusätzliche Einschaltbedingung # swoncondregex - Regex einer zusätzliche Einschaltbedingung

View File

@ -159,7 +159,8 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.46.2" => "19.02.2025 aiAddRawData: save original data and sort to bin in sub aiAddInstancePV instead, _calcConsForecast_circular: include epiecAVG ", "1.46.2" => "19.02.2025 aiAddRawData: save original data and sort to bin in sub aiAddInstancePV instead, _calcConsForecast_circular: include epiecAVG ".
"fix NOTIFYDEV for consumers, change MAXINVERTER to 4 ",
"1.46.1" => "18.02.2025 improve temp2bin, correct Log output to consumptionHistory, set setupStringDeclination can be free integer between 0..90 ", "1.46.1" => "18.02.2025 improve temp2bin, correct Log output to consumptionHistory, set setupStringDeclination can be free integer between 0..90 ",
"1.46.0" => "17.02.2025 Notification System: print out last/next file pull if no messages are present, improvements and activation of ". "1.46.0" => "17.02.2025 Notification System: print out last/next file pull if no messages are present, improvements and activation of ".
"_calcConsForecast_circular, checkPlantConfig: add Data Memory check pvHistory 'con' ". "_calcConsForecast_circular, checkPlantConfig: add Data Memory check pvHistory 'con' ".
@ -386,7 +387,7 @@ use constant {
MAXBATTERIES => 3, # maximale Anzahl der möglichen Batterien MAXBATTERIES => 3, # maximale Anzahl der möglichen Batterien
MAXCONSUMER => 16, # maximale Anzahl der möglichen Consumer (Attribut) MAXCONSUMER => 16, # maximale Anzahl der möglichen Consumer (Attribut)
MAXPRODUCER => 3, # maximale Anzahl der möglichen anderen Produzenten (Attribut) MAXPRODUCER => 3, # maximale Anzahl der möglichen anderen Produzenten (Attribut)
MAXINVERTER => 3, # maximale Anzahl der möglichen Inverter MAXINVERTER => 4, # maximale Anzahl der möglichen Inverter
MAXSOCDEF => 95, # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt MAXSOCDEF => 95, # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt
CARECYCLEDEF => 20, # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen CARECYCLEDEF => 20, # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen
@ -1766,8 +1767,8 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
return; return;
} }
my $startts = time; my $startts = time;
my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME); my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME);
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
@ -11999,13 +12000,13 @@ return ($simpCstat, $starttime, $stoptime, $supplmnt);
# Energieverbrauch Vorhersage kalkulieren (Median) # Energieverbrauch Vorhersage kalkulieren (Median)
################################################################ ################################################################
sub _calcConsForecast_circular { sub _calcConsForecast_circular {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $t = $paref->{t}; my $t = $paref->{t};
my $date = $paref->{date}; # aktuelles Datum my $date = $paref->{date}; # aktuelles Datum
my $day = $paref->{day}; # aktuelles Tagdatum (01...31) my $day = $paref->{day}; # aktuelles Tagdatum (01...31)
my $dayname = $paref->{dayname}; # aktueller Tagname my $todayname = $paref->{dayname}; # aktueller Tagname
my $hash = $defs{$name}; my $hash = $defs{$name};
my $acref = $data{$name}{consumers}; my $acref = $data{$name}{consumers};
@ -12087,19 +12088,18 @@ sub _calcConsForecast_circular {
for my $n (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) { for my $n (sort{$a<=>$b} keys %{$data{$name}{pvhist}}) {
next if ($n eq $day); # aktuellen (unvollständigen) Tag nicht berücksichtigen next if ($n eq $day); # aktuellen (unvollständigen) Tag nicht berücksichtigen
my $do = 1;
for my $c (sort{$a<=>$b} keys %{$acref}) { # historischer Verbrauch aller registrierten Verbraucher aufaddieren for my $c (sort{$a<=>$b} keys %{$acref}) { # historischer Verbrauch aller registrierten Verbraucher aufaddieren
$exconfc = ConsumerVal ($hash, $c, 'exconfc', 0); $exconfc = ConsumerVal ($hash, $c, 'exconfc', 0);
if ($exconfc) { if ($exconfc) {
## Tageswert Excludes finden und summieren ## Tageswert Excludes finden und summieren
############################################ ############################################
if ($exconfc == 1) { # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen if ($do && $exconfc == 1) { # 1 -> Consumer Verbrauch von Erstelleung der Verbrauchsprognose ausschließen
my $do = 1;
if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen
my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef); my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef);
$do = 0 if(!$hdn || $hdn ne $tomdayname); $do = 0 if(!$hdn || $hdn ne $tomdayname);
} }
if ($do) { if ($do) {
@ -12114,36 +12114,47 @@ sub _calcConsForecast_circular {
} }
} }
## hist. On-Stunden aller Tage aufnehmen ## Stundenweise exkludes und inkludes aufnehmen
########################################## #################################################
my $epiecelem = 1; $do = 1;
if ($swdfcfc) { # nur gleiche Tage (Mo...So) einbeziehen
my $hdn = HistoryVal ($hash, $n, 99, 'dayname', undef);
$do = 0 if(!$hdn || $hdn ne $todayname);
}
for my $h (1..24) { # excludieren ob exconfc 1 oder 2 if ($do) {
my $hh = sprintf "%02d", $h; my $epiecelem = 1;
$csme = HistoryVal ($hash, $n, $hh, "csme${c}", 0);
if ($csme) {
$usage{$hh}{histcon} += $csme;
$usage{$hh}{histnum}++;
}
if ($exconfc == 2 && $lap == 1) { # AVG-Daten des Consumers inkludieren for my $h (1..24) { # excludieren ob exconfc 1 oder 2
my $rt = $st + (3600 * ($h - 1)); # Schleifenlaufzeit my $hh = sprintf "%02d", $h;
my $plson = ConsumerVal ($name, $c, 'planswitchon', $st + 86400); # geplante Switch-on Zeit des Consumers $csme = HistoryVal ($hash, $n, $hh, "csme${c}", 0);
my $plsoff = ConsumerVal ($name, $c, 'planswitchoff', 0); # geplante Switch-off Zeit des Consumers
if ($csme) {
if ($rt >= $plson && $rt <= $plsoff) { $csme = sprintf "%.2f", $csme;
if (defined $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}) { $usage{$hh}{histcon} += $csme;
$usage{$hh}{plancon} += $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}; $usage{$hh}{histnum}++;
$usage{$hh}{plannum}++;
debugLog ($paref, 'consumption_long', "consumer '$c' register for exclude day $n, hod: $hh - ".$csme." Wh");
debugLog ($paref, 'consumption_long', "consumer '$c' register epiecAVG: ".$data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}." Wh for include in Hour $hh"); }
$epiecelem++; if ($exconfc == 2 && $lap == 1) { # AVG-Daten des Consumers inkludieren
} my $rt = $st + (3600 * ($h - 1)); # Schleifenlaufzeit
} my $plson = ConsumerVal ($name, $c, 'planswitchon', $st + 86400); # geplante Switch-on Zeit des Consumers
my $plsoff = ConsumerVal ($name, $c, 'planswitchoff', 0); # geplante Switch-off Zeit des Consumers
if ($rt >= $plson && $rt <= $plsoff) {
if (defined $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}) {
$usage{$hh}{plancon} += $data{$name}{consumers}{$c}{epiecAVG}{$epiecelem};
$usage{$hh}{plannum}++;
debugLog ($paref, 'consumption_long', "consumer '$c' register epiecAVG: ".$data{$name}{consumers}{$c}{epiecAVG}{$epiecelem}." Wh for include in Hour $hh");
$epiecelem++;
}
}
}
} }
} }
} }
} }
@ -19819,10 +19830,10 @@ sub createAssociatedWith {
push @cd, $medev; push @cd, $medev;
for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices for my $c (sort{$a<=>$b} keys %{$data{$name}{consumers}}) { # Consumer Devices
my $consumer = AttrVal ($name, "consumer${c}", ""); my $consumer = AttrVal ($name, "consumer${c}", "");
my ($ac,$hc) = parseParams ($consumer); my ($ac,$hc) = parseParams ($consumer);
my $codev = $ac->[0] // ''; my ($codev) = split ":", ($ac->[0] // '');
my $dswitch = $hc->{switchdev} // ''; # alternatives Schaltdevice my ($dswitch) = split ":", ($hc->{switchdev} // ''); # alternatives Schaltdevice
push @cd, $codev if($codev); push @cd, $codev if($codev);
push @cd, $dswitch if($dswitch); push @cd, $dswitch if($dswitch);
} }