mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 03:44:52 +00:00
76_SolarForecast: remove graphicBeam1MaxVal,ctrlAreaFactorUsage
git-svn-id: https://svn.fhem.de/fhem/trunk@29581 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
a221850f21
commit
f93176ff22
@ -1,5 +1,6 @@
|
||||
# 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
|
||||
- change: 76_SolarForecast: remove graphicBeam1MaxVal,ctrlAreaFactorUsage
|
||||
- feature: 76_SolarForecast: new special readings todayBatInSum,todayBatOutSum
|
||||
- change: 73_AutoShuttersControl: Change version
|
||||
- feature: 76_SolarForecast: show historical battery SoC when displaying the
|
||||
|
@ -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,8 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.44.4" => "26.01.2025 _getlistPVCircular: change width of output, new sub _listDataPoolPvHist, fix bug in hrepl Hash ".
|
||||
"remove Attr graphicBeam1MaxVal,ctrlAreaFactorUsage ",
|
||||
"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 +177,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 ",
|
||||
@ -717,7 +720,7 @@ my %hrepl = ( # Z
|
||||
'7' => 'h',
|
||||
'8' => 'i',
|
||||
'9' => 'j',
|
||||
'.' => 'k',
|
||||
'\.' => 'k',
|
||||
);
|
||||
|
||||
my %hqtxt = ( # Hash (Setup) Texte
|
||||
@ -1449,11 +1452,10 @@ sub Initialize {
|
||||
|
||||
## Hinweis: graphicBeamXContent wird in _addDynAttr hinzugefügt
|
||||
|
||||
|
||||
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
|
||||
##########################################################################################################################
|
||||
my $av1 = "obsolete#-#the#attribute#will#be#deleted#soon"; # 12.01.25
|
||||
$hash->{AttrList} .= " graphicBeam1MaxVal:$av1 ctrlAreaFactorUsage:$av1 ";
|
||||
# my $av1 = "obsolete#-#the#attribute#will#be#deleted#soon";
|
||||
# $hash->{AttrList} .= " graphicBeam1MaxVal:$av1 ctrlAreaFactorUsage:$av1 ";
|
||||
##########################################################################################################################
|
||||
|
||||
$hash->{FW_hideDisplayName} = 1; # Forum 88667
|
||||
@ -4743,7 +4745,7 @@ sub _getlistPVCircular {
|
||||
my $hash = $defs{$name};
|
||||
|
||||
my $ret = listDataPool ($hash, 'circular', $arg);
|
||||
$ret .= lineFromSpaces ($ret, 20);
|
||||
$ret .= lineFromSpaces ($ret, 5);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
@ -5536,16 +5538,16 @@ sub Attr {
|
||||
|
||||
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
|
||||
######################################################################################################################
|
||||
if ($cmd eq 'set' && $aName =~ /^graphicBeam1MaxVal|ctrlAreaFactorUsage$/) { # 12.01.25
|
||||
my $msg = "The attribute $aName is obsolete and will be deleted soon. Please save your Configuration.";
|
||||
if (!$init_done) {
|
||||
Log3 ($name, 1, "$name - $msg");
|
||||
return qq{Device "$name" -> $msg};
|
||||
}
|
||||
else {
|
||||
return $msg;
|
||||
}
|
||||
}
|
||||
#if ($cmd eq 'set' && $aName =~ /^graphicBeam1MaxVal|ctrlAreaFactorUsage$/) {
|
||||
# my $msg = "The attribute $aName is obsolete and will be deleted soon. Please save your Configuration.";
|
||||
# if (!$init_done) {
|
||||
# Log3 ($name, 1, "$name - $msg");
|
||||
# return qq{Device "$name" -> $msg};
|
||||
# }
|
||||
# else {
|
||||
# return $msg;
|
||||
# }
|
||||
#}
|
||||
######################################################################################################################
|
||||
|
||||
if ($aName eq 'disable') {
|
||||
@ -8289,14 +8291,6 @@ sub __delObsoleteAPIData {
|
||||
delete $data{$name}{solcastapi}{$idx}{$scd} if($ds && $ds < $refts);
|
||||
}
|
||||
}
|
||||
|
||||
### nicht mehr benötigte Daten verarbeiten - Bereich kann später wieder raus !!
|
||||
##########################################################################################################################
|
||||
# 01.12.2024
|
||||
for my $idx (keys %{$data{$name}{solcastapi}{'?All'}}) { # Wetterindexe löschen (kann später raus)
|
||||
delete $data{$name}{solcastapi}{'?All'}{$idx} if($idx =~ /^fc?([0-9]{1,2})_?([0-9]{1,2})$/xs);
|
||||
}
|
||||
#####################################################################################################################
|
||||
}
|
||||
|
||||
## veraltete Strings aus Strings-Hash löschen
|
||||
@ -14848,7 +14842,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 +15246,7 @@ return $ret;
|
||||
################################################################
|
||||
# Batterieladeempfehlung in Balkengrafik
|
||||
################################################################
|
||||
sub __batRcmdOnBeam {
|
||||
sub __batteryOnBeam {
|
||||
my $paref = shift;
|
||||
my $name = $paref->{name};
|
||||
my $maxhours = $paref->{maxhours};
|
||||
@ -15370,14 +15364,13 @@ sub __batRcmdOnBeam {
|
||||
);
|
||||
|
||||
$title .= defined $currsoc ? "\n".$htitles{socbacur}{$lang}.": ".$currsoc." %" : '';
|
||||
my $image = defined $hfcg->{$i}{'rcdchargebat'.$bn} ? FW_makeImage ($bicon) : '';
|
||||
|
||||
$ret .= "<td title='$title' class='solarfc' width='$width' style='margin:1px; vertical-align:middle align:center; padding-bottom:1px;'>$image</td>";
|
||||
|
||||
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')." %");
|
||||
|
||||
my $image = defined $hfcg->{$i}{'rcdchargebat'.$bn} ? FW_makeImage ($bicon) : '';
|
||||
|
||||
$ret .= "<td title='$title' class='solarfc' width='$width' style='margin:1px; vertical-align:middle align:center; padding-bottom:1px;'>$image</td>";
|
||||
}
|
||||
|
||||
$ret .= "<td class='solarfc'></td></tr>" if($ret); # freier Platz am Ende der Icon Zeile
|
||||
@ -17631,7 +17624,70 @@ sub listDataPool {
|
||||
my $par = shift // q{};
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my ($sq, $h);
|
||||
|
||||
if ($htol eq "pvhist") {
|
||||
$sq = _listDataPoolPvHist ($hash, $par);
|
||||
}
|
||||
|
||||
if ($htol =~ /consumers|inverters|producers|strings|batteries/xs) {
|
||||
$sq = _listDataPoolVarious ($hash, $htol, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "circular") {
|
||||
$sq = _listDataPoolCircular ($hash, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "nexthours") {
|
||||
$sq = _listDataPoolNextHours ($name, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "qualities") {
|
||||
$sq = _listDataPoolQualities ($name, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "current") {
|
||||
$sq = _listDataPoolCurrent ($name, $par);
|
||||
}
|
||||
|
||||
if ($htol =~ /radiationApiData|weatherApiData|statusApiData/xs) {
|
||||
$sq = _listDataPoolApiData ($name, $htol, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "aiRawData") {
|
||||
$h = $data{$name}{aidectree}{airaw};
|
||||
my $maxcnt = keys %{$h};
|
||||
if (!$maxcnt) {
|
||||
return qq{aiRawData values cache is empty.};
|
||||
}
|
||||
|
||||
$sq = "<b>Number of datasets:</b> ".$maxcnt."\n";
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $hod = AiRawdataVal ($name, $idx, 'hod', '-');
|
||||
my $sunalt = AiRawdataVal ($name, $idx, 'sunalt', '-');
|
||||
my $sunaz = AiRawdataVal ($name, $idx, 'sunaz', '-');
|
||||
my $rad1h = AiRawdataVal ($name, $idx, 'rad1h', '-');
|
||||
my $wcc = AiRawdataVal ($name, $idx, 'wcc', '-');
|
||||
my $rr1c = AiRawdataVal ($name, $idx, 'rr1c', '-');
|
||||
my $pvrl = AiRawdataVal ($name, $idx, 'pvrl', '-');
|
||||
my $temp = AiRawdataVal ($name, $idx, 'temp', '-');
|
||||
$sq .= "\n";
|
||||
$sq .= "$idx => hod: $hod, sunaz: $sunaz, sunalt: $sunalt, rad1h: $rad1h, wcc: $wcc, rr1c: $rr1c, pvrl: $pvrl, temp: $temp";
|
||||
}
|
||||
}
|
||||
|
||||
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{};
|
||||
@ -17875,7 +17931,6 @@ sub listDataPool {
|
||||
return $ret;
|
||||
};
|
||||
|
||||
if ($htol eq "pvhist") {
|
||||
$h = $data{$name}{pvhist};
|
||||
|
||||
if (!keys %{$h}) {
|
||||
@ -17897,17 +17952,28 @@ sub listDataPool {
|
||||
if ($export eq 'csv') {
|
||||
return _writeAsCsv ($hash, $hexp, $pvhexprtcsv.$name.'.csv');
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
|
||||
if ($htol =~ /consumers|inverters|producers|strings|batteries/xs) {
|
||||
my $sub = $htol eq 'consumers' ? \&ConsumerVal :
|
||||
################################################################
|
||||
# Listing des verschiedene Speicher
|
||||
################################################################
|
||||
sub _listDataPoolVarious {
|
||||
my $hash = shift;
|
||||
my $htol = shift;
|
||||
my $par = shift // q{};
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $func = $htol eq 'consumers' ? \&ConsumerVal :
|
||||
$htol eq 'inverters' ? \&InverterVal :
|
||||
$htol eq 'producers' ? \&ProducerVal :
|
||||
$htol eq 'strings' ? \&StringVal :
|
||||
$htol eq 'batteries' ? \&BatteryVal :
|
||||
'';
|
||||
|
||||
$h = $data{$name}{$htol};
|
||||
my $h = $data{$name}{$htol};
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return ucfirst($htol).qq{ cache is empty.};
|
||||
@ -17920,6 +17986,8 @@ sub listDataPool {
|
||||
}
|
||||
}
|
||||
|
||||
my $sq;
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
next if($par && $idx ne $par);
|
||||
my ($cret, $s1);
|
||||
@ -17940,224 +18008,13 @@ sub listDataPool {
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ".$hk."\n";
|
||||
}
|
||||
else {
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ". &{$sub} ($hash, $idx, $ckey, "")."\n";
|
||||
$cret .= ($s1 ? $sp1 : "").$ckey." => ". &{$func} ($hash, $idx, $ckey, "")."\n";
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
}
|
||||
$sq .= $idx." => ".$cret."\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol eq "circular") {
|
||||
$sq = _listDataPoolCircular ($hash, $par);
|
||||
}
|
||||
|
||||
if ($htol eq "nexthours") {
|
||||
$h = $data{$name}{nexthours};
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{NextHours cache is empty.};
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $nhts = NexthoursVal ($name, $idx, 'starttime', '-');
|
||||
my $hod = NexthoursVal ($name, $idx, 'hourofday', '-');
|
||||
my $today = NexthoursVal ($name, $idx, 'today', '-');
|
||||
my $pvfc = NexthoursVal ($name, $idx, 'pvfc', '-');
|
||||
my $pvapifc = NexthoursVal ($name, $idx, 'pvapifc', '-'); # PV Forecast der API
|
||||
my $pvaifc = NexthoursVal ($name, $idx, 'pvaifc', '-'); # PV Forecast der KI
|
||||
my $aihit = NexthoursVal ($name, $idx, 'aihit', '-'); # KI ForeCast Treffer Status
|
||||
my $wid = NexthoursVal ($name, $idx, 'weatherid', '-');
|
||||
my $wcc = NexthoursVal ($name, $idx, 'wcc', '-');
|
||||
my $crang = NexthoursVal ($name, $idx, 'cloudrange', '-');
|
||||
my $rr1c = NexthoursVal ($name, $idx, 'rr1c', '-');
|
||||
my $rrange = NexthoursVal ($name, $idx, 'rainrange', '-');
|
||||
my $rad1h = NexthoursVal ($name, $idx, 'rad1h', '-');
|
||||
my $pvcorrf = NexthoursVal ($name, $idx, 'pvcorrf', '-');
|
||||
my $temp = NexthoursVal ($name, $idx, 'temp', '-');
|
||||
my $confc = NexthoursVal ($name, $idx, 'confc', '-');
|
||||
my $confcex = NexthoursVal ($name, $idx, 'confcEx', '-');
|
||||
my $don = NexthoursVal ($name, $idx, 'DoN', '-');
|
||||
my $sunaz = NexthoursVal ($name, $idx, 'sunaz', '-');
|
||||
my $sunalt = NexthoursVal ($name, $idx, 'sunalt', '-');
|
||||
|
||||
my ($rcdbat, $socs);
|
||||
for my $bn (1..$maxbatteries) { # alle Batterien
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my $rcdcharge = NexthoursVal ($name, $idx, 'rcdchargebat'.$bn, '-');
|
||||
my $socxx = NexthoursVal ($name, $idx, 'soc'.$bn, '-');
|
||||
$rcdbat .= ', ' if($rcdbat);
|
||||
$rcdbat .= "rcdchargebat${bn}: $rcdcharge";
|
||||
$socs .= ', ' if($socs);
|
||||
$socs .= "soc${bn}: $socxx";
|
||||
}
|
||||
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= $idx." => ";
|
||||
$sq .= "starttime: $nhts, hourofday: $hod, today: $today";
|
||||
$sq .= "\n ";
|
||||
$sq .= "pvapifc: $pvapifc, pvaifc: $pvaifc, pvfc: $pvfc, aihit: $aihit, confc: $confc";
|
||||
$sq .= "\n ";
|
||||
$sq .= "confcEx: $confcex, DoN: $don, weatherid: $wid, wcc: $wcc, rr1c: $rr1c, temp=$temp";
|
||||
$sq .= "\n ";
|
||||
$sq .= "rad1h: $rad1h, sunaz: $sunaz, sunalt: $sunalt";
|
||||
$sq .= "\n ";
|
||||
$sq .= "rrange: $rrange, crange: $crang, correff: $pvcorrf";
|
||||
$sq .= "\n ";
|
||||
$sq .= $socs;
|
||||
$sq .= "\n ";
|
||||
$sq .= $rcdbat;
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol eq "qualities") {
|
||||
$h = $data{$name}{nexthours};
|
||||
if (!keys %{$h}) {
|
||||
return qq{NextHours cache is empty.};
|
||||
}
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $nhfc = NexthoursVal ($hash, $idx, 'pvfc', undef);
|
||||
next if(!$nhfc);
|
||||
|
||||
my $nhts = NexthoursVal ($hash, $idx, 'starttime', '-');
|
||||
my $pvcorrf = NexthoursVal ($hash, $idx, 'pvcorrf', '-/-');
|
||||
my $aihit = NexthoursVal ($hash, $idx, 'aihit', '-');
|
||||
my $pvfc = NexthoursVal ($hash, $idx, 'pvfc', '-');
|
||||
my $wcc = NexthoursVal ($hash, $idx, 'wcc', '-');
|
||||
my $sunalt = NexthoursVal ($hash, $idx, 'sunalt', '-');
|
||||
|
||||
my ($f,$q) = split "/", $pvcorrf;
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Sun Alt: $sunalt, Cloud: $wcc";
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol eq "current") {
|
||||
$h = $data{$name}{current};
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{Current values cache is empty.};
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
if (ref $h->{$idx} eq 'ARRAY') {
|
||||
my $aser = join " ",@{$h->{$idx}};
|
||||
$sq .= $idx." => ".$aser."\n";
|
||||
}
|
||||
elsif (ref $h->{$idx} eq 'HASH') {
|
||||
my $s1;
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
$sq .= $idx." => ";
|
||||
|
||||
for my $idx1 (sort keys %{$h->{$idx}}) {
|
||||
if (ref $h->{$idx}{$idx1} eq 'HASH') {
|
||||
my $s2;
|
||||
my $sp2 = _ldpspaces ($idx1, $sp1);
|
||||
$sq .= ($s1 ? $sp1 : "").$idx1." => ";
|
||||
|
||||
for my $idx2 (sort keys %{$h->{$idx}{$idx1}}) {
|
||||
my $s3;
|
||||
my $sp3 = _ldpspaces ($idx2, $sp2);
|
||||
$sq .= ($s2 ? $sp2 : "").$idx2." => ";
|
||||
|
||||
if (ref $h->{$idx}{$idx1}{$idx2} eq 'HASH') {
|
||||
for my $idx3 (sort keys %{$h->{$idx}{$idx1}{$idx2}}) {
|
||||
$sq .= ($s3 ? $sp3 : "").$idx3." => ".(defined $h->{$idx}{$idx1}{$idx2}{$idx3} ? $h->{$idx}{$idx1}{$idx2}{$idx3} : '')."\n";
|
||||
$s3 = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= (defined $h->{$idx}{$idx1}{$idx2} ? $h->{$idx}{$idx1}{$idx2} : '')."\n";
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
$s2 = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= (defined $h->{$idx}{$idx1} ? $h->{$idx}{$idx1} : '')."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= $idx." => ".(defined $h->{$idx} ? $h->{$idx} : '')."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $git = sub {
|
||||
my $it = shift;
|
||||
my @sorted = sort { $a cmp $b } keys %$it;
|
||||
my $key = shift @sorted;
|
||||
|
||||
my $ret = {};
|
||||
$ret = { $key => $it->{$key} } if($key);
|
||||
|
||||
return $ret;
|
||||
};
|
||||
|
||||
if ($htol =~ /radiationApiData|weatherApiData|statusApiData/xs) {
|
||||
$h = $data{$name}{solcastapi};
|
||||
$h = $data{$name}{weatherapi} if($htol eq 'weatherApiData');
|
||||
$h = $data{$name}{statusapi} if($htol eq 'statusApiData');
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{The API values cache is empty.};
|
||||
}
|
||||
|
||||
my $pve = q{};
|
||||
my $itref = dclone $h; # Deep Copy von $h
|
||||
|
||||
for my $idx (sort keys %{$itref}) {
|
||||
my $s1;
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
$sq .= $idx." => ";
|
||||
|
||||
while (my ($tag, $item) = each %{$git->($itref->{$idx})}) {
|
||||
$sq .= ($s1 ? $sp1 : "").$tag." => ";
|
||||
|
||||
if (ref $item eq 'HASH') {
|
||||
my $s2;
|
||||
my $sp2 = _ldpspaces ($tag, $sp1);
|
||||
|
||||
while (my ($tag1, $item1) = each %{$git->($itref->{$idx}{$tag})}) {
|
||||
$sq .= ($s2 ? $sp2 : "")."$tag1: ".$item1."\n";
|
||||
$s2 = 1;
|
||||
delete $itref->{$idx}{$tag}{$tag1};
|
||||
}
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
$sq .= "\n" if($sq !~ /\n$/xs);
|
||||
|
||||
delete $itref->{$idx}{$tag};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($htol eq "aiRawData") {
|
||||
$h = $data{$name}{aidectree}{airaw};
|
||||
my $maxcnt = keys %{$h};
|
||||
if (!$maxcnt) {
|
||||
return qq{aiRawData values cache is empty.};
|
||||
}
|
||||
|
||||
$sq = "<b>Number of datasets:</b> ".$maxcnt."\n";
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $hod = AiRawdataVal ($hash, $idx, 'hod', '-');
|
||||
my $sunalt = AiRawdataVal ($hash, $idx, 'sunalt', '-');
|
||||
my $sunaz = AiRawdataVal ($hash, $idx, 'sunaz', '-');
|
||||
my $rad1h = AiRawdataVal ($hash, $idx, 'rad1h', '-');
|
||||
my $wcc = AiRawdataVal ($hash, $idx, 'wcc', '-');
|
||||
my $rr1c = AiRawdataVal ($hash, $idx, 'rr1c', '-');
|
||||
my $pvrl = AiRawdataVal ($hash, $idx, 'pvrl', '-');
|
||||
my $temp = AiRawdataVal ($hash, $idx, 'temp', '-');
|
||||
$sq .= "\n";
|
||||
$sq .= "$idx => hod: $hod, sunaz: $sunaz, sunalt: $sunalt, rad1h: $rad1h, wcc: $wcc, rr1c: $rr1c, pvrl: $pvrl, temp: $temp";
|
||||
}
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
@ -18178,35 +18035,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);
|
||||
|
||||
@ -18348,6 +18176,228 @@ sub _listDataPoolCircular {
|
||||
return $sq;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Listing des NextHours Speicher
|
||||
################################################################
|
||||
sub _listDataPoolNextHours {
|
||||
my $name = shift;
|
||||
my $par = shift // q{};
|
||||
|
||||
my $h = $data{$name}{nexthours};
|
||||
my $sq;
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{NextHours cache is empty.};
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $nhts = NexthoursVal ($name, $idx, 'starttime', '-');
|
||||
my $hod = NexthoursVal ($name, $idx, 'hourofday', '-');
|
||||
my $today = NexthoursVal ($name, $idx, 'today', '-');
|
||||
my $pvfc = NexthoursVal ($name, $idx, 'pvfc', '-');
|
||||
my $pvapifc = NexthoursVal ($name, $idx, 'pvapifc', '-'); # PV Forecast der API
|
||||
my $pvaifc = NexthoursVal ($name, $idx, 'pvaifc', '-'); # PV Forecast der KI
|
||||
my $aihit = NexthoursVal ($name, $idx, 'aihit', '-'); # KI ForeCast Treffer Status
|
||||
my $wid = NexthoursVal ($name, $idx, 'weatherid', '-');
|
||||
my $wcc = NexthoursVal ($name, $idx, 'wcc', '-');
|
||||
my $crang = NexthoursVal ($name, $idx, 'cloudrange', '-');
|
||||
my $rr1c = NexthoursVal ($name, $idx, 'rr1c', '-');
|
||||
my $rrange = NexthoursVal ($name, $idx, 'rainrange', '-');
|
||||
my $rad1h = NexthoursVal ($name, $idx, 'rad1h', '-');
|
||||
my $pvcorrf = NexthoursVal ($name, $idx, 'pvcorrf', '-');
|
||||
my $temp = NexthoursVal ($name, $idx, 'temp', '-');
|
||||
my $confc = NexthoursVal ($name, $idx, 'confc', '-');
|
||||
my $confcex = NexthoursVal ($name, $idx, 'confcEx', '-');
|
||||
my $don = NexthoursVal ($name, $idx, 'DoN', '-');
|
||||
my $sunaz = NexthoursVal ($name, $idx, 'sunaz', '-');
|
||||
my $sunalt = NexthoursVal ($name, $idx, 'sunalt', '-');
|
||||
|
||||
my ($rcdbat, $socs);
|
||||
for my $bn (1..$maxbatteries) { # alle Batterien
|
||||
$bn = sprintf "%02d", $bn;
|
||||
my $rcdcharge = NexthoursVal ($name, $idx, 'rcdchargebat'.$bn, '-');
|
||||
my $socxx = NexthoursVal ($name, $idx, 'soc'.$bn, '-');
|
||||
$rcdbat .= ', ' if($rcdbat);
|
||||
$rcdbat .= "rcdchargebat${bn}: $rcdcharge";
|
||||
$socs .= ', ' if($socs);
|
||||
$socs .= "soc${bn}: $socxx";
|
||||
}
|
||||
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= $idx." => ";
|
||||
$sq .= "starttime: $nhts, hourofday: $hod, today: $today";
|
||||
$sq .= "\n ";
|
||||
$sq .= "pvapifc: $pvapifc, pvaifc: $pvaifc, pvfc: $pvfc, aihit: $aihit, confc: $confc";
|
||||
$sq .= "\n ";
|
||||
$sq .= "confcEx: $confcex, DoN: $don, weatherid: $wid, wcc: $wcc, rr1c: $rr1c, temp=$temp";
|
||||
$sq .= "\n ";
|
||||
$sq .= "rad1h: $rad1h, sunaz: $sunaz, sunalt: $sunalt";
|
||||
$sq .= "\n ";
|
||||
$sq .= "rrange: $rrange, crange: $crang, correff: $pvcorrf";
|
||||
$sq .= "\n ";
|
||||
$sq .= $socs;
|
||||
$sq .= "\n ";
|
||||
$sq .= $rcdbat;
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Listing des Qualities Speicher
|
||||
################################################################
|
||||
sub _listDataPoolQualities {
|
||||
my $name = shift;
|
||||
my $par = shift // q{};
|
||||
|
||||
my $h = $data{$name}{nexthours};
|
||||
my $sq;
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{NextHours cache is empty.};
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $nhfc = NexthoursVal ($name, $idx, 'pvfc', undef);
|
||||
next if(!$nhfc);
|
||||
|
||||
my $nhts = NexthoursVal ($name, $idx, 'starttime', '-');
|
||||
my $pvcorrf = NexthoursVal ($name, $idx, 'pvcorrf', '-/-');
|
||||
my $aihit = NexthoursVal ($name, $idx, 'aihit', '-');
|
||||
my $pvfc = NexthoursVal ($name, $idx, 'pvfc', '-');
|
||||
my $wcc = NexthoursVal ($name, $idx, 'wcc', '-');
|
||||
my $sunalt = NexthoursVal ($name, $idx, 'sunalt', '-');
|
||||
|
||||
my ($f,$q) = split "/", $pvcorrf;
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Sun Alt: $sunalt, Cloud: $wcc";
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Listing des Current Speicher
|
||||
################################################################
|
||||
sub _listDataPoolCurrent {
|
||||
my $name = shift;
|
||||
my $par = shift // q{};
|
||||
|
||||
my $h = $data{$name}{current};
|
||||
my $sq;
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{Current values cache is empty.};
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$h}) {
|
||||
if (ref $h->{$idx} eq 'ARRAY') {
|
||||
my $aser = join " ",@{$h->{$idx}};
|
||||
$sq .= $idx." => ".$aser."\n";
|
||||
}
|
||||
elsif (ref $h->{$idx} eq 'HASH') {
|
||||
my $s1;
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
$sq .= $idx." => ";
|
||||
|
||||
for my $idx1 (sort keys %{$h->{$idx}}) {
|
||||
if (ref $h->{$idx}{$idx1} eq 'HASH') {
|
||||
my $s2;
|
||||
my $sp2 = _ldpspaces ($idx1, $sp1);
|
||||
$sq .= ($s1 ? $sp1 : "").$idx1." => ";
|
||||
|
||||
for my $idx2 (sort keys %{$h->{$idx}{$idx1}}) {
|
||||
my $s3;
|
||||
my $sp3 = _ldpspaces ($idx2, $sp2);
|
||||
$sq .= ($s2 ? $sp2 : "").$idx2." => ";
|
||||
|
||||
if (ref $h->{$idx}{$idx1}{$idx2} eq 'HASH') {
|
||||
for my $idx3 (sort keys %{$h->{$idx}{$idx1}{$idx2}}) {
|
||||
$sq .= ($s3 ? $sp3 : "").$idx3." => ".(defined $h->{$idx}{$idx1}{$idx2}{$idx3} ? $h->{$idx}{$idx1}{$idx2}{$idx3} : '')."\n";
|
||||
$s3 = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= (defined $h->{$idx}{$idx1}{$idx2} ? $h->{$idx}{$idx1}{$idx2} : '')."\n";
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
$s2 = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= (defined $h->{$idx}{$idx1} ? $h->{$idx}{$idx1} : '')."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sq .= $idx." => ".(defined $h->{$idx} ? $h->{$idx} : '')."\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Listing der APiData Speicher
|
||||
################################################################
|
||||
sub _listDataPoolApiData {
|
||||
my $name = shift;
|
||||
my $htol = shift;
|
||||
my $par = shift // q{};
|
||||
|
||||
my $h = $data{$name}{solcastapi};
|
||||
$h = $data{$name}{weatherapi} if($htol eq 'weatherApiData');
|
||||
$h = $data{$name}{statusapi} if($htol eq 'statusApiData');
|
||||
|
||||
if (!keys %{$h}) {
|
||||
return qq{The API values cache is empty.};
|
||||
}
|
||||
|
||||
my $git = sub {
|
||||
my $it = shift;
|
||||
my @sorted = sort { $a cmp $b } keys %$it;
|
||||
my $key = shift @sorted;
|
||||
|
||||
my $ret = {};
|
||||
$ret = { $key => $it->{$key} } if($key);
|
||||
|
||||
return $ret;
|
||||
};
|
||||
|
||||
my $sq;
|
||||
my $pve = q{};
|
||||
my $itref = dclone $h; # Deep Copy von $h
|
||||
|
||||
for my $idx (sort keys %{$itref}) {
|
||||
my $s1;
|
||||
my $sp1 = _ldpspaces ($idx, q{});
|
||||
$sq .= $idx." => ";
|
||||
|
||||
while (my ($tag, $item) = each %{$git->($itref->{$idx})}) {
|
||||
$sq .= ($s1 ? $sp1 : "").$tag." => ";
|
||||
|
||||
if (ref $item eq 'HASH') {
|
||||
my $s2;
|
||||
my $sp2 = _ldpspaces ($tag, $sp1);
|
||||
|
||||
while (my ($tag1, $item1) = each %{$git->($itref->{$idx}{$tag})}) {
|
||||
$sq .= ($s2 ? $sp2 : "")."$tag1: ".$item1."\n";
|
||||
$s2 = 1;
|
||||
delete $itref->{$idx}{$tag}{$tag1};
|
||||
}
|
||||
}
|
||||
|
||||
$s1 = 1;
|
||||
$sq .= "\n" if($sq !~ /\n$/xs);
|
||||
|
||||
delete $itref->{$idx}{$tag};
|
||||
}
|
||||
}
|
||||
|
||||
return $sq;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Hashwert aus CircularVal in formatierten String umwandeln
|
||||
################################################################
|
||||
|
Loading…
x
Reference in New Issue
Block a user