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 .= ""; $ret .= ""; $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 =~ 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:

  • @@ -4459,6 +4582,28 @@ verfügbare Globalstrahlung ganz spezifisch in elektrische Energie umgewandelt.
    + +
    +