diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index 4bcc4d5ff..2237842c2 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -119,6 +119,8 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "0.37.0" => "17.04.2021 estConsumptionForecast, new getter forecastQualities, new setter currentRadiationDev ".
+ "language sensitive setup hints ",
"0.36.1" => "14.04.2021 add dayname to pvHistory ",
"0.36.0" => "14.04.2021 add con to pvHistory, add quality info to pvCircular, new reading nextPolltime ",
"0.35.0" => "12.04.2021 create additional PVforecast events - PV forecast until the end of the coming day ",
@@ -171,6 +173,7 @@ my %vNotesIntern = (
my %hset = ( # Hash der Set-Funktion
currentForecastDev => { fn => \&_setcurrentForecastDev },
+ currentRadiationDev => { fn => \&_setcurrentRadiationDev },
modulePeakString => { fn => \&_setmodulePeakString },
inverterStrings => { fn => \&_setinverterStrings },
currentInverterDev => { fn => \&_setinverterDevice },
@@ -203,14 +206,15 @@ my %hset = ( # Ha
);
my %hget = ( # Hash für Get-Funktion (needcred => 1: Funktion benötigt gesetzte Credentials)
- data => { fn => \&_getdata, needcred => 0 },
- html => { fn => \&_gethtml, needcred => 0 },
- ftui => { fn => \&_getftui, needcred => 0 },
- valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
- pvHistory => { fn => \&_getlistPVHistory, needcred => 0 },
- pvCircular => { fn => \&_getlistPVCircular, needcred => 0 },
- nextHours => { fn => \&_getlistNextHours, needcred => 0 },
- stringConfig => { fn => \&_getstringConfig, needcred => 0 },
+ data => { fn => \&_getdata, needcred => 0 },
+ html => { fn => \&_gethtml, needcred => 0 },
+ ftui => { fn => \&_getftui, needcred => 0 },
+ valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
+ pvHistory => { fn => \&_getlistPVHistory, needcred => 0 },
+ pvCircular => { fn => \&_getlistPVCircular, needcred => 0 },
+ forecastQualities => { fn => \&_getForecastQualities, needcred => 0 },
+ nextHours => { fn => \&_getlistNextHours, needcred => 0 },
+ stringConfig => { fn => \&_getstringConfig, needcred => 0 },
);
my %hff = ( # Flächenfaktoren
@@ -227,6 +231,25 @@ my %hff = (
"90" => { N => 33, NE => 43, E => 62, SE => 78, S => 85, SW => 78, W => 62, NW => 43 },
);
+my %hqtxt = ( # Hash Setup Texte
+ cfd => { EN => qq{Please select the Weather forecast device with "set LINK currentForecastDev"},
+ DE => qq{Bitte geben sie das Wettervorhersage Device mit "set LINK currentForecastDev" an} },
+ crd => { EN => qq{Please select the Radiation forecast device with "set LINK currentRadiationDev"},
+ DE => qq{Bitte geben sie das Strahlungsvorhersage Device mit "set LINK currentRadiationDev" an} },
+ cid => { EN => qq{Please select the Inverter device with "set LINK currentInverterDev"},
+ DE => qq{Bitte geben sie das Wechselrichter Device mit "set LINK currentInverterDev" an} },
+ ist => { EN => qq{Please define all of your used string names with "set LINK inverterStrings"},
+ DE => qq{Bitte geben sie alle von Ihnen verwendeten Stringnamen mit "set LINK inverterStrings" an} },
+ mps => { EN => qq{Please specify the total peak power for every string with "set LINK modulePeakString"},
+ DE => qq{Bitte geben sie die Gesamtspitzenleistung für jeden String mit "set LINK modulePeakString" an} },
+ mdr => { EN => qq{Please specify the module direction with "set LINK moduleDirection"},
+ DE => qq{Bitte geben Sie die Modulausrichtung mit "set LINK moduleDirection" an} },
+ mta => { EN => qq{Please specify the module tilt angle with "set LINK moduleTiltAngle"},
+ DE => qq{Bitte geben Sie den Modulneigungswinkel mit "set LINK moduleTiltAngle" an} },
+ awd => { EN => qq{Awaiting data from Solar Forecast devices ...},
+ DE => qq{Warten auf Daten von Solarvorhersagegeräten ...} },
+);
+
my %weather_ids = (
# s => 0 , 0 - 3 DWD -> kein signifikantes Wetter
# s => 1 , 45 - 99 DWD -> signifikantes Wetter
@@ -354,7 +377,8 @@ my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_";
my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt)
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
-my @dwdattrmust = qw(Rad1h TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des DWD_Opendata Devices mindestens gesetzt sein müssen
+my @dweattrmust = qw(TTT Neff R101 ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
+my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
my $cldampdef = 45; # Dämpfung (%) des Korrekturfaktors bzgl. effektiver Bewölkung, siehe: https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
@@ -540,6 +564,7 @@ sub Set {
$setlist = "Unknown argument $opt, choose one of ".
"currentForecastDev:$fcd ".
+ "currentRadiationDev:$fcd ".
"currentBatteryDev:textField-long ".
"currentInverterDev:textField-long ".
"currentMeterDev:textField-long ".
@@ -580,10 +605,10 @@ sub _setcurrentForecastDev { ## no critic "not used"
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
- my $prop = $paref->{prop} // return qq{no PV forecast device specified};
+ my $prop = $paref->{prop} // return qq{no forecast device specified};
if(!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData") {
- return qq{Forecast device "$prop" doesn't exist or has no TYPE "DWD_OpenData"}; #' :)
+ return qq{The device "$prop" doesn't exist or has no TYPE "DWD_OpenData"}; #' :)
}
readingsSingleUpdate($hash, "currentForecastDev", $prop, 1);
@@ -592,6 +617,25 @@ sub _setcurrentForecastDev { ## no critic "not used"
return;
}
+################################################################
+# Setter currentRadiationDev
+################################################################
+sub _setcurrentRadiationDev { ## no critic "not used"
+ my $paref = shift;
+ my $hash = $paref->{hash};
+ my $name = $paref->{name};
+ my $prop = $paref->{prop} // return qq{no radiation device specified};
+
+ if(!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData") {
+ return qq{The device "$prop" doesn't exist or has no TYPE "DWD_OpenData"}; #' :)
+ }
+
+ readingsSingleUpdate($hash, "currentRadiationDev", $prop, 1);
+ createNotifyDev ($hash);
+
+return;
+}
+
################################################################
# Setter currentInverterDev
################################################################
@@ -1014,6 +1058,7 @@ sub Get {
my $getlist = "Unknown argument $opt, choose one of ".
"data:noArg ".
+ "forecastQualities:noArg ".
"html:noArg ".
"nextHours:noArg ".
"pvCircular:noArg ".
@@ -1075,15 +1120,12 @@ return pageAsHtml ($hash,"ftui");
}
###############################################################
-# Getter listPVHistory
+# Getter pvHistory
###############################################################
sub _getlistPVHistory {
my $paref = shift;
my $hash = $paref->{hash};
- my $name = $hash->{NAME};
- my $type = $hash->{TYPE};
-
my $ret = listDataPool ($hash, "pvhist");
return $ret;
@@ -1096,29 +1138,35 @@ sub _getlistPVCircular {
my $paref = shift;
my $hash = $paref->{hash};
- my $name = $hash->{NAME};
- my $type = $hash->{TYPE};
-
my $ret = listDataPool ($hash, "circular");
return $ret;
}
###############################################################
-# Getter listNextHours
+# Getter nextHours
###############################################################
sub _getlistNextHours {
my $paref = shift;
my $hash = $paref->{hash};
- my $name = $hash->{NAME};
- my $type = $hash->{TYPE};
-
my $ret = listDataPool ($hash, "nexthours");
return $ret;
}
+###############################################################
+# Getter pvQualities
+###############################################################
+sub _getForecastQualities {
+ my $paref = shift;
+ my $hash = $paref->{hash};
+
+ my $ret = listDataPool ($hash, "qualities");
+
+return $ret;
+}
+
###############################################################
# Getter valCurrent
###############################################################
@@ -1126,9 +1174,6 @@ sub _getlistCurrent {
my $paref = shift;
my $hash = $paref->{hash};
- my $name = $hash->{NAME};
- my $type = $hash->{TYPE};
-
my $ret = listDataPool ($hash, "current");
return $ret;
@@ -1294,27 +1339,27 @@ return;
################################################################
sub centralTask {
my $hash = shift;
- my $name = $hash->{NAME}; # Name des eigenen Devices
+ my $name = $hash->{NAME};
my $type = $hash->{TYPE};
RemoveInternalTimer($hash, "FHEM::SolarForecast::centralTask");
### nicht mehr benötigte Readings/Daten löschen - kann später wieder raus !!
- for my $i (keys %{$data{$type}{$name}{pvhist}}) {
- delete $data{$type}{$name}{pvhist}{$i}{"00"};
- delete $data{$type}{$name}{pvhist}{$i} if(!$i); # evtl. vorhandene leere Schlüssel entfernen
- }
+ #for my $i (keys %{$data{$type}{$name}{pvhist}}) {
+ # delete $data{$type}{$name}{pvhist}{$i}{"00"};
+ # delete $data{$type}{$name}{pvhist}{$i} if(!$i); # evtl. vorhandene leere Schlüssel entfernen
+ #}
- deleteReadingspec ($hash, "Today_Hour.*_Consumption");
- deleteReadingspec ($hash, "ThisHour_.*");
- deleteReadingspec ($hash, "Today_PV");
- deleteReadingspec ($hash, "Tomorrow_PV");
- deleteReadingspec ($hash, "Next04Hours_PV");
- deleteReadingspec ($hash, "Next.*HoursPVforecast");
- deleteReadingspec ($hash, "moduleEfficiency");
- deleteReadingspec ($hash, "RestOfDay_PV");
- deleteReadingspec ($hash, "CurrentHourPVforecast");
- deleteReadingspec ($hash, "NextHours_Sum00_PVforecast");
+ #deleteReadingspec ($hash, "Today_Hour.*_Consumption");
+ #deleteReadingspec ($hash, "ThisHour_.*");
+ #deleteReadingspec ($hash, "Today_PV");
+ #deleteReadingspec ($hash, "Tomorrow_PV");
+ #deleteReadingspec ($hash, "Next04Hours_PV");
+ #deleteReadingspec ($hash, "Next.*HoursPVforecast");
+ #deleteReadingspec ($hash, "moduleEfficiency");
+ #deleteReadingspec ($hash, "RestOfDay_PV");
+ #deleteReadingspec ($hash, "CurrentHourPVforecast");
+ #deleteReadingspec ($hash, "NextHours_Sum00_PVforecast");
my $interval = controlParams ($name);
@@ -1380,8 +1425,9 @@ sub centralTask {
createReadingsFromArray ($hash, \@da, 1);
}
- calcVariance ($params); # Autokorrektur berechnen
- saveEnergyConsumption ($params); # Energie Hausverbrauch speichern
+ calcVariance ($params); # Autokorrektur berechnen
+ saveEnergyConsumption ($params); # Energie Hausverbrauch speichern
+ estConsumptionForecast ($params);
readingsSingleUpdate($hash, "state", $params->{state}, 1); # Abschluß state
}
@@ -1612,16 +1658,18 @@ sub _transferDWDForecastValues {
my $chour = $paref->{chour};
my $daref = $paref->{daref};
- my $fcname = ReadingsVal($name, "currentForecastDev", ""); # aktuelles Forecast Device
- return if(!$fcname || !$defs{$fcname});
+ my $raname = ReadingsVal($name, "currentRadiationDev", ""); # Radiation Forecast Device
+ return if(!$raname || !$defs{$raname});
my ($time_str,$epoche);
my $type = $hash->{TYPE};
my $uac = ReadingsVal($name, "pvCorrectionFactor_Auto", "off"); # Auto- oder manuelle Korrektur
-
- my @aneeded = checkdwdattr ($fcname);
+
+ my @aneeded = checkdwdattr ($raname,\@draattrmust);
if (@aneeded) {
- Log3($name, 2, qq{$name - ERROR - the attribute "forecastProperties" of device "$fcname" must contain: }.join ",",@aneeded);
+ my $err = qq{ERROR - the attribute "forecastProperties" of device "$raname" must contain: }.join ",",@aneeded;
+ $paref->{state} = $err;
+ Log3($name, 2, "$name - $err");
}
for my $num (0..47) {
@@ -1634,9 +1682,9 @@ sub _transferDWDForecastValues {
my $fh1 = $fh+1;
my $fh2 = $fh1 == 24 ? 23 : $fh1;
- my $rad = ReadingsVal($fcname, "fc${fd}_${fh2}_Rad1h", 0);
+ my $rad = ReadingsVal($raname, "fc${fd}_${fh2}_Rad1h", 0);
- Log3($name, 5, "$name - collect DWD forecast data: device=$fcname, rad=fc${fd}_${fh2}_Rad1h, Rad1h=$rad");
+ Log3($name, 5, "$name - collect Radiation data: device=$raname, rad=fc${fd}_${fh2}_Rad1h, Rad1h=$rad");
my $params = {
hash => $hash,
@@ -1692,9 +1740,16 @@ sub _transferWeatherValues {
my $chour = $paref->{chour};
my $daref = $paref->{daref};
- my $fcname = ReadingsVal($name, "currentForecastDev", ""); # aktuelles Forecast Device
+ my $fcname = ReadingsVal($name, "currentForecastDev", ""); # Weather Forecast Device
return if(!$fcname || !$defs{$fcname});
+ my @aneeded = checkdwdattr ($fcname,\@dweattrmust);
+ if (@aneeded) {
+ my $err = qq{ERROR - the attribute "forecastProperties" of device "$fcname" must contain: }.join ",",@aneeded;
+ $paref->{state} = $err;
+ Log3($name, 2, "$name - $err");
+ }
+
my $type = $hash->{TYPE};
my ($time_str);
@@ -2221,23 +2276,25 @@ sub _calcSummaries {
push @{$data{$type}{$name}{current}{h4fcslidereg}}, int $next4HoursSum->{PV}; # Schieberegister 4h Summe Forecast
limitArray ($data{$type}{$name}{current}{h4fcslidereg}, $defslidenum);
- my $gcon = CurrentVal ($hash, "gridconsumption", 0); # Berechnung aktueller Verbrauch
- my $pvgen = CurrentVal ($hash, "generation", 0);
- my $gfeedin = CurrentVal ($hash, "gridfeedin", 0);
- my $batin = CurrentVal ($hash, "powerbatin", 0); # aktuelle Batterieladung
- my $batout = CurrentVal ($hash, "powerbatout", 0); # aktuelle Batterieentladung
+ my $gcon = CurrentVal ($hash, "gridconsumption", 0); # aktueller Netzbezug
+ my $tconsum = CurrentVal ($hash, "tomorrowconsumption", 0); # Verbrauchsprognose für morgigen Tag
+ my $pvgen = CurrentVal ($hash, "generation", 0);
+ my $gfeedin = CurrentVal ($hash, "gridfeedin", 0);
+ my $batin = CurrentVal ($hash, "powerbatin", 0); # aktuelle Batterieladung
+ my $batout = CurrentVal ($hash, "powerbatout", 0); # aktuelle Batterieentladung
my $consumption = $pvgen - $gfeedin + $gcon - $batin + $batout;
$data{$type}{$name}{current}{consumption} = $consumption;
- push @$daref, "Current_Consumption<>". $consumption. " W";
- push @$daref, "NextHours_Sum01_PVforecast<>".(int $next1HoursSum->{PV})." Wh";
- push @$daref, "NextHours_Sum02_PVforecast<>".(int $next2HoursSum->{PV})." Wh";
- push @$daref, "NextHours_Sum03_PVforecast<>".(int $next3HoursSum->{PV})." Wh";
- push @$daref, "NextHours_Sum04_PVforecast<>".(int $next4HoursSum->{PV})." Wh";
- push @$daref, "RestOfDayPVforecast<>". (int $restOfDaySum->{PV}). " Wh";
- push @$daref, "Tomorrow_PVforecast<>". (int $tomorrowSum->{PV}). " Wh";
- push @$daref, "Today_PVforecast<>". (int $todaySum->{PV}). " Wh";
+ push @$daref, "Current_Consumption<>". $consumption. " W";
+ push @$daref, "Tomorrow_ConsumptionForecast<>".$tconsum. " Wh";
+ push @$daref, "NextHours_Sum01_PVforecast<>". (int $next1HoursSum->{PV})." Wh";
+ push @$daref, "NextHours_Sum02_PVforecast<>". (int $next2HoursSum->{PV})." Wh";
+ push @$daref, "NextHours_Sum03_PVforecast<>". (int $next3HoursSum->{PV})." Wh";
+ push @$daref, "NextHours_Sum04_PVforecast<>". (int $next4HoursSum->{PV})." Wh";
+ push @$daref, "RestOfDayPVforecast<>". (int $restOfDaySum->{PV}). " Wh";
+ push @$daref, "Tomorrow_PVforecast<>". (int $tomorrowSum->{PV}). " Wh";
+ push @$daref, "Today_PVforecast<>". (int $todaySum->{PV}). " Wh";
return;
}
@@ -2282,6 +2339,46 @@ sub saveEnergyConsumption {
return;
}
+################################################################
+# Energieverbrauch Vorhersage kalkulieren
+#
+# Es werden nur gleiche Wochentage (Mo ... So)
+# zusammengefasst und der Durchschnitt ermittelt als
+# Vorhersage
+################################################################
+sub estConsumptionForecast {
+ my $paref = shift;
+ my $hash = $paref->{hash};
+ my $name = $paref->{name};
+ my $chour = $paref->{chour};
+ my $t = $paref->{t};
+
+ my $type = $hash->{TYPE};
+
+ ## Verbrauchsvorhersage für den nächsten Tag
+ ##############################################
+ my $tomorrow = strftime "%a", localtime($t+86400); # Wochentagsname morgen
+ my $totcon = 0;
+ my $dnum = 0;
+
+ for my $n (1..31) {
+ my $hdn = HistoryVal ($hash, sprintf("%02d",$n), 99, "dayname", undef);
+ next if(!$hdn || $hdn ne $tomorrow);
+
+ $totcon += HistoryVal ($hash, sprintf("%02d",$n), 99, "con", 0);
+ $dnum++;
+ }
+
+ if ($dnum) {
+ $data{$type}{$name}{current}{tomorrowconsumption} = $totcon/$dnum; # Durchschnittsverbrauch aller gleicher Wochentage
+ }
+ else {
+ $data{$type}{$name}{current}{tomorrowconsumption} = "Wait for more days with a consumption figure";
+ }
+
+return;
+}
+
################################################################
# FHEMWEB Fn
################################################################
@@ -2402,18 +2499,20 @@ sub forecastGraphic {
$hash->{HELPER}{SPGROOM} = $FW_room ? $FW_room : ""; # Raum aus dem das SMAPortalSPG-Device die Funktion aufrief
$hash->{HELPER}{SPGDETAIL} = $FW_detail ? $FW_detail : ""; # Name des SMAPortalSPG-Devices (wenn Detailansicht)
- my $fcdev = ReadingsVal ($name, "currentForecastDev", ""); # aktuelles Forecast Device
- my $indev = ReadingsVal ($name, "currentInverterDev", ""); # aktuelles Inverter Device
+ my $lang = AttrVal ("global", "language", "EN");
+ my $fcdev = ReadingsVal ($name, "currentForecastDev", "" ); # Forecast Device (Wetter)
+ my $radev = ReadingsVal ($name, "currentRadiationDev", "" ); # Forecast Device (Wetter)
+ my $indev = ReadingsVal ($name, "currentInverterDev", "" ); # Inverter Device
my ($a,$h) = parseParams ($indev);
$indev = $a->[0] // "";
my $pv0 = NexthoursVal ($hash, "NextHour00", "pvforecast", undef);
- my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
- my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
- my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
- my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
+ my $is = ReadingsVal ($name, "inverterStrings", undef); # String Konfig
+ my $peak = ReadingsVal ($name, "modulePeakString", undef); # String Peak
+ my $dir = ReadingsVal ($name, "moduleDirection", undef); # Modulausrichtung Konfig
+ my $ta = ReadingsVal ($name, "moduleTiltAngle", undef); # Modul Neigungswinkel Konfig
- if(!$is || !$fcdev || !$indev || !$peak || !defined $pv0 || !$dir || !$ta) {
+ if(!$is || !$fcdev || !$radev || !$indev || !$peak || !defined $pv0 || !$dir || !$ta) {
my $link = qq{$name};
$height = AttrNum($name, 'beamHeight', 200);
$ret .= "
";
@@ -2421,30 +2520,34 @@ sub forecastGraphic {
$ret .= "";
if(!$fcdev) { ## no critic 'Cascading'
- $ret .= qq{Please select a Solar Forecast device with "set $link currentForecastDev"};
+ $ret .= $hqtxt{cfd}{$lang};
+ }
+ elsif(!$radev) {
+ $ret .= $hqtxt{crd}{$lang};
}
elsif(!$indev) {
- $ret .= qq{Please select an Inverter device with "set $link currentInverterDev"};
+ $ret .= $hqtxt{cid}{$lang};
}
elsif(!$is) {
- $ret .= qq{Please define all of your used string names with "set $link inverterStrings".};
+ $ret .= $hqtxt{ist}{$lang};
}
elsif(!$peak) {
- $ret .= qq{Please specify the total peak power for every string with "set $link modulePeakString"};
+ $ret .= $hqtxt{mps}{$lang};
}
elsif(!$dir) {
- $ret .= qq{Please specify the module direction with "set $link moduleDirection"};
+ $ret .= $hqtxt{mdr}{$lang};
}
elsif(!$ta) {
- $ret .= qq{Please specify the module tilt angle with "set $link moduleTiltAngle"};
+ $ret .= $hqtxt{mta}{$lang};
}
elsif(!defined $pv0) {
- $ret .= qq{Awaiting data from selected Solar Forecast device ...};
+ $ret .= $hqtxt{awd}{$lang};
}
$ret .= " | ";
$ret .= "";
$ret .= "
";
+ $ret =~ s/LINK/$link/gxs;
return $ret;
}
@@ -2539,15 +2642,15 @@ sub forecastGraphic {
# Beispiel mit Farbe: $icon = FW_makeImage('light_light_dim_100.svg@green');
$icon = FW_makeImage($icon) if (defined($icon));
- my $co4h = ReadingsNum ($name,"Next04Hours_Consumption", 0);
- my $coRe = ReadingsNum ($name,"RestOfDay_Consumption", 0);
- my $coTo = ReadingsNum ($name,"Tomorrow_Consumption", 0);
- my $coCu = ReadingsNum ($name,"Current_Consumption", 0);
+ my $co4h = ReadingsNum ($name,"Next04Hours_Consumption", 0);
+ my $coRe = ReadingsNum ($name,"RestOfDay_Consumption", 0);
+ my $coTo = ReadingsNum ($name,"Tomorrow_ConsumptionForecast", 0);
+ my $coCu = ReadingsNum ($name,"Current_Consumption", 0);
- my $pv4h = ReadingsNum ($name,"NextHours_Sum04_PVforecast", 0);
- my $pvRe = ReadingsNum ($name,"RestOfDayPVforecast", 0);
- my $pvTo = ReadingsNum ($name,"Tomorrow_PVforecast", 0);
- my $pvCu = ReadingsNum ($name,"Current_PV", 0);
+ my $pv4h = ReadingsNum ($name,"NextHours_Sum04_PVforecast", 0);
+ my $pvRe = ReadingsNum ($name,"RestOfDayPVforecast", 0);
+ my $pvTo = ReadingsNum ($name,"Tomorrow_PVforecast", 0);
+ my $pvCu = ReadingsNum ($name,"Current_PV", 0);
my $pcfa = ReadingsVal ($name,"pvCorrectionFactor_Auto", "off");
@@ -2576,9 +2679,7 @@ sub forecastGraphic {
# Headerzeile generieren
##########################
if ($header) {
- my $lang = AttrVal ("global", "language", "EN" );
my $alias = AttrVal ($name, "alias", $name ); # Linktext als Aliasname
-
my $dlink = "$alias";
my $lup = ReadingsTimestamp($name, ".lastupdateForecastValues", "0000-00-00 00:00:00"); # letzter Forecast Update
@@ -3323,11 +3424,12 @@ return ($ts,$tsdef,$realts);
################################################################
sub checkdwdattr {
my $dwddev = shift;
+ my $amref = shift;
my @fcprop = map { trim($_) } split ",", AttrVal($dwddev, "forecastProperties", "pattern");
my @aneeded;
- for my $am (@dwdattrmust) {
+ for my $am (@$amref) {
next if($am ~~ @fcprop);
push @aneeded, $am;
}
@@ -3885,6 +3987,21 @@ sub listDataPool {
}
}
+ if ($htol eq "qualities") {
+ $h = $data{$type}{$name}{nexthours};
+ if (!keys %{$h}) {
+ return qq{NextHours cache is empty.};
+ }
+ for my $idx (sort keys %{$h}) {
+ my $nhts = NexthoursVal ($hash, $idx, "starttime", undef);
+ my $pvcorrf = NexthoursVal ($hash, $idx, "pvcorrf", undef);
+ $pvcorrf //= "-/-";
+ my ($f,$q) = split "/", $pvcorrf;
+ $sq .= "\n" if($sq);
+ $sq .= "starttime: $nhts, quality: $q, used factor: $f";
+ }
+ }
+
if ($htol eq "current") {
$h = $data{$type}{$name}{current};
if (!keys %{$h}) {
@@ -4040,12 +4157,16 @@ sub createNotifyDev {
if($init_done == 1) {
my @nd;
- my ($afc,$ain,$ame,$h);
+ my ($afc,$ara,$ain,$ame,$h);
- my $fcdev = ReadingsVal($name, "currentForecastDev", ""); # Forecast Device
+ my $fcdev = ReadingsVal($name, "currentForecastDev", ""); # Weather forecast Device
($afc,$h) = parseParams ($fcdev);
$fcdev = $afc->[0] // "";
+ my $radev = ReadingsVal($name, "currentRadiationDev", ""); # Radiation forecast Device
+ ($ara,$h) = parseParams ($radev);
+ $radev = $ara->[0] // "";
+
my $indev = ReadingsVal($name, "currentInverterDev", ""); # Inverter Device
($ain,$h) = parseParams ($indev);
$indev = $ain->[0] // "";
@@ -4056,6 +4177,7 @@ sub createNotifyDev {
$medev = $ame->[0] // "";
push @nd, $fcdev;
+ push @nd, $radev if($radev ne $fcdev);
push @nd, $indev;
push @nd, $medev;
@@ -4086,6 +4208,7 @@ return;
# wcc - Grad der Bewölkung
# wrp - Niederschlagswahrscheinlichkeit
# pvcorrf - PV Autokorrekturfaktor f. Stunde des Tages
+# dayname - Tagesname (Kürzel)
# $def: Defaultwert
#
######################################################################
@@ -4367,18 +4490,18 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
currentForecastDev
- Legt das Device (Typ DWD_OpenData) fest, welches die Daten der solaren Vorhersage liefert. Ist noch kein Device dieses Typs
- vorhanden, muß es manuell definiert werden (siehe DWD_OpenData Commandref).
+ Legt das Device (Typ DWD_OpenData) fest, welches die Wetterdaten (Bewölkung, Niederschlag, usw.) liefert.
+ Ist noch kein Device dieses Typs vorhanden, muß es manuell definiert werden
+ (siehe DWD_OpenData Commandref).
Im ausgewählten DWD_OpenData Device müssen mindestens diese Attribute gesetzt sein:
- forecastDays | 1 |
- forecastProperties | Rad1h,TTT,Neff,R101,ww,SunUp,SunRise,SunSet |
- forecastResolution | 1 |
- forecastStation | <Stationscode der ausgewerteten DWD Station> |
- | Hinweis: Die ausgewählte forecastStation muß Strahlungswerte (Rad1h Readings) liefern. |
+ forecastDays | 1 |
+ forecastProperties | TTT,Neff,R101,ww,SunUp,SunRise,SunSet |
+ forecastResolution | 1 |
+ forecastStation | <Stationscode der ausgewerteten DWD Station> |
@@ -4459,6 +4582,28 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
+
+
+ - currentRadiationDev
+
+ Legt das Device (Typ DWD_OpenData) fest, welches die solaren Strahlungsdaten liefert. Ist noch kein Device dieses Typs
+ vorhanden, muß es manuell definiert werden (siehe DWD_OpenData Commandref).
+ Im ausgewählten DWD_OpenData Device müssen mindestens diese Attribute gesetzt sein:
+
+
+
+
+ forecastDays | 1 |
+ forecastProperties | Rad1h |
+ forecastResolution | 1 |
+ forecastStation | <Stationscode der ausgewerteten DWD Station> |
+ | Hinweis: Die ausgewählte forecastStation muß Strahlungswerte (Rad1h Readings) liefern. |
+
+
+
+
+
+
- energyH4Trigger <1on>=<Wert> <1off>=<Wert> [<2on>=<Wert> <2off>=<Wert> ...]
@@ -4630,19 +4775,30 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
Get
-
+
-
- - html
- Die Solar Grafik wird als HTML-Code abgerufen und wiedergegeben.
+
+ - data
+ Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
-
- - data
- Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
+
+ - forecastQualities
+ Zeigt die aktuell verwendeten Korrekturfaktoren mit der jeweiligen Startzeit zur Bestimmung der PV Vorhersage sowie
+ deren Qualitäten an.
+ Die Qualität ergibt sich aus der Anzahl der bereits in der Vergangenheit bewerteten Tage mit einer
+ identischen Bewölkungsrange.
+
+
+
+
+
+
+ - html
+ Die Solar Grafik wird als HTML-Code abgerufen und wiedergegeben.