mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 16:05:19 +00:00
76_SolarForecast: contrib 0.82.0
git-svn-id: https://svn.fhem.de/fhem/trunk@27923 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
44d27f5b81
commit
067917be2b
@ -30,18 +30,19 @@ package FHEM::SolarForecast; ## no critic 'package'
|
||||
use strict;
|
||||
use warnings;
|
||||
use POSIX;
|
||||
use GPUtils qw(GP_Import GP_Export); # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt
|
||||
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);
|
||||
|
||||
eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; ## no critic 'eval'
|
||||
eval "use FHEM::Utility::CTZ qw(:all);1" or my $ctzAbsent = 1; ## no critic 'eval'
|
||||
eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; ## no critic 'eval'
|
||||
eval "use FHEM::Utility::CTZ qw(:all);1;" or my $ctzAbsent = 1; ## no critic 'eval'
|
||||
|
||||
use Encode;
|
||||
use Color;
|
||||
use utf8;
|
||||
use HttpUtils;
|
||||
eval "use JSON;1;" or my $jsonabs = 'JSON'; ## no critic 'eval' # Debian: apt-get install libjson-perl
|
||||
eval "use AI::DecisionTree;1;" or my $aidtabs = 'AI::DecisionTree'; ## no critic 'eval'
|
||||
eval "use JSON;1;" or my $jsonabs = 'JSON'; ## no critic 'eval' # Debian: sudo apt-get install libjson-perl
|
||||
eval "use AI::DecisionTree;1;" or my $aidtabs = 'AI::DecisionTree'; ## no critic 'eval'
|
||||
eval "use Test2::Tools::Class qw(isa_ok);1;" or my $t2sabs = 'Test2::Suite'; ## no critic 'eval' # Debian: sudo apt-get install libtest2-suite-perl
|
||||
|
||||
use FHEM::SynoModules::SMUtils qw(
|
||||
evaljson
|
||||
@ -49,12 +50,11 @@ use FHEM::SynoModules::SMUtils qw(
|
||||
delClHash
|
||||
moduleVersion
|
||||
trim
|
||||
); # Hilfsroutinen Modul
|
||||
); # Hilfsroutinen Modul
|
||||
|
||||
use Data::Dumper;
|
||||
use Storable qw(dclone freeze thaw nstore store retrieve);
|
||||
use MIME::Base64;
|
||||
use Test2::Tools::Class qw(isa_ok);
|
||||
no if $] >= 5.017011, warnings => 'experimental::smartmatch';
|
||||
|
||||
# Run before module compilation
|
||||
@ -649,8 +649,10 @@ my %hqtxt = (
|
||||
DE => qq{KI Status:} },
|
||||
aimstt => { EN => qq{Perl module AI::DecisionTree is missing},
|
||||
DE => qq{Perl Modul AI::DecisionTree ist nicht vorhanden} },
|
||||
aiwook => { EN => qq{AI support works properly},
|
||||
DE => qq{KI Unterstützung arbeitet einwandfrei} },
|
||||
aimmts => { EN => qq{Perl module Test2::Suite is missing},
|
||||
DE => qq{Perl Modul Test2::Suite ist nicht vorhanden} },
|
||||
aiwook => { EN => qq{AI support works properly, but does not provide a value for the current hour},
|
||||
DE => qq{KI Unterstützung arbeitet einwandfrei, liefert jedoch keinen Wert für die aktuelle Stunde} },
|
||||
nxtscc => { EN => qq{next SolCast call},
|
||||
DE => qq{nächste SolCast Abfrage} },
|
||||
fulfd => { EN => qq{fulfilled},
|
||||
@ -4493,9 +4495,6 @@ sub centralTask {
|
||||
|
||||
_getRoofTopData ($centpars); # Strahlungswerte/Forecast-Werte in solcastapi-Hash erstellen
|
||||
_transferAPIRadiationValues ($centpars); # Raw Erzeugungswerte aus solcastapi-Hash übertragen und Forecast mit/ohne Korrektur erstellen
|
||||
|
||||
#aiGetResult ($centpars);
|
||||
|
||||
_calcMaxEstimateToday ($centpars); # heutigen Max PV Estimate & dessen Tageszeit ermitteln
|
||||
_transferInverterValues ($centpars); # WR Werte übertragen
|
||||
_transferMeterValues ($centpars); # Energy Meter auswerten
|
||||
@ -4924,9 +4923,128 @@ sub __delObsoleteAPIData {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Wetter Werte aus dem angebenen Wetterdevice extrahieren
|
||||
################################################################
|
||||
sub _transferWeatherValues {
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $paref->{name};
|
||||
my $t = $paref->{t}; # Epoche Zeit
|
||||
my $chour = $paref->{chour};
|
||||
my $daref = $paref->{daref};
|
||||
my $date = $paref->{date}; # aktuelles Datum
|
||||
|
||||
my $fcname = ReadingsVal($name, 'currentWeatherDev', ""); # Weather Forecast Device
|
||||
return if(!$fcname || !$defs{$fcname});
|
||||
|
||||
my $err = checkdwdattr ($name,$fcname,\@dweattrmust);
|
||||
$paref->{state} = $err if($err);
|
||||
|
||||
my $type = $paref->{type};
|
||||
|
||||
debugLog ($paref, "collectData", "collect Weather data - device: $fcname =>");
|
||||
|
||||
my ($time_str);
|
||||
|
||||
my $fc0_SunRise = ReadingsVal($fcname, "fc0_SunRise", "23:59"); # Sonnenaufgang heute
|
||||
my $fc0_SunSet = ReadingsVal($fcname, "fc0_SunSet", "00:00"); # Sonnenuntergang heute
|
||||
my $fc1_SunRise = ReadingsVal($fcname, "fc1_SunRise", "23:59"); # Sonnenaufgang morgen
|
||||
my $fc1_SunSet = ReadingsVal($fcname, "fc1_SunSet", "00:00"); # Sonnenuntergang morgen
|
||||
|
||||
$data{$type}{$name}{current}{sunriseToday} = $date.' '.$fc0_SunRise.':00';
|
||||
$data{$type}{$name}{current}{sunriseTodayTs} = timestringToTimestamp ($date.' '.$fc0_SunRise.':00');
|
||||
|
||||
$data{$type}{$name}{current}{sunsetToday} = $date.' '.$fc0_SunSet.':00';
|
||||
$data{$type}{$name}{current}{sunsetTodayTs} = timestringToTimestamp ($date.' '.$fc0_SunSet.':00');
|
||||
|
||||
debugLog ($paref, "collectData", "sunrise/sunset today: $fc0_SunRise / $fc0_SunSet, sunrise/sunset tomorrow: $fc1_SunRise / $fc1_SunSet");
|
||||
|
||||
push @$daref, "Today_SunRise<>". $fc0_SunRise;
|
||||
push @$daref, "Today_SunSet<>". $fc0_SunSet;
|
||||
push @$daref, "Tomorrow_SunRise<>".$fc1_SunRise;
|
||||
push @$daref, "Tomorrow_SunSet<>". $fc1_SunSet;
|
||||
|
||||
my $fc0_SunRise_round = sprintf "%02d", (split ":", $fc0_SunRise)[0];
|
||||
my $fc0_SunSet_round = sprintf "%02d", (split ":", $fc0_SunSet)[0];
|
||||
my $fc1_SunRise_round = sprintf "%02d", (split ":", $fc1_SunRise)[0];
|
||||
my $fc1_SunSet_round = sprintf "%02d", (split ":", $fc1_SunSet)[0];
|
||||
|
||||
for my $num (0..46) {
|
||||
my ($fd,$fh) = _calcDayHourMove ($chour, $num);
|
||||
last if($fd > 1);
|
||||
|
||||
my $fh1 = $fh+1;
|
||||
my $fh2 = $fh1 == 24 ? 23 : $fh1;
|
||||
my $wid = ReadingsNum($fcname, "fc${fd}_${fh2}_ww", -1);
|
||||
my $neff = ReadingsNum($fcname, "fc${fd}_${fh2}_Neff", 0); # Effektive Wolkendecke
|
||||
my $r101 = ReadingsNum($fcname, "fc${fd}_${fh2}_R101", 0); # Niederschlagswahrscheinlichkeit> 0,1 mm während der letzten Stunde
|
||||
my $temp = ReadingsNum($fcname, "fc${fd}_${fh2}_TTT", 0); # Außentemperatur
|
||||
|
||||
my $don = 1; # es ist default "Tag"
|
||||
my $fhstr = sprintf "%02d", $fh; # hier kann Tag/Nacht-Grenze verstellt werden
|
||||
|
||||
if($fd == 0 && ($fhstr lt $fc0_SunRise_round || $fhstr gt $fc0_SunSet_round)) { # Zeit vor Sonnenaufgang oder nach Sonnenuntergang heute
|
||||
$wid += 100; # "1" der WeatherID voranstellen wenn Nacht
|
||||
$don = 0;
|
||||
}
|
||||
elsif ($fd == 1 && ($fhstr lt $fc1_SunRise_round || $fhstr gt $fc1_SunSet_round)) { # Zeit vor Sonnenaufgang oder nach Sonnenuntergang morgen
|
||||
$wid += 100; # "1" der WeatherID voranstellen wenn Nacht
|
||||
$don = 0;
|
||||
}
|
||||
|
||||
my $txt = ReadingsVal($fcname, "fc${fd}_${fh2}_wwd", '');
|
||||
|
||||
debugLog ($paref, "collectData", "wid: fc${fd}_${fh1}_ww, val: $wid, txt: $txt, cc: $neff, rp: $r101, temp: $temp");
|
||||
|
||||
$time_str = "NextHour".sprintf "%02d", $num;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{weatherid} = $wid;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{cloudcover} = $neff;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{rainprob} = $r101;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{temp} = $temp;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{DoN} = $don;
|
||||
|
||||
if($num < 23 && $fh < 24) { # Ringspeicher Weather Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{weatherid} = $wid;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{weathertxt} = $txt;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{wcc} = $neff;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{wrp} = $r101;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{temp} = $temp;
|
||||
|
||||
if($num == 0) { # aktuelle Außentemperatur
|
||||
$data{$type}{$name}{current}{temp} = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
if($fd == 0 && $fh1) { # Weather in pvhistory speichern
|
||||
$paref->{wid} = $wid;
|
||||
$paref->{histname} = "weatherid";
|
||||
$paref->{nhour} = sprintf("%02d",$fh1);
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{wcc} = $neff;
|
||||
$paref->{histname} = "weathercloudcover";
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{wrp} = $r101;
|
||||
$paref->{histname} = "weatherrainprob";
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{temp} = $temp;
|
||||
$paref->{histname} = "temperature";
|
||||
setPVhistory ($paref);
|
||||
|
||||
delete $paref->{histname};
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Strahlungsvorhersage Werte aus solcastapi-Hash
|
||||
# übertragen und ggf. manipulieren
|
||||
# übertragen und PV Vorhersage berechnen / in Nexthours
|
||||
# speichern
|
||||
################################################################
|
||||
sub _transferAPIRadiationValues {
|
||||
my $paref = shift;
|
||||
@ -4957,7 +5075,7 @@ sub _transferAPIRadiationValues {
|
||||
my $wantts = (timestringToTimestamp ($date.' '.$chour.':00:00')) + ($num * 3600);
|
||||
my $wantdt = (timestampToTimestring ($wantts, $lang))[1];
|
||||
|
||||
my $time_str = "NextHour".sprintf "%02d", $num;
|
||||
my $time_str = 'NextHour'.sprintf "%02d", $num;
|
||||
my ($hod) = $wantdt =~ /\s(\d{2}):/xs;
|
||||
$hod = sprintf "%02d", int $hod + 1; # Stunde des Tages
|
||||
|
||||
@ -4969,6 +5087,7 @@ sub _transferAPIRadiationValues {
|
||||
type => $type,
|
||||
wantdt => $wantdt,
|
||||
hod => $hod,
|
||||
nhidx => $time_str,
|
||||
num => $num,
|
||||
fh1 => $fh1,
|
||||
fd => $fd,
|
||||
@ -4984,6 +5103,15 @@ sub _transferAPIRadiationValues {
|
||||
$data{$type}{$name}{nexthours}{$time_str}{today} = $fd == 0 ? 1 : 0;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{rad1h} = $rad;
|
||||
|
||||
my ($err, $pvaifc) = aiGetResult ($params); # KI Entscheidungen abfragen
|
||||
if (!$err) {
|
||||
$data{$type}{$name}{nexthours}{$time_str}{pvaifc} = $pvaifc;
|
||||
$data{$type}{$name}{current}{aigetresult} = 'ok';
|
||||
}
|
||||
else {
|
||||
$data{$type}{$name}{current}{aigetresult} = $err;
|
||||
}
|
||||
|
||||
if($num < 23 && $fh < 24) { # Ringspeicher PV forecast Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||
$data{$type}{$name}{circular}{sprintf "%02d",$fh1}{pvfc} = $est;
|
||||
}
|
||||
@ -5393,124 +5521,6 @@ sub _transferInverterValues {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Wetter Werte aus dem angebenen Wetterdevice extrahieren
|
||||
################################################################
|
||||
sub _transferWeatherValues {
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $paref->{name};
|
||||
my $t = $paref->{t}; # Epoche Zeit
|
||||
my $chour = $paref->{chour};
|
||||
my $daref = $paref->{daref};
|
||||
my $date = $paref->{date}; # aktuelles Datum
|
||||
|
||||
my $fcname = ReadingsVal($name, 'currentWeatherDev', ""); # Weather Forecast Device
|
||||
return if(!$fcname || !$defs{$fcname});
|
||||
|
||||
my $err = checkdwdattr ($name,$fcname,\@dweattrmust);
|
||||
$paref->{state} = $err if($err);
|
||||
|
||||
my $type = $paref->{type};
|
||||
|
||||
debugLog ($paref, "collectData", "collect Weather data - device: $fcname =>");
|
||||
|
||||
my ($time_str);
|
||||
|
||||
my $fc0_SunRise = ReadingsVal($fcname, "fc0_SunRise", "23:59"); # Sonnenaufgang heute
|
||||
my $fc0_SunSet = ReadingsVal($fcname, "fc0_SunSet", "00:00"); # Sonnenuntergang heute
|
||||
my $fc1_SunRise = ReadingsVal($fcname, "fc1_SunRise", "23:59"); # Sonnenaufgang morgen
|
||||
my $fc1_SunSet = ReadingsVal($fcname, "fc1_SunSet", "00:00"); # Sonnenuntergang morgen
|
||||
|
||||
$data{$type}{$name}{current}{sunriseToday} = $date.' '.$fc0_SunRise.':00';
|
||||
$data{$type}{$name}{current}{sunriseTodayTs} = timestringToTimestamp ($date.' '.$fc0_SunRise.':00');
|
||||
|
||||
$data{$type}{$name}{current}{sunsetToday} = $date.' '.$fc0_SunSet.':00';
|
||||
$data{$type}{$name}{current}{sunsetTodayTs} = timestringToTimestamp ($date.' '.$fc0_SunSet.':00');
|
||||
|
||||
debugLog ($paref, "collectData", "sunrise/sunset today: $fc0_SunRise / $fc0_SunSet, sunrise/sunset tomorrow: $fc1_SunRise / $fc1_SunSet");
|
||||
|
||||
push @$daref, "Today_SunRise<>". $fc0_SunRise;
|
||||
push @$daref, "Today_SunSet<>". $fc0_SunSet;
|
||||
push @$daref, "Tomorrow_SunRise<>".$fc1_SunRise;
|
||||
push @$daref, "Tomorrow_SunSet<>". $fc1_SunSet;
|
||||
|
||||
my $fc0_SunRise_round = sprintf "%02d", (split ":", $fc0_SunRise)[0];
|
||||
my $fc0_SunSet_round = sprintf "%02d", (split ":", $fc0_SunSet)[0];
|
||||
my $fc1_SunRise_round = sprintf "%02d", (split ":", $fc1_SunRise)[0];
|
||||
my $fc1_SunSet_round = sprintf "%02d", (split ":", $fc1_SunSet)[0];
|
||||
|
||||
for my $num (0..46) {
|
||||
my ($fd,$fh) = _calcDayHourMove ($chour, $num);
|
||||
last if($fd > 1);
|
||||
|
||||
my $fh1 = $fh+1;
|
||||
my $fh2 = $fh1 == 24 ? 23 : $fh1;
|
||||
my $wid = ReadingsNum($fcname, "fc${fd}_${fh2}_ww", -1);
|
||||
my $neff = ReadingsNum($fcname, "fc${fd}_${fh2}_Neff", 0); # Effektive Wolkendecke
|
||||
my $r101 = ReadingsNum($fcname, "fc${fd}_${fh2}_R101", 0); # Niederschlagswahrscheinlichkeit> 0,1 mm während der letzten Stunde
|
||||
my $temp = ReadingsNum($fcname, "fc${fd}_${fh2}_TTT", 0); # Außentemperatur
|
||||
|
||||
my $don = 1; # es ist default "Tag"
|
||||
my $fhstr = sprintf "%02d", $fh; # hier kann Tag/Nacht-Grenze verstellt werden
|
||||
|
||||
if($fd == 0 && ($fhstr lt $fc0_SunRise_round || $fhstr gt $fc0_SunSet_round)) { # Zeit vor Sonnenaufgang oder nach Sonnenuntergang heute
|
||||
$wid += 100; # "1" der WeatherID voranstellen wenn Nacht
|
||||
$don = 0;
|
||||
}
|
||||
elsif ($fd == 1 && ($fhstr lt $fc1_SunRise_round || $fhstr gt $fc1_SunSet_round)) { # Zeit vor Sonnenaufgang oder nach Sonnenuntergang morgen
|
||||
$wid += 100; # "1" der WeatherID voranstellen wenn Nacht
|
||||
$don = 0;
|
||||
}
|
||||
|
||||
my $txt = ReadingsVal($fcname, "fc${fd}_${fh2}_wwd", '');
|
||||
|
||||
debugLog ($paref, "collectData", "wid: fc${fd}_${fh1}_ww, val: $wid, txt: $txt, cc: $neff, rp: $r101, temp: $temp");
|
||||
|
||||
$time_str = "NextHour".sprintf "%02d", $num;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{weatherid} = $wid;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{cloudcover} = $neff;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{rainprob} = $r101;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{temp} = $temp;
|
||||
$data{$type}{$name}{nexthours}{$time_str}{DoN} = $don;
|
||||
|
||||
if($num < 23 && $fh < 24) { # Ringspeicher Weather Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{weatherid} = $wid;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{weathertxt} = $txt;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{wcc} = $neff;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{wrp} = $r101;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$fh1)}{temp} = $temp;
|
||||
|
||||
if($num == 0) { # aktuelle Außentemperatur
|
||||
$data{$type}{$name}{current}{temp} = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
if($fd == 0 && $fh1) { # Weather in pvhistory speichern
|
||||
$paref->{wid} = $wid;
|
||||
$paref->{histname} = "weatherid";
|
||||
$paref->{nhour} = sprintf("%02d",$fh1);
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{wcc} = $neff;
|
||||
$paref->{histname} = "weathercloudcover";
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{wrp} = $r101;
|
||||
$paref->{histname} = "weatherrainprob";
|
||||
setPVhistory ($paref);
|
||||
|
||||
$paref->{temp} = $temp;
|
||||
$paref->{histname} = "temperature";
|
||||
setPVhistory ($paref);
|
||||
|
||||
delete $paref->{histname};
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Werte Meter Device ermitteln und übertragen
|
||||
################################################################
|
||||
@ -8527,14 +8537,16 @@ sub _graphicHeader {
|
||||
my $aiast = CurrentVal ($hash, 'aiaddistate', 'ok');
|
||||
|
||||
my $aitit = $aidtabs ? $hqtxt{aimstt}{$lang} :
|
||||
$t2sabs ? $hqtxt{aimmts}{$lang} :
|
||||
$aiist ne 'ok' ? $hqtxt{ainuse}{$lang} :
|
||||
q{};
|
||||
|
||||
my $aiimg = $aidtabs ? FW_makeImage ('--', $aitit) :
|
||||
$t2sabs ? FW_makeImage ('--', $aitit) :
|
||||
$aiist ne 'ok' ? FW_makeImage ('-', $aitit) :
|
||||
$aitst ne 'ok' ? FW_makeImage ('10px-kreis-rot.png', $aitst) :
|
||||
$aiast ne 'ok' ? FW_makeImage ('10px-kreis-rot.png', $aiast) :
|
||||
FW_makeImage ('10px-kreis-gruen.png', $hqtxt{aiwook}{$lang});
|
||||
FW_makeImage ('10px-kreis-gelb.png', $hqtxt{aiwook}{$lang});
|
||||
|
||||
my $aiicon = qq{<a title="$aitit">$aiimg</a>};
|
||||
|
||||
@ -10568,6 +10580,8 @@ sub aiTrain { ## no critic "not used"
|
||||
return;
|
||||
}
|
||||
|
||||
####################################################################################
|
||||
|
||||
################################################################
|
||||
# AI Ergebnis für ermitteln
|
||||
################################################################
|
||||
@ -10576,50 +10590,49 @@ sub aiGetResult { ## no critic "not used"
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $paref->{name};
|
||||
my $type = $paref->{type};
|
||||
my $hod = $paref->{hod};
|
||||
my $nhidx = $paref->{nhidx};
|
||||
|
||||
return if(!isDWDUsed ($hash));
|
||||
my $err = 'no decition delivered';
|
||||
|
||||
return $err if(!isDWDUsed ($hash) || !$hod || !$nhidx);
|
||||
|
||||
my $err;
|
||||
my $dtree = AiDetreeVal ($hash, undef);
|
||||
|
||||
if (!$dtree) {
|
||||
($err, $dtree) = aiInit ($paref);
|
||||
return if($err);
|
||||
return $err if($err);
|
||||
}
|
||||
|
||||
for my $idx (sort keys %{$data{$type}{$name}{nexthours}}) {
|
||||
my $rad1h = NexthoursVal ($hash, $idx, "rad1h", undef);
|
||||
next if(!defined $rad1h);
|
||||
my $rad1h = NexthoursVal ($hash, $nhidx, "rad1h", undef);
|
||||
return "no rad1h for hod: $hod" if(!defined $rad1h);
|
||||
|
||||
my $hod = NexthoursVal ($hash, $idx, "hourofday", undef);
|
||||
next if(!defined $hod);
|
||||
my $wcc = NexthoursVal ($hash, $nhidx, "cloudcover", 0);
|
||||
my $wrp = NexthoursVal ($hash, $nhidx, "rainprob", 0);
|
||||
my $temp = NexthoursVal ($hash, $nhidx, "temp", 20);
|
||||
|
||||
my $wcc = NexthoursVal ($hash, $idx, "cloudcover", 0);
|
||||
my $wrp = NexthoursVal ($hash, $idx, "rainprob", 0);
|
||||
my $temp = NexthoursVal ($hash, $idx, "temp", 20);
|
||||
my $pvaifc;
|
||||
|
||||
my $pvfc;
|
||||
eval { $pvaifc = $dtree->get_result (attributes => { rad1h => $rad1h,
|
||||
temp => $temp,
|
||||
wcc => $wcc,
|
||||
wrp => $wrp,
|
||||
hod => $hod
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
eval { $pvfc = $dtree->get_result (attributes => { rad1h => $rad1h,
|
||||
temp => $temp,
|
||||
wcc => $wcc,
|
||||
wrp => $wrp,
|
||||
hod => $hod
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
Log3 ($name, 1, "$name - aiGetResult ERROR: $@");
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined $pvfc) {
|
||||
debugLog ($paref, 'aiProcess', qq{result AI: pvfc: $pvfc (hod: $hod, rad1h: $rad1h, wcc: $wcc, wrp: $wrp, temp: $temp)});
|
||||
}
|
||||
if ($@) {
|
||||
Log3 ($name, 1, "$name - aiGetResult ERROR: $@");
|
||||
return $@;
|
||||
}
|
||||
|
||||
return;
|
||||
if (defined $pvaifc) {
|
||||
debugLog ($paref, 'aiData', qq{result AI: pvaifc: $pvaifc (hod: $hod, rad1h: $rad1h, wcc: $wcc, wrp: $wrp, temp: $temp)});
|
||||
return ('', $pvaifc);
|
||||
}
|
||||
|
||||
return $err;
|
||||
}
|
||||
|
||||
################################################################
|
||||
@ -10633,8 +10646,9 @@ sub aiInit { ## no critic "not used"
|
||||
|
||||
my $err;
|
||||
|
||||
if ($aidtabs) {
|
||||
my $err = qq(The Perl module AI::DecisionTree is missing. Please install it with e.g. "sudo apt-get install libai-decisiontree-perl" for AI support);
|
||||
if ($aidtabs || $t2sabs) {
|
||||
$err = qq(The Perl module AI::DecisionTree is missing. Please install it with e.g. "sudo apt-get install libai-decisiontree-perl" for AI support) if($aidtabs);
|
||||
$err = qq(The Perl module Test2::Suite is missing. Please install it with e.g. "sudo apt-get install libtest2-suite-perl") if($t2sabs);
|
||||
debugLog ($paref, 'aiProcess', $err);
|
||||
$data{$type}{$name}{current}{aiinitstate} = $err;
|
||||
return $err;
|
||||
@ -11185,24 +11199,25 @@ sub listDataPool {
|
||||
return qq{NextHours cache is empty.};
|
||||
}
|
||||
for my $idx (sort keys %{$h}) {
|
||||
my $nhts = NexthoursVal ($hash, $idx, "starttime", "-");
|
||||
my $hod = NexthoursVal ($hash, $idx, "hourofday", "-");
|
||||
my $today = NexthoursVal ($hash, $idx, "today", "-");
|
||||
my $pvfc = NexthoursVal ($hash, $idx, "pvforecast", "-");
|
||||
my $wid = NexthoursVal ($hash, $idx, "weatherid", "-");
|
||||
my $neff = NexthoursVal ($hash, $idx, "cloudcover", "-");
|
||||
my $crange = NexthoursVal ($hash, $idx, "cloudrange", "-");
|
||||
my $r101 = NexthoursVal ($hash, $idx, "rainprob", "-");
|
||||
my $rad1h = NexthoursVal ($hash, $idx, "rad1h", "-");
|
||||
my $pvcorrf = NexthoursVal ($hash, $idx, "pvcorrf", "-");
|
||||
my $temp = NexthoursVal ($hash, $idx, "temp", "-");
|
||||
my $confc = NexthoursVal ($hash, $idx, "confc", "-");
|
||||
my $confcex = NexthoursVal ($hash, $idx, "confcEx", "-");
|
||||
my $don = NexthoursVal ($hash, $idx, "DoN", "-");
|
||||
my $nhts = NexthoursVal ($hash, $idx, 'starttime', "-");
|
||||
my $hod = NexthoursVal ($hash, $idx, 'hourofday', "-");
|
||||
my $today = NexthoursVal ($hash, $idx, 'today', "-");
|
||||
my $pvfc = NexthoursVal ($hash, $idx, 'pvforecast', "-");
|
||||
my $pvaifc = NexthoursVal ($hash, $idx, 'pvaifc', "-"); # PV Forecast der KI
|
||||
my $wid = NexthoursVal ($hash, $idx, 'weatherid', "-");
|
||||
my $neff = NexthoursVal ($hash, $idx, 'cloudcover', "-");
|
||||
my $crange = NexthoursVal ($hash, $idx, 'cloudrange', "-");
|
||||
my $r101 = NexthoursVal ($hash, $idx, 'rainprob', "-");
|
||||
my $rad1h = NexthoursVal ($hash, $idx, 'rad1h', "-");
|
||||
my $pvcorrf = NexthoursVal ($hash, $idx, 'pvcorrf', "-");
|
||||
my $temp = NexthoursVal ($hash, $idx, 'temp', "-");
|
||||
my $confc = NexthoursVal ($hash, $idx, 'confc', "-");
|
||||
my $confcex = NexthoursVal ($hash, $idx, 'confcEx', "-");
|
||||
my $don = NexthoursVal ($hash, $idx, 'DoN', "-");
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= $idx." => starttime: $nhts, hourofday: $hod, today: $today\n";
|
||||
$sq .= " pvfc: $pvfc, confc: $confc, confcEx: $confcex, DoN: $don\n";
|
||||
$sq .= " wid: $wid, wcc: $neff, wrp: $r101, temp=$temp\n";
|
||||
$sq .= " pvfc: $pvfc, pvaifc: $pvaifc, confc: $confc, confcEx: $confcex\n";
|
||||
$sq .= " DoN: $don, wid: $wid, wcc: $neff, wrp: $r101, temp=$temp\n";
|
||||
$sq .= " rad1h: $rad1h, crange: $crange, correff: $pvcorrf";
|
||||
}
|
||||
}
|
||||
@ -11614,6 +11629,13 @@ sub checkPlantConfig {
|
||||
$result->{'Common Settings'}{info} = 1;
|
||||
}
|
||||
|
||||
if ($t2sabs) {
|
||||
$result->{'Common Settings'}{state} = $info;
|
||||
$result->{'Common Settings'}{result} .= qq{The Perl module Test2::Suite is missing. <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{If you want use AI support, please install it with e.g. "sudo apt-get install libtest2-suite-perl".<br>};
|
||||
$result->{'Common Settings'}{info} = 1;
|
||||
}
|
||||
|
||||
if (!$pcf || $pcf !~ /on/xs) {
|
||||
$result->{'Common Settings'}{state} = $info;
|
||||
$result->{'Common Settings'}{result} .= qq{pvCorrectionFactor_Auto is set to "$pcf" <br>};
|
||||
@ -11624,8 +11646,8 @@ sub checkPlantConfig {
|
||||
$result->{'Common Settings'}{result} = $hqtxt{fulfd}{$lang};
|
||||
$result->{'Common Settings'}{note} .= qq{checked parameters: <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{pvCorrectionFactor_Auto, event-on-change-reading, ctrlLanguage, global language <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{checked Perl module: <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{AI::DecisionTree <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{checked Perl modules: <br>};
|
||||
$result->{'Common Settings'}{note} .= qq{AI::DecisionTree, Test2::Suite <br>};
|
||||
}
|
||||
}
|
||||
|
||||
@ -13932,8 +13954,9 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> </td><td>Faktor/0..1 - Qualität der PV Prognose (1 = beste Qualität) </td></tr>
|
||||
<tr><td> <b>DoN</b> </td><td>Sonnenauf- und untergangsstatus (0 - Nacht, 1 - Tag) </td></tr>
|
||||
<tr><td> <b>hourofday</b> </td><td>laufende Stunde des Tages </td></tr>
|
||||
<tr><td> <b>pvfc</b> </td><td>erwartete PV Erzeugung (Wh) </td></tr>
|
||||
<tr><td> <b>today</b> </td><td>"1" wenn Startdatum am aktuellen Tag </td></tr>
|
||||
<tr><td> <b>pvfc</b> </td><td>erwartete PV Erzeugung (Wh) ohne KI Unterstützung </td></tr>
|
||||
<tr><td> <b>pvaifc</b> </td><td>erwartete PV Erzeugung der KI (Wh) </td></tr>
|
||||
<tr><td> <b>today</b> </td><td>hat Wert '1' wenn Startdatum am aktuellen Tag </td></tr>
|
||||
<tr><td> <b>rad1h</b> </td><td>vorhergesagte Globalstrahlung </td></tr>
|
||||
<tr><td> <b>starttime</b> </td><td>Startzeit des Datensatzes </td></tr>
|
||||
<tr><td> <b>temp</b> </td><td>vorhergesagte Außentemperatur </td></tr>
|
||||
@ -14881,7 +14904,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
"Time::HiRes": 0,
|
||||
"MIME::Base64": 0,
|
||||
"Storable": 0,
|
||||
"Test2::Tools::Class": 0
|
||||
"Test2::Suite": 0
|
||||
},
|
||||
"recommends": {
|
||||
"FHEM::Meta": 0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user