From 55ad97e71f7e7e6fc7dc32297862c2fe097c22d6 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sun, 26 Jan 2025 10:54:17 +0000 Subject: [PATCH] 76_SolarForecast: contrib Test git-svn-id: https://svn.fhem.de/fhem/trunk@29578 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/76_SolarForecast.pm | 606 ++++++++++---------- 1 file changed, 302 insertions(+), 304 deletions(-) diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 2a06418c8..990bbd23c 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -34,6 +34,7 @@ package FHEM::SolarForecast; use strict; use warnings; +#use lib qw(/opt/fhem/FHEM /opt/fhem/lib); # für Syntaxcheck mit: perl -c /opt/fhem/FHEM/76_SolarForecast.pm use POSIX; use GPUtils qw(GP_Import GP_Export); # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt use Time::HiRes qw(gettimeofday tv_interval); @@ -159,6 +160,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.44.4" => "26.01.2025 _getlistPVCircular: change width of output, new sub _listDataPoolPvHist ", "1.44.3" => "25.01.2025 Notification System: minor changes, special Readings todayBatInSum todayBatOutSum ", "1.44.2" => "23.01.2025 _batChargeRecmd: user storeffdef, show historical battery SoC when displaying the battery in the bar graph ", "1.44.1" => "20.01.2025 Notification system: minor fixes, integration of controls_solarforecast_messages_test/prod ". @@ -174,7 +176,7 @@ my %vNotesIntern = ( "trackFlex now default in DWD Model, replace title Charging recommendation by Charging release ". "_saveEnergyConsumption: add dowrite flag, edit comref ", "1.43.1" => "11.01.2025 _batChargeRecmd: bugfix PV daily surplus update, _collectAllRegConsumers: fix interruptable hysteresis ". - "__batRcmdOnBeam: show soc forecast for hour 00 and fix english translation ". + "__batteryOnBeam: show soc forecast for hour 00 and fix english translation ". "_batChargeRecmd: consider battery capacity as part of total capacity ", "1.43.0" => "10.01.2025 graphicShowNight: add possible Time Sync of chart bar level 1 and the other ". "_addDynAttr: minor fix for graphicBeamXContent, new attr ctrlNextHoursSoCForecastReadings ", @@ -4743,7 +4745,7 @@ sub _getlistPVCircular { my $hash = $defs{$name}; my $ret = listDataPool ($hash, 'circular', $arg); - $ret .= lineFromSpaces ($ret, 20); + $ret .= lineFromSpaces ($ret, -20); return $ret; } @@ -14848,7 +14850,7 @@ sub _beamGraphic { my $ret = q{}; $ret .= __weatherOnBeam ($paref) if($weather); - $ret .= __batRcmdOnBeam ($paref); + $ret .= __batteryOnBeam ($paref); my $m = $paref->{modulo} % 2; if ($show_diff eq 'top') { # Zusätzliche Zeile Ertrag - Verbrauch @@ -15252,7 +15254,7 @@ return $ret; ################################################################ # Batterieladeempfehlung in Balkengrafik ################################################################ -sub __batRcmdOnBeam { +sub __batteryOnBeam { my $paref = shift; my $name = $paref->{name}; my $maxhours = $paref->{maxhours}; @@ -15327,6 +15329,7 @@ sub __batRcmdOnBeam { $ret .= ""; # freier Platz am Anfang my $ii = 0; + my $m =0; for my $i (0..($maxhours * 2) - 1) { my $skip = __dontNightshowSkipSync ($name, $paref, $i); @@ -15369,17 +15372,27 @@ sub __batRcmdOnBeam { } ); - $title .= defined $currsoc ? "\n".$htitles{socbacur}{$lang}.": ".$currsoc." %" : ''; - - debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef'). - " W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef'). - ", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %"); + Log3 ($name, 4, "$name - Test title nach Subst $i: $title") if($m==0 || $m==1 || $m==2); + + my $titleadd = defined $currsoc ? "\n".$htitles{socbacur}{$lang}.": ".$currsoc." %" : ''; + + Log3 ($name, 4, "$name - Test title Addon $i: $titleadd") if($m==0 || $m==1 || $m==2); + + $title .= $titleadd; + + Log3 ($name, 4, "$name - Test title Zusammengesetzt $i: $title") if($m==0 || $m==1 || $m==2); my $image = defined $hfcg->{$i}{'rcdchargebat'.$bn} ? FW_makeImage ($bicon) : ''; - Log3 ($name, 1, "$name - Test orig title: $title"); + $ret .= "$image"; + + Log3 ($name, 4, "$name - Test Return komplett $i: $ret\n") if($m==0 || $m==1 || $m==2); - $ret .= "$image"; + debugLog ($paref, 'graphic', "Battery $bn pos >$i< day: $day_str, time: $time_str, Power ('-' = out): ".(defined $bpower ? $bpower : 'undef'). + " W, Rcmd: ".(defined $hfcg->{$i}{'rcdchargebat'.$bn} ? $hfcg->{$i}{'rcdchargebat'.$bn} : 'undef'). + ", SoC: ".(defined $hfcg->{$i}{'soc'.$bn} ? $hfcg->{$i}{'soc'.$bn} : 'undef')." %"); + + $m++; } $ret .= "" if($ret); # freier Platz am Ende der Icon Zeile @@ -17633,272 +17646,10 @@ sub listDataPool { my $par = shift // q{}; my $name = $hash->{NAME}; - my $type = $hash->{TYPE}; - - my ($sq, $h, $hexp); - my $export = q{}; - - if ($par eq 'exportToCsv') { - $export = 'csv'; - $par = q{}; - } - - my $sub = sub { - my $day = shift; - my $ret; - - for my $key (sort {$a<=>$b} keys %{$h->{$day}}) { - my $pvrl = HistoryVal ($name, $day, $key, 'pvrl', '-'); - my $pvrlvd = HistoryVal ($name, $day, $key, 'pvrlvd', '-'); - my $pvfc = HistoryVal ($name, $day, $key, 'pvfc', '-'); - my $gcons = HistoryVal ($name, $day, $key, 'gcons', '-'); - my $con = HistoryVal ($name, $day, $key, 'con', '-'); - my $confc = HistoryVal ($name, $day, $key, 'confc', '-'); - my $gfeedin = HistoryVal ($name, $day, $key, 'gfeedin', '-'); - my $wid = HistoryVal ($name, $day, $key, 'weatherid', '-'); - my $wcc = HistoryVal ($name, $day, $key, 'wcc', '-'); - my $rr1c = HistoryVal ($name, $day, $key, 'rr1c', '-'); - my $temp = HistoryVal ($name, $day, $key, 'temp', undef); - my $pvcorrf = HistoryVal ($name, $day, $key, 'pvcorrf', '-'); - my $dayname = HistoryVal ($name, $day, $key, 'dayname', undef); - my $rad1h = HistoryVal ($name, $day, $key, 'rad1h', '-'); - my $sunaz = HistoryVal ($name, $day, $key, 'sunaz', '-'); - my $sunalt = HistoryVal ($name, $day, $key, 'sunalt', '-'); - my $don = HistoryVal ($name, $day, $key, 'DoN', '-'); - my $conprc = HistoryVal ($name, $day, $key, 'conprice', '-'); - my $feedprc = HistoryVal ($name, $day, $key, 'feedprice', '-'); - - if ($export eq 'csv') { - $hexp->{$day}{$key}{PVreal} = $pvrl; - $hexp->{$day}{$key}{PVrealValid} = $pvrlvd; - $hexp->{$day}{$key}{PVforecast} = $pvfc; - $hexp->{$day}{$key}{GridConsumption} = $gcons; - $hexp->{$day}{$key}{Consumption} = $con; - $hexp->{$day}{$key}{confc} = $confc; - $hexp->{$day}{$key}{GridFeedIn} = $gfeedin; - $hexp->{$day}{$key}{WeatherId} = $wid; - $hexp->{$day}{$key}{CloudCover} = $wcc; - $hexp->{$day}{$key}{TotalPrecipitation} = $rr1c; - $hexp->{$day}{$key}{Temperature} = $temp // ''; - $hexp->{$day}{$key}{PVCorrectionFactor} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[0]; - $hexp->{$day}{$key}{Quality} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[1]; - $hexp->{$day}{$key}{DayName} = $dayname // ''; - $hexp->{$day}{$key}{GlobalRadiation } = $rad1h; - $hexp->{$day}{$key}{SunAzimuth} = $sunaz; - $hexp->{$day}{$key}{SunAltitude} = $sunalt; - $hexp->{$day}{$key}{DayOrNight} = $don; - $hexp->{$day}{$key}{PurchasePrice} = $conprc; - $hexp->{$day}{$key}{FeedInPrice} = $feedprc; - } - - my ($inve, $invl); - for my $in (1..$maxinverter) { # + alle Inverter - $in = sprintf "%02d", $in; - my $etoti = HistoryVal ($name, $day, $key, 'etotali'.$in, '-'); - my $pvrli = HistoryVal ($name, $day, $key, 'pvrl'.$in, '-'); - - if ($export eq 'csv') { - $hexp->{$day}{$key}{"Etotal${in}"} = $etoti; - $hexp->{$day}{$key}{"PVreal${in}"} = $pvrli; - } - - $inve .= ', ' if($inve); - $inve .= "etotali${in}: $etoti"; - $invl .= ', ' if($invl); - $invl .= "pvrl${in}: $pvrli"; - } - - my ($prde, $prdl); - for my $pn (1..$maxproducer) { # + alle Producer - $pn = sprintf "%02d", $pn; - my $etotp = HistoryVal ($name, $day, $key, 'etotalp'.$pn, '-'); - my $pprl = HistoryVal ($name, $day, $key, 'pprl'.$pn, '-'); - - if ($export eq 'csv') { - $hexp->{$day}{$key}{"Etotal${pn}"} = $etotp; - $hexp->{$day}{$key}{"PPreal${pn}"} = $pprl; - } - - $prde .= ', ' if($prde); - $prde .= "etotalp${pn}: $etotp"; - $prdl .= ', ' if($prdl); - $prdl .= "pprl${pn}: $pprl"; - } - - my ($btotin, $batin, $btotout, $batout, $batmsoc, $batssoc, $batsoc); - for my $bn (1..$maxbatteries) { # + alle Batterien - $bn = sprintf "%02d", $bn; - my $hbtotin = HistoryVal ($name, $day, $key, 'batintotal'.$bn, '-'); - my $hbtotout = HistoryVal ($name, $day, $key, 'batouttotal'.$bn, '-'); - my $hbatin = HistoryVal ($name, $day, $key, 'batin'.$bn, '-'); - my $hbatout = HistoryVal ($name, $day, $key, 'batout'.$bn, '-'); - my $hbatmsoc = HistoryVal ($name, $day, $key, 'batmaxsoc'.$bn, '-'); - my $hbatssoc = HistoryVal ($name, $day, $key, 'batsetsoc'.$bn, '-'); - my $hbatsoc = HistoryVal ($name, $day, $key, 'batsoc'.$bn, '-'); - - if ($export eq 'csv') { - $hexp->{$day}{$key}{"BatteryInTotal${bn}"} = $hbtotin; - $hexp->{$day}{$key}{"BatteryOutTotal${bn}"} = $hbtotout; - $hexp->{$day}{$key}{"BatteryIn${bn}"} = $hbatin; - $hexp->{$day}{$key}{"BatteryOut${bn}"} = $hbatout; - $hexp->{$day}{$key}{"BatteryMaxSoc${bn}"} = $hbatmsoc; - $hexp->{$day}{$key}{"BatterySetSoc${bn}"} = $hbatssoc; - $hexp->{$day}{$key}{"BatterySoc${bn}"} = $hbatsoc; - } - - $btotin .= ', ' if($btotin); - $btotin .= "batintotal${bn}: $hbtotin"; - $btotout .= ', ' if($btotout); - $btotout .= "batouttotal${bn}: $hbtotout"; - $batin .= ', ' if($batin); - $batin .= "batin${bn}: $hbatin"; - $batout .= ', ' if($batout); - $batout .= "batout${bn}: $hbatout"; - $batmsoc .= ', ' if($batmsoc); - $batmsoc .= "batmaxsoc${bn}: $hbatmsoc"; - $batssoc .= ', ' if($batssoc); - $batssoc .= "batsetsoc${bn}: $hbatssoc"; - $batsoc .= ', ' if($batsoc); - $batsoc .= "batsoc${bn}: $hbatsoc"; - } - - $ret .= "\n " if($ret); - $ret .= $key." => "; - $ret .= "pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h"; - $ret .= "\n "; - $ret .= $inve if($inve && $key ne '99'); - $ret .= "\n " if($inve && $key ne '99'); - $ret .= $invl if($invl); - $ret .= "\n " if($invl); - $ret .= $prde if($prde && $key ne '99'); - $ret .= "\n " if($prde && $key ne '99'); - $ret .= $prdl if($prdl); - $ret .= "\n " if($prdl); - $ret .= "confc: $confc, con: $con, gcons: $gcons, conprice: $conprc"; - $ret .= "\n "; - $ret .= "gfeedin: $gfeedin, feedprice: $feedprc"; - $ret .= "\n "; - $ret .= "DoN: $don, sunaz: $sunaz, sunalt: $sunalt"; - $ret .= "\n "; - - $ret .= $btotin if($key ne '99'); - $ret .= "\n " if($key ne '99'); - $ret .= $btotout if($key ne '99'); - $ret .= "\n " if($key ne '99'); - $ret .= $batsoc if($key ne '99'); - $ret .= "\n " if($key ne '99'); - - $ret .= $batin; - $ret .= "\n "; - $ret .= $batout; - $ret .= "\n "; - - $ret .= $batmsoc if($key eq '99'); - $ret .= "\n " if($key eq '99'); - $ret .= $batssoc if($key eq '99'); - $ret .= "\n " if($key eq '99'); - - if ($key ne '99') { - $ret .= "wid: $wid, "; - $ret .= "wcc: $wcc, "; - $ret .= "rr1c: $rr1c, "; - $ret .= "pvcorrf: $pvcorrf "; - } - - $ret .= "temp: $temp, " if($temp); - $ret .= "dayname: $dayname, " if($dayname); - - my $csm; - for my $c (1..$maxconsumer) { # + alle Consumer - $c = sprintf "%02d", $c; - my $nl = 0; - my $csmc = HistoryVal ($name, $day, $key, "cyclescsm${c}", undef); - my $csmt = HistoryVal ($name, $day, $key, "csmt${c}", undef); - my $csme = HistoryVal ($name, $day, $key, "csme${c}", undef); - my $csmm = HistoryVal ($name, $day, $key, "minutescsm${c}", undef); - my $csmh = HistoryVal ($name, $day, $key, "hourscsme${c}", undef); - my $csma = HistoryVal ($name, $day, $key, "avgcycmntscsm${c}", undef); - - if ($export eq 'csv') { - $hexp->{$day}{$key}{"CyclesCsm${c}"} = $csmc if(defined $csmc); - $hexp->{$day}{$key}{"Csmt${c}"} = $csmt if(defined $csmt); - $hexp->{$day}{$key}{"Csme${c}"} = $csme if(defined $csme); - $hexp->{$day}{$key}{"MinutesCsm${c}"} = $csmm if(defined $csmm); - $hexp->{$day}{$key}{"HoursCsme${c}"} = $csmh if(defined $csmh); - $hexp->{$day}{$key}{"AvgCycleMinutesCsm${c}"} = $csma if(defined $csma); - } - - if (defined $csmc) { - $csm .= "cyclescsm${c}: $csmc"; - $nl = 1; - } - - if (defined $csmt) { - $csm .= ", " if($nl); - $csm .= "csmt${c}: $csmt"; - $nl = 1; - } - - if (defined $csme) { - $csm .= ", " if($nl); - $csm .= "csme${c}: $csme"; - $nl = 1; - } - - if (defined $csmm) { - $csm .= ", " if($nl); - $csm .= "minutescsm${c}: $csmm"; - $nl = 1; - } - - if (defined $csmh) { - $csm .= ", " if($nl); - $csm .= "hourscsme${c}: $csmh"; - $nl = 1; - } - - if (defined $csma) { - $csm .= ", " if($nl); - $csm .= "avgcycmntscsm${c}: $csma"; - $nl = 1; - } - - $csm .= "\n " if($nl); - } - - if ($csm) { - $ret .= "\n "; - $ret .= $csm; - } - else { - $ret .= "\n "; - } - } - return $ret; - }; + my ($sq, $h); if ($htol eq "pvhist") { - $h = $data{$name}{pvhist}; - - if (!keys %{$h}) { - return qq{PV cache is empty.}; - } - - for my $i (keys %{$h}) { - if (!isNumeric ($i)) { - delete $data{$name}{pvhist}{$i}; - Log3 ($name, 2, qq{$name - INFO - invalid key "$i" was deleted from pvHistory storage}); - } - } - - for my $idx (sort keys %{$h}) { - next if($par && $idx ne $par); - $sq .= $idx." => ".$sub->($idx)."\n"; - } - - if ($export eq 'csv') { - return _writeAsCsv ($hash, $hexp, $pvhexprtcsv.$name.'.csv'); - } + $sq = _listDataPoolPvHist ($hash, $par); } if ($htol =~ /consumers|inverters|producers|strings|batteries/xs) { @@ -18164,6 +17915,282 @@ sub listDataPool { return $sq; } +################################################################ +# Listing des pvHistory Speichers +################################################################ +sub _listDataPoolPvHist { + my $hash = shift; + my $par = shift // q{}; + + my $name = $hash->{NAME}; + + my ($sq, $h, $hexp); + my $export = q{}; + + if ($par eq 'exportToCsv') { + $export = 'csv'; + $par = q{}; + } + + my $sub = sub { + my $day = shift; + my $ret; + + for my $key (sort {$a<=>$b} keys %{$h->{$day}}) { + my $pvrl = HistoryVal ($name, $day, $key, 'pvrl', '-'); + my $pvrlvd = HistoryVal ($name, $day, $key, 'pvrlvd', '-'); + my $pvfc = HistoryVal ($name, $day, $key, 'pvfc', '-'); + my $gcons = HistoryVal ($name, $day, $key, 'gcons', '-'); + my $con = HistoryVal ($name, $day, $key, 'con', '-'); + my $confc = HistoryVal ($name, $day, $key, 'confc', '-'); + my $gfeedin = HistoryVal ($name, $day, $key, 'gfeedin', '-'); + my $wid = HistoryVal ($name, $day, $key, 'weatherid', '-'); + my $wcc = HistoryVal ($name, $day, $key, 'wcc', '-'); + my $rr1c = HistoryVal ($name, $day, $key, 'rr1c', '-'); + my $temp = HistoryVal ($name, $day, $key, 'temp', undef); + my $pvcorrf = HistoryVal ($name, $day, $key, 'pvcorrf', '-'); + my $dayname = HistoryVal ($name, $day, $key, 'dayname', undef); + my $rad1h = HistoryVal ($name, $day, $key, 'rad1h', '-'); + my $sunaz = HistoryVal ($name, $day, $key, 'sunaz', '-'); + my $sunalt = HistoryVal ($name, $day, $key, 'sunalt', '-'); + my $don = HistoryVal ($name, $day, $key, 'DoN', '-'); + my $conprc = HistoryVal ($name, $day, $key, 'conprice', '-'); + my $feedprc = HistoryVal ($name, $day, $key, 'feedprice', '-'); + + if ($export eq 'csv') { + $hexp->{$day}{$key}{PVreal} = $pvrl; + $hexp->{$day}{$key}{PVrealValid} = $pvrlvd; + $hexp->{$day}{$key}{PVforecast} = $pvfc; + $hexp->{$day}{$key}{GridConsumption} = $gcons; + $hexp->{$day}{$key}{Consumption} = $con; + $hexp->{$day}{$key}{confc} = $confc; + $hexp->{$day}{$key}{GridFeedIn} = $gfeedin; + $hexp->{$day}{$key}{WeatherId} = $wid; + $hexp->{$day}{$key}{CloudCover} = $wcc; + $hexp->{$day}{$key}{TotalPrecipitation} = $rr1c; + $hexp->{$day}{$key}{Temperature} = $temp // ''; + $hexp->{$day}{$key}{PVCorrectionFactor} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[0]; + $hexp->{$day}{$key}{Quality} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[1]; + $hexp->{$day}{$key}{DayName} = $dayname // ''; + $hexp->{$day}{$key}{GlobalRadiation } = $rad1h; + $hexp->{$day}{$key}{SunAzimuth} = $sunaz; + $hexp->{$day}{$key}{SunAltitude} = $sunalt; + $hexp->{$day}{$key}{DayOrNight} = $don; + $hexp->{$day}{$key}{PurchasePrice} = $conprc; + $hexp->{$day}{$key}{FeedInPrice} = $feedprc; + } + + my ($inve, $invl); + for my $in (1..$maxinverter) { # + alle Inverter + $in = sprintf "%02d", $in; + my $etoti = HistoryVal ($name, $day, $key, 'etotali'.$in, '-'); + my $pvrli = HistoryVal ($name, $day, $key, 'pvrl'.$in, '-'); + + if ($export eq 'csv') { + $hexp->{$day}{$key}{"Etotal${in}"} = $etoti; + $hexp->{$day}{$key}{"PVreal${in}"} = $pvrli; + } + + $inve .= ', ' if($inve); + $inve .= "etotali${in}: $etoti"; + $invl .= ', ' if($invl); + $invl .= "pvrl${in}: $pvrli"; + } + + my ($prde, $prdl); + for my $pn (1..$maxproducer) { # + alle Producer + $pn = sprintf "%02d", $pn; + my $etotp = HistoryVal ($name, $day, $key, 'etotalp'.$pn, '-'); + my $pprl = HistoryVal ($name, $day, $key, 'pprl'.$pn, '-'); + + if ($export eq 'csv') { + $hexp->{$day}{$key}{"Etotal${pn}"} = $etotp; + $hexp->{$day}{$key}{"PPreal${pn}"} = $pprl; + } + + $prde .= ', ' if($prde); + $prde .= "etotalp${pn}: $etotp"; + $prdl .= ', ' if($prdl); + $prdl .= "pprl${pn}: $pprl"; + } + + my ($btotin, $batin, $btotout, $batout, $batmsoc, $batssoc, $batsoc); + for my $bn (1..$maxbatteries) { # + alle Batterien + $bn = sprintf "%02d", $bn; + my $hbtotin = HistoryVal ($name, $day, $key, 'batintotal'.$bn, '-'); + my $hbtotout = HistoryVal ($name, $day, $key, 'batouttotal'.$bn, '-'); + my $hbatin = HistoryVal ($name, $day, $key, 'batin'.$bn, '-'); + my $hbatout = HistoryVal ($name, $day, $key, 'batout'.$bn, '-'); + my $hbatmsoc = HistoryVal ($name, $day, $key, 'batmaxsoc'.$bn, '-'); + my $hbatssoc = HistoryVal ($name, $day, $key, 'batsetsoc'.$bn, '-'); + my $hbatsoc = HistoryVal ($name, $day, $key, 'batsoc'.$bn, '-'); + + if ($export eq 'csv') { + $hexp->{$day}{$key}{"BatteryInTotal${bn}"} = $hbtotin; + $hexp->{$day}{$key}{"BatteryOutTotal${bn}"} = $hbtotout; + $hexp->{$day}{$key}{"BatteryIn${bn}"} = $hbatin; + $hexp->{$day}{$key}{"BatteryOut${bn}"} = $hbatout; + $hexp->{$day}{$key}{"BatteryMaxSoc${bn}"} = $hbatmsoc; + $hexp->{$day}{$key}{"BatterySetSoc${bn}"} = $hbatssoc; + $hexp->{$day}{$key}{"BatterySoc${bn}"} = $hbatsoc; + } + + $btotin .= ', ' if($btotin); + $btotin .= "batintotal${bn}: $hbtotin"; + $btotout .= ', ' if($btotout); + $btotout .= "batouttotal${bn}: $hbtotout"; + $batin .= ', ' if($batin); + $batin .= "batin${bn}: $hbatin"; + $batout .= ', ' if($batout); + $batout .= "batout${bn}: $hbatout"; + $batmsoc .= ', ' if($batmsoc); + $batmsoc .= "batmaxsoc${bn}: $hbatmsoc"; + $batssoc .= ', ' if($batssoc); + $batssoc .= "batsetsoc${bn}: $hbatssoc"; + $batsoc .= ', ' if($batsoc); + $batsoc .= "batsoc${bn}: $hbatsoc"; + } + + $ret .= "\n " if($ret); + $ret .= $key." => "; + $ret .= "pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h"; + $ret .= "\n "; + $ret .= $inve if($inve && $key ne '99'); + $ret .= "\n " if($inve && $key ne '99'); + $ret .= $invl if($invl); + $ret .= "\n " if($invl); + $ret .= $prde if($prde && $key ne '99'); + $ret .= "\n " if($prde && $key ne '99'); + $ret .= $prdl if($prdl); + $ret .= "\n " if($prdl); + $ret .= "confc: $confc, con: $con, gcons: $gcons, conprice: $conprc"; + $ret .= "\n "; + $ret .= "gfeedin: $gfeedin, feedprice: $feedprc"; + $ret .= "\n "; + $ret .= "DoN: $don, sunaz: $sunaz, sunalt: $sunalt"; + $ret .= "\n "; + + $ret .= $btotin if($key ne '99'); + $ret .= "\n " if($key ne '99'); + $ret .= $btotout if($key ne '99'); + $ret .= "\n " if($key ne '99'); + $ret .= $batsoc if($key ne '99'); + $ret .= "\n " if($key ne '99'); + + $ret .= $batin; + $ret .= "\n "; + $ret .= $batout; + $ret .= "\n "; + + $ret .= $batmsoc if($key eq '99'); + $ret .= "\n " if($key eq '99'); + $ret .= $batssoc if($key eq '99'); + $ret .= "\n " if($key eq '99'); + + if ($key ne '99') { + $ret .= "wid: $wid, "; + $ret .= "wcc: $wcc, "; + $ret .= "rr1c: $rr1c, "; + $ret .= "pvcorrf: $pvcorrf "; + } + + $ret .= "temp: $temp, " if($temp); + $ret .= "dayname: $dayname, " if($dayname); + + my $csm; + for my $c (1..$maxconsumer) { # + alle Consumer + $c = sprintf "%02d", $c; + my $nl = 0; + my $csmc = HistoryVal ($name, $day, $key, "cyclescsm${c}", undef); + my $csmt = HistoryVal ($name, $day, $key, "csmt${c}", undef); + my $csme = HistoryVal ($name, $day, $key, "csme${c}", undef); + my $csmm = HistoryVal ($name, $day, $key, "minutescsm${c}", undef); + my $csmh = HistoryVal ($name, $day, $key, "hourscsme${c}", undef); + my $csma = HistoryVal ($name, $day, $key, "avgcycmntscsm${c}", undef); + + if ($export eq 'csv') { + $hexp->{$day}{$key}{"CyclesCsm${c}"} = $csmc if(defined $csmc); + $hexp->{$day}{$key}{"Csmt${c}"} = $csmt if(defined $csmt); + $hexp->{$day}{$key}{"Csme${c}"} = $csme if(defined $csme); + $hexp->{$day}{$key}{"MinutesCsm${c}"} = $csmm if(defined $csmm); + $hexp->{$day}{$key}{"HoursCsme${c}"} = $csmh if(defined $csmh); + $hexp->{$day}{$key}{"AvgCycleMinutesCsm${c}"} = $csma if(defined $csma); + } + + if (defined $csmc) { + $csm .= "cyclescsm${c}: $csmc"; + $nl = 1; + } + + if (defined $csmt) { + $csm .= ", " if($nl); + $csm .= "csmt${c}: $csmt"; + $nl = 1; + } + + if (defined $csme) { + $csm .= ", " if($nl); + $csm .= "csme${c}: $csme"; + $nl = 1; + } + + if (defined $csmm) { + $csm .= ", " if($nl); + $csm .= "minutescsm${c}: $csmm"; + $nl = 1; + } + + if (defined $csmh) { + $csm .= ", " if($nl); + $csm .= "hourscsme${c}: $csmh"; + $nl = 1; + } + + if (defined $csma) { + $csm .= ", " if($nl); + $csm .= "avgcycmntscsm${c}: $csma"; + $nl = 1; + } + + $csm .= "\n " if($nl); + } + + if ($csm) { + $ret .= "\n "; + $ret .= $csm; + } + else { + $ret .= "\n "; + } + } + return $ret; + }; + + $h = $data{$name}{pvhist}; + + if (!keys %{$h}) { + return qq{PV cache is empty.}; + } + + for my $i (keys %{$h}) { + if (!isNumeric ($i)) { + delete $data{$name}{pvhist}{$i}; + Log3 ($name, 2, qq{$name - INFO - invalid key "$i" was deleted from pvHistory storage}); + } + } + + for my $idx (sort keys %{$h}) { + next if($par && $idx ne $par); + $sq .= $idx." => ".$sub->($idx)."\n"; + } + + if ($export eq 'csv') { + return _writeAsCsv ($hash, $hexp, $pvhexprtcsv.$name.'.csv'); + } + +return $sq; +} + ################################################################ # Listing des Circular Speichers ################################################################ @@ -18180,35 +18207,6 @@ sub _listDataPoolCircular { my $sq; - ### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !! - ########################################################################################################################## - delete $data{$name}{circular}{'01'}{pvrl_5}; - delete $data{$name}{circular}{'01'}{pvrl_10}; - delete $data{$name}{circular}{'01'}{pvrl_25}; - delete $data{$name}{circular}{'01'}{pvrl_60}; - delete $data{$name}{circular}{'01'}{pvrl_65}; - delete $data{$name}{circular}{'01'}{pvrl_90}; - - #push @{$data{$name}{circular}{'01'}{pvrl_65}{100}}, 4561; - #push @{$data{$name}{circular}{'01'}{pvrl_65}{100}}, 4562; - #push @{$data{$name}{circular}{'01'}{pvrl_65}{100}}, 4563; - #push @{$data{$name}{circular}{'01'}{pvrl_65}{100}}, 4564; - #push @{$data{$name}{circular}{'01'}{pvrl_65}{100}}, 4565; - # - #push @{$data{$name}{circular}{'01'}{pvrl_65}{60}}, 3561; - #push @{$data{$name}{circular}{'01'}{pvrl_65}{60}}, 3562; - # - #push @{$data{$name}{circular}{'01'}{pvrl_90}{100}}, 4561; - #push @{$data{$name}{circular}{'01'}{pvrl_90}{100}}, 4562; - #push @{$data{$name}{circular}{'01'}{pvrl_90}{100}}, 4563; - #push @{$data{$name}{circular}{'01'}{pvrl_90}{100}}, 4564; - #push @{$data{$name}{circular}{'01'}{pvrl_90}{100}}, 4565; - - #push @{$data{$name}{circular}{'01'}{pvrl_90}{60}}, 3561; - #push @{$data{$name}{circular}{'01'}{pvrl_90}{60}}, 3562; - - ############################################################################################################ - for my $idx (sort keys %{$h}) { next if($par && $idx ne $par);