| ";
- if(!$fcdev) { ## no critic 'Cascading'
+ if (!$wedev) { ## no critic 'Cascading'
$ret .= $hqtxt{cfd}{$lang};
}
- elsif(!$radev) {
+ elsif (!$radev) {
$ret .= $hqtxt{crd}{$lang};
}
- elsif(!$indev) {
+ elsif (!$indev) {
$ret .= $hqtxt{cid}{$lang};
}
- elsif(!$medev) {
+ elsif (!$medev) {
$ret .= $hqtxt{mid}{$lang};
}
- elsif(!$is) {
+ elsif (!$is) {
$ret .= $hqtxt{ist}{$lang};
}
- elsif(!$peaks) {
+ elsif (!$peaks) {
$ret .= $hqtxt{mps}{$lang};
}
- elsif(!$rip && isSolCastUsed ($hash)) { # Verwendung SolCast API
+ elsif (!$rip && isSolCastUsed ($hash)) {
$ret .= $hqtxt{rip}{$lang};
}
- elsif(!$mrt && isSolCastUsed ($hash)) { # Verwendung SolCast API
+ elsif (!$mrt && isSolCastUsed ($hash)) {
$ret .= $hqtxt{mrt}{$lang};
}
- elsif(!$dir && !isSolCastUsed ($hash)) { # Verwendung DWD / Forecast.Solar API Strahlungsdevice
+ elsif (!$dir && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
$ret .= $hqtxt{mdr}{$lang};
}
- elsif(!$ta && !isSolCastUsed ($hash)) { # Verwendung DWD / Forecast.Solar API Strahlungsdevice
+ elsif (!$ta && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
$ret .= $hqtxt{mta}{$lang};
}
- elsif (!$coset && isForecastSolarUsed ($hash)) { # Verwendung Forecast.Solar API Strahlungsdevice
+ elsif (!$vrmcr && isVictronKiUsed ($hash)) {
+ $ret .= $hqtxt{vrmcr}{$lang};
+ }
+ elsif (!$coset && isForecastSolarUsed ($hash)) {
$ret .= $hqtxt{coord}{$lang};
}
- elsif(!defined $pv0) {
+ elsif (!defined $pv0) {
$ret .= $hqtxt{awd}{$lang};
}
@@ -7817,24 +8349,25 @@ sub _graphicHeader {
## Solare API Sektion
########################
my $api = isSolCastUsed ($hash) ? 'SolCast:' :
- isForecastSolarUsed ($hash) ? 'Forecast.Solar:' :
+ isForecastSolarUsed ($hash) ? 'Forecast.Solar:' :
+ isVictronKiUsed ($hash) ? 'VictronVRM:' :
q{};
+
+ my $nscc = ReadingsVal ($name, 'nextSolCastCall', '?');
+ my $lrt = SolCastAPIVal ($hash, '?All', '?All', 'lastretrieval_time', '-');
+ my $scrm = SolCastAPIVal ($hash, '?All', '?All', 'response_message', '-');
+
+ if ($lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x) {
+ my ($sly, $slmo, $sld, $slt) = $lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x;
+ $lrt = "$sly-$slmo-$sld $slt";
+
+ if($lang eq "DE") {
+ $lrt = "$sld.$slmo.$sly $slt";
+ }
+ }
if ($api eq 'SolCast:') {
- my $nscc = ReadingsVal ($name, 'nextSolCastCall', '?');
- my $lrt = SolCastAPIVal ($hash, '?All', '?All', 'lastretrieval_time', '-');
-
- if ($lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x) {
- my ($sly, $slmo, $sld, $slt) = $lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x;
- $lrt = "$sly-$slmo-$sld $slt";
-
- if($lang eq "DE") {
- $lrt = "$sld.$slmo.$sly $slt";
- }
- }
-
$api .= ' '.$lrt;
- my $scrm = SolCastAPIVal ($hash, '?All', '?All', 'response_message', '-');
if ($scrm eq 'success') {
$img = FW_makeImage ('10px-kreis-gruen.png', $htitles{scaresps}{$lang}.'
'.$htitles{natc}{$lang}.' '.$nscc);
@@ -7864,20 +8397,7 @@ sub _graphicHeader {
$api .= '';
}
elsif ($api eq 'Forecast.Solar:') {
- my $nscc = ReadingsVal ($name, 'nextSolCastCall', '?');
- my $lrt = SolCastAPIVal ($hash, '?All', '?All', 'lastretrieval_time', '-');
-
- if ($lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x) {
- my ($sly, $slmo, $sld, $slt) = $lrt =~ /(\d{4})-(\d{2})-(\d{2})\s+(.*)/x;
- $lrt = "$sly-$slmo-$sld $slt";
-
- if($lang eq "DE") {
- $lrt = "$sld.$slmo.$sly $slt";
- }
- }
-
$api .= ' '.$lrt;
- my $scrm = SolCastAPIVal ($hash, '?All', '?All', 'response_message', '-');
if ($scrm eq 'success') {
$img = FW_makeImage('10px-kreis-gruen.png', $htitles{scaresps}{$lang}.'
'.$htitles{natc}{$lang}.' '.$nscc);
@@ -7900,6 +8420,26 @@ sub _graphicHeader {
$api .= ')';
$api .= '';
}
+ elsif ($api eq 'VictronVRM:') {
+ $api .= ' '.$lrt;
+
+ if ($scrm eq 'success') {
+ $img = FW_makeImage('10px-kreis-gruen.png', $htitles{scaresps}{$lang}.'
'.$htitles{natc}{$lang}.' '.$nscc);
+ }
+ else {
+ $img = FW_makeImage('10px-kreis-rot.png', $htitles{scarespf}{$lang}.': '. $scrm);
+ }
+
+ $scicon = "$img";
+
+ $api .= ' '.$scicon;
+ $api .= '';
+ $api .= ' (';
+ $api .= SolCastAPIVal ($hash, '?All', '?All', 'todayDoneAPIrequests', 0);
+ $api .= ')';
+ $api .= '';
+ }
+
## Qualitäts-Icon
######################
@@ -9444,31 +9984,22 @@ sub _calcCaQcomplex {
my ($oldfac, $oldq) = CircularAutokorrVal ($hash, sprintf("%02d",$h), $range, 0); # bisher definierter Korrekturfaktor/KF-Qualität der Stunde des Tages der entsprechenden Bewölkungsrange
$oldfac = 1 if(1 * $oldfac == 0);
- my $factor;
- my ($usenhd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ?
-
- if ($dnum) { # Werte in History vorhanden -> haben Prio !
- $dnum = $dnum + 1;
- $pvre = ($pvre + $pvhis) / $dnum; # Ertrag aktuelle Stunde berücksichtigen
- $pvfc = ($pvfc + $fchis) / $dnum; # Vorhersage aktuelle Stunde berücksichtigen
- $factor = sprintf "%.2f", ($pvre / $pvfc); # Faktorberechnung: reale PV / Prognose
- }
- elsif ($oldfac && !$usenhd) { # keine Werte in History vorhanden, aber in CircularVal && keine Beschränkung durch Attr affectNumHistDays
- $dnum = 1;
- $factor = sprintf "%.2f", ($pvre / $pvfc);
- $factor = sprintf "%.2f", ($factor + $oldfac) / 2;
- }
- else { # ganz neuer Wert
- $factor = sprintf "%.2f", ($pvre / $pvfc);
- $dnum = 1;
- }
+ (my $factor, $dnum) = __calcNewFactor ({ name => $name,
+ oldfac => $oldfac,
+ dnum => $dnum,
+ pvre => $pvre,
+ pvfc => $pvfc,
+ pvhis => $pvhis,
+ fchis => $fchis
+ }
+ );
if (abs($factor - $oldfac) > $maxvar) {
$factor = sprintf "%.2f", ($factor > $oldfac ? $oldfac + $maxvar : $oldfac - $maxvar);
Log3 ($name, 3, "$name - new correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h");
}
else {
- Log3 ($name, 3, "$name - new correction factor calculated: $factor (old: $oldfac) for hour: $h calculated") if($factor != $oldfac);
+ Log3 ($name, 3, "$name - new complex correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac);
}
$pvre = sprintf "%.0f", $pvre;
@@ -9517,7 +10048,8 @@ sub __Pv_Fc_Complex_Dnum_Hist {
$hour = sprintf("%02d",$hour);
my $pvhh = $data{$type}{$name}{pvhist};
- my ($usenhd, $calcd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ? und welcher Wert
+ my ($dnum , $pvrl, $pvfc) = (0,0,0);
+ my ($usenhd, $calcd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ? und welcher Wert
my @k = sort {$a<=>$b} keys %{$pvhh};
my $ile = $#k; # Index letztes Arrayelement
@@ -9554,9 +10086,6 @@ sub __Pv_Fc_Complex_Dnum_Hist {
debugLog ($paref, 'pvCorrection', "Complex Corrf -> cloudiness range of day/hour $day/$hour is: $range");
- my $dnum = 0;
- my ($pvrl,$pvfc) = (0,0);
-
for my $dayfa (@efa) {
my $histwcc = HistoryVal ($hash, $dayfa, $hour, "wcc", undef); # historische Wolkenbedeckung
@@ -9594,27 +10123,6 @@ sub __Pv_Fc_Complex_Dnum_Hist {
return ($pvhis,$fchis,$dnum,$range);
}
-################################################################
-# Ist Attribut 'affectNumHistDays' gesetzt ?
-# $usenhd: 1 - ja, 0 - nein
-# $nhd : Anzahl der zu verwendenden HistDays
-################################################################
-sub __useNumHistDays {
- my $name = shift;
-
- my $usenhd = 0;
- my $nhd = AttrVal($name, 'affectNumHistDays', $calcmaxd+1);
-
- if($nhd == $calcmaxd+1) {
- $nhd = $calcmaxd;
- }
- else {
- $usenhd = 1;
- }
-
-return ($usenhd, $nhd);
-}
-
################################################################
# PV Ist/Forecast ermitteln und Korrekturfaktoren, Qualität
# ohne Nebenfaktoren errechnen und speichern (simple)
@@ -9623,12 +10131,12 @@ sub _calcCaQsimple {
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
- my $chour = $paref->{chour}; # aktuelle Stunde
+ my $chour = $paref->{chour}; # aktuelle Stunde
my $date = $paref->{date};
my $daref = $paref->{daref};
my $acu = $paref->{acu};
- my $maxvar = AttrVal($name, 'affectMaxDayVariance', $defmaxvar); # max. Korrekturvarianz
+ my $maxvar = AttrVal($name, 'affectMaxDayVariance', $defmaxvar); # max. Korrekturvarianz
for my $h (1..23) {
next if(!$chour || $h > $chour);
@@ -9647,37 +10155,27 @@ sub _calcCaQsimple {
next if(!$pvre);
$paref->{hour} = $h;
- my ($pvhis,$fchis,$dnum) = __Pv_Fc_Simple_Dnum_Hist ($paref); # historischen Percentilfaktor / Qualität ermitteln
+ my ($pvhis,$fchis,$dnum) = __Pv_Fc_Simple_Dnum_Hist ($paref); # historischen Percentilfaktor / Qualität ermitteln
my ($oldfac, $oldq) = CircularAutokorrVal ($hash, sprintf("%02d",$h), 'percentile', 0);
- $oldfac = 1.0 if(1 * $oldfac == 0 || $oldfac >= 10);
+ $oldfac = 1 if(1 * $oldfac == 0);
- my $factor;
- my ($usenhd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ?
-
- if ($dnum) { # Werte in History vorhanden -> haben Prio !
- $dnum++;
- $pvre = ($pvre + $pvhis) / $dnum; # Ertrag aktuelle Stunde berücksichtigen
- $pvfc = ($pvfc + $fchis) / $dnum; # Vorhersage aktuelle Stunde berücksichtigen
- $factor = sprintf "%.2f", ($pvre / $pvfc); # Faktorberechnung: reale PV / Prognose
- }
- elsif ($oldfac && !$usenhd) { # keine Werte in History vorhanden, aber in CircularVal && keine Beschränkung durch Attr affectNumHistDays
- $dnum = 1;
- $factor = sprintf "%.2f", ($pvre / $pvfc);
- $factor = sprintf "%.2f", ($factor + $oldfac) / 2;
- }
- else { # ganz neuer Wert
- $dnum = 1;
- $factor = sprintf "%.2f", ($pvre / $pvfc);
- $oldfac = '-';
- }
+ (my $factor, $dnum) = __calcNewFactor ({ name => $name,
+ oldfac => $oldfac,
+ dnum => $dnum,
+ pvre => $pvre,
+ pvfc => $pvfc,
+ pvhis => $pvhis,
+ fchis => $fchis
+ }
+ );
if (abs($factor - $oldfac) > $maxvar) {
$factor = sprintf "%.2f", ($factor > $oldfac ? $oldfac + $maxvar : $oldfac - $maxvar);
Log3 ($name, 3, "$name - new correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h");
}
else {
- Log3 ($name, 3, "$name - new correction factor calculated: $factor (old: $oldfac) for hour: $h calculated") if($factor != $oldfac);
+ Log3 ($name, 3, "$name - new simple correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac);
}
$pvre = sprintf "%.0f", $pvre;
@@ -9718,14 +10216,15 @@ sub __Pv_Fc_Simple_Dnum_Hist {
$hour = sprintf("%02d",$hour);
my $pvhh = $data{$type}{$name}{pvhist};
-
- my ($usenhd, $calcd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ? und welcher Wert
+
+ my ($dnum , $pvrl, $pvfc) = (0,0,0);
+ my ($usenhd, $calcd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ? und welcher Wert
my @k = sort {$a<=>$b} keys %{$pvhh};
my $ile = $#k; # Index letztes Arrayelement
my ($idx) = grep {$k[$_] eq "$day"} (0..@k-1); # Index des aktuellen Tages
- return if(!defined $idx);
+ return ($pvrl, $pvfc, $dnum) if(!defined $idx);
my $ei = $idx-1;
$ei = $ei < 0 ? $ile : $ei;
@@ -9743,14 +10242,10 @@ sub __Pv_Fc_Simple_Dnum_Hist {
}
else {
debugLog ($paref, "pvCorrection", "Simple Corrf -> Day $day has index $idx. Use only current day for average calc");
- return 0;
+ return ($pvrl, $pvfc, $dnum);
}
- my $dnum = 0;
- my ($pvrl,$pvfc) = (0,0);
-
for my $dayfa (@efa) {
-
$pvrl += HistoryVal ($hash, $dayfa, $hour, "pvrl", 0);
$pvfc += HistoryVal ($hash, $dayfa, $hour, "pvfc", 0);
$dnum++;
@@ -9758,10 +10253,12 @@ sub __Pv_Fc_Simple_Dnum_Hist {
debugLog ($paref, "pvCorrection", "Simple Corrf -> historical Day/hour $dayfa/$hour included -> PVreal: $pvrl, PVforecast: $pvfc");
last if($dnum == $calcd);
}
+
+ $dnum = 0 if(!$pvrl && !$pvfc); # es gab keine gespeicherten Werte in pvHistory
if(!$dnum) {
Log3 ($name, 5, "$name - PV History -> no historical PV data forecast and real found");
- return 0;
+ return ($pvrl, $pvfc, $dnum);
}
my $pvhis = sprintf "%.2f", $pvrl;
@@ -9770,6 +10267,63 @@ sub __Pv_Fc_Simple_Dnum_Hist {
return ($pvhis, $fchis, $dnum);
}
+################################################################
+# den neuen Korrekturfaktur berechnen
+################################################################
+sub __calcNewFactor {
+ my $paref = shift;
+
+ my $name = $paref->{name};
+ my $oldfac = $paref->{oldfac};
+ my $dnum = $paref->{dnum};
+ my $pvre = $paref->{pvre};
+ my $pvfc = $paref->{pvfc};
+ my $pvhis = $paref->{pvhis};
+ my $fchis = $paref->{fchis};
+
+ my $factor;
+ my ($usenhd) = __useNumHistDays ($name); # ist Attr affectNumHistDays gesetzt ?
+
+ if ($dnum) { # Werte in History vorhanden -> haben Prio !
+ $dnum++;
+ $pvre = ($pvre + $pvhis) / $dnum; # Ertrag aktuelle Stunde berücksichtigen
+ $pvfc = ($pvfc + $fchis) / $dnum; # Vorhersage aktuelle Stunde berücksichtigen
+ $factor = sprintf "%.2f", ($pvre / $pvfc); # Faktorberechnung: reale PV / Prognose
+ }
+ elsif ($oldfac && !$usenhd) { # keine Werte in History vorhanden, aber in CircularVal && keine Beschränkung durch Attr affectNumHistDays
+ $dnum = 1;
+ $factor = sprintf "%.2f", ($pvre / $pvfc);
+ $factor = sprintf "%.2f", ($factor + $oldfac) / 2;
+ }
+ else { # ganz neuer Wert
+ $dnum = 1;
+ $factor = sprintf "%.2f", ($pvre / $pvfc);
+ }
+
+return ($factor, $dnum);
+}
+
+################################################################
+# Ist Attribut 'affectNumHistDays' gesetzt ?
+# $usenhd: 1 - ja, 0 - nein
+# $nhd : Anzahl der zu verwendenden HistDays
+################################################################
+sub __useNumHistDays {
+ my $name = shift;
+
+ my $usenhd = 0;
+ my $nhd = AttrVal($name, 'affectNumHistDays', $calcmaxd+1);
+
+ if($nhd == $calcmaxd+1) {
+ $nhd = $calcmaxd;
+ }
+ else {
+ $usenhd = 1;
+ }
+
+return ($usenhd, $nhd);
+}
+
################################################################
# Qualität der Vorhersage berechnen
################################################################
@@ -10510,12 +11064,18 @@ sub checkPlantConfig {
$result->{'String Configuration'}{warn} = 1;
}
- if (!isSolCastUsed ($hash)) { # Strahlungsdevice DWD
+ if (!isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
if ($sp !~ /dir.*?peak.*?tilt/x) {
$result->{'String Configuration'}{state} = $nok;
$result->{'String Configuration'}{fault} = 1; # Test Vollständigkeit: z.B. Süddach => dir: S, peak: 5.13, tilt: 45
}
}
+ elsif (isVictronKiUsed ($hash)) {
+ if($sp !~ /KI-based\s=>\speak/xs) {
+ $result->{'String Configuration'}{state} = $nok;
+ $result->{'String Configuration'}{fault} = 1;
+ }
+ }
else { # Strahlungsdevice SolCast-API
if($sp !~ /peak.*?pk/x) {
$result->{'String Configuration'}{state} = $nok;
@@ -10523,12 +11083,12 @@ sub checkPlantConfig {
}
}
}
-
+
$result->{'String Configuration'}{result} = $hqtxt{fulfd}{$lang} if(!$result->{'String Configuration'}{fault} && !$result->{'String Configuration'}{warn});
## Check Attribute DWD Wetterdevice
#####################################
- my $fcname = ReadingsVal($name, 'currentForecastDev', '');
+ my $fcname = ReadingsVal($name, 'currentWeatherDev', '');
if (!$fcname || !$defs{$fcname}) {
$result->{'DWD Weather Attributes'}{state} = $nok;
@@ -10746,7 +11306,7 @@ sub checkPlantConfig {
$result->{'Common Settings'}{result} = $hqtxt{fulfd}{$lang};
$result->{'Common Settings'}{note} .= qq{checked parameters: }; $result->{'Common Settings'}{note} .= qq{affectCloudfactorDamping, affectRainfactorDamping, ctrlSolCastAPIoptimizeReq }; - $result->{'Common Settings'}{note} .= qq{pvCorrectionFactor_Auto, event-on-change-reading, ctrlLanguage, global language }; + $result->{'Common Settings'}{note} .= qq{pvCorrectionFactor_Auto, event-on-change-reading, ctrlLanguage, global language, global dnsServer }; } } @@ -10765,6 +11325,41 @@ sub checkPlantConfig { $result->{'Common Settings'}{note} .= qq{pvCorrectionFactor_Auto, event-on-change-reading, ctrlLanguage, global language }; } } + + ## allg. Settings bei Nutzung VictronKI-API + ############################################# + if (isVictronKiUsed ($hash)) { + my $gdn = AttrVal ('global', 'dnsServer', ''); + my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt + + if ($pcf && $pcf !~ /off/xs) { + $result->{'Common Settings'}{state} = $warn; + $result->{'Common Settings'}{result} .= qq{pvCorrectionFactor_Auto is set to "$pcf" }; + $result->{'Common Settings'}{note} .= qq{set pvCorrectionFactor_Auto to "off" is recommended because of this API is KI based. }; + $result->{'Common Settings'}{warn} = 1; + } + + if (!$vrmcr) { + $result->{'API Access'}{state} = $nok; + $result->{'API Access'}{result} .= qq{The Victron VRM Portal credentials are not set. }; + $result->{'API Access'}{note} .= qq{set the credentials with command "set $name vrmCredentials". }; + $result->{'API Access'}{fault} = 1; + } + + if (!$gdn) { + $result->{'API Access'}{state} = $nok; + $result->{'API Access'}{result} .= qq{Attribute dnsServer in global device is not set. }; + $result->{'API Access'}{note} .= qq{set global attribute dnsServer to the IP Adresse of your DNS Server. }; + $result->{'API Access'}{fault} = 1; + } + + if (!$result->{'Common Settings'}{fault} && !$result->{'Common Settings'}{warn} && !$result->{'Common Settings'}{info}) { + $result->{'Common Settings'}{result} = $hqtxt{fulfd}{$lang}; + $result->{'Common Settings'}{note} .= qq{checked parameters: }; + $result->{'Common Settings'}{note} .= qq{affectCloudfactorDamping, affectRainfactorDamping, global dnsServer, global language }; + $result->{'Common Settings'}{note} .= qq{pvCorrectionFactor_Auto, vrmCredentials, event-on-change-reading, ctrlLanguage }; + } + } ## Ausgabe ############ @@ -10855,10 +11450,17 @@ return; ################################################################ # Timestrings berechnen +# gibt Zeitstring in lokaler Zeit zurück ################################################################ sub timestampToTimestring { my $epoch = shift; my $lang = shift; + + return if($epoch !~ /[0-9]/xs); + + if (length ($epoch) == 13) { # Millisekunden + $epoch = $epoch / 1000; + } my ($lyear,$lmonth,$lday,$lhour,$lmin,$lsec) = (localtime($epoch))[5,4,3,2,1,0]; my $tm; @@ -10899,6 +11501,21 @@ sub timestringToTimestamp { return $timestamp; } +################################################################ +# einen Zeitstring YYYY-MM-TT hh:mm:ss in einen Unix +# Timestamp GMT umwandeln +################################################################ +sub timestringToTimestampGMT { + my $tstring = shift; + + my($y, $mo, $d, $h, $m, $s) = $tstring =~ /([0-9]{4})-([0-9]{2})-([0-9]{2})\s([0-9]{2}):([0-9]{2}):([0-9]{2})/xs; + return if(!$mo || !$y); + + my $tsgm = fhemTimeGm ($s, $m, $h, $d, $mo-1, $y-1900); + +return $tsgm; +} + ################################################################ # Zeitstring der Form 2023-05-27T14:24:30+02:00 formatieren # in YYYY-MM-TT hh:mm:ss @@ -10970,7 +11587,7 @@ sub debugLog { my $name = $paref->{name}; my $debug = $paref->{debug}; - if($debug =~ /$dreg/x) { + if ($debug =~ /$dreg/x) { Log3 ($name, 1, "$name DEBUG> $dmsg"); } @@ -11008,7 +11625,7 @@ sub createAssociatedWith { my (@cd,@nd); my ($afc,$ara,$ain,$ame,$aba,$h); - my $fcdev = ReadingsVal($name, "currentForecastDev", ""); # Weather forecast Device + my $fcdev = ReadingsVal($name, "currentWeatherDev", ""); # Weather forecast Device ($afc,$h) = parseParams ($fcdev); $fcdev = $afc->[0] // ""; @@ -11099,6 +11716,9 @@ sub setModel { elsif ($api =~ /ForecastSolar/xs) { $hash->{MODEL} = 'ForecastSolarAPI'; } + elsif ($api =~ /VictronKI/xs) { + $hash->{MODEL} = 'VictronKiAPI'; + } else { $hash->{MODEL} = 'DWD'; deleteReadingspec ($hash, 'nextSolCastCall'); @@ -11513,6 +12133,21 @@ sub isForecastSolarUsed { return $ret; } +################################################################ +# Prüfung auf Verwendung von Victron VRM API (KI basierend) +################################################################ +sub isVictronKiUsed { + my $hash = shift; + + my $ret = 0; + + if ($hash->{MODEL} && $hash->{MODEL} eq 'VictronKiAPI') { + $ret = 1; + } + +return $ret; +} + ################################################################ # welche PV Autokorrektur wird verwendet ? # Standard bei nur "on" -> on_simple @@ -11677,7 +12312,7 @@ return $debug; } ################################################################ -# Namen des Consumerdivices und des zugeordneten +# Namen des Consumerdevices und des zugeordneten # Switch Devices ermitteln ################################################################ sub getCDnames { @@ -11691,6 +12326,36 @@ sub getCDnames { return ($cname, $dswname); } +############################################################################### +# verscrambelt einen String +############################################################################### +sub chew { + my $sstr = shift; + + $sstr = encode_base64 ($sstr, ''); + my @key = qw(1 3 4 5 6 3 2 1 9); + my $len = scalar @key; + my $i = 0; + my $dstr = join "", map { $i = ($i + 1) % $len; chr((ord($_) + $key[$i]) % 256) } split //, $sstr; ## no critic 'Map blocks'; + +return $dstr; +} + +############################################################################### +# entpackt einen mit _enscramble behandelten String +############################################################################### +sub assemble { + my $sstr = shift; + + my @key = qw(1 3 4 5 6 3 2 1 9); + my $len = scalar @key; + my $i = 0; + my $dstr = join "", map { $i = ($i + 1) % $len; chr((ord($_) - $key[$i] + 256) % 256) } split //, $sstr; ## no critic 'Map blocks'; + $dstr = decode_base64 ($dstr); + +return $dstr; +} + ################################################################ # Funktion um userspezifische Programmaufrufe nach # Aktualisierung aller Readings zu ermöglichen @@ -11836,7 +12501,7 @@ return $def; # $q: Qualität des Korrekturfaktors # # $hod: Stunde des Tages (01,02,...,24) -# $range: Range Bewölkung (1...10) +# $range: Range Bewölkung (1...100) oder "percentile" # $def: Defaultwert # ################################################################ @@ -11956,7 +12621,7 @@ return $def; ################################################################################################### # Wert des String Hash zurückliefern # Usage: -# StringVal ($hash, $strg, $key, $def) +# StringVal ($hash, $strg, $key, $def) # # $strg: - Name des Strings aus modulePeakString # $key: peak - Peakleistung aus modulePeakString @@ -12138,7 +12803,7 @@ Zur Erstellung der solaren Vorhersage kann das Modul SolarForecast unterschiedli Die Nutzung der erwähnten API's beschränkt sich auf die jeweils kostenlose Version des Dienstes. -In zugeordneten DWD_OpenData Device(s) ist die passende Wetterstation mit dem Setter "currentForecastDev" +In zugeordneten DWD_OpenData Device(s) ist die passende Wetterstation mit dem Setter "currentWeatherDev" festzulegen um meteorologische Daten (Bewölkung, Sonnenaufgang, u.a.) bzw. eine Strahlungsprognose (falls Model DWD genutzt) für den Anlagenstandort zu erhalten. @@ -12175,7 +12840,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|