Anwendungsbeispiel JsonMod - SolCast Solar-Vorhersage abrufen

Begonnen von freetz, 11 August 2021, 09:05:22

Vorheriges Thema - Nächstes Thema

Aurel_B

Hallo zusammen,

ich habe unterdessen auch noch die Prognose von "SolarForecast" (nicht zu verwechseln mit "SolCast", Thread siehe: https://forum.fhem.de/index.php/topic,117864.1335.html) integriert und jetzt 2 Monate Erfahrung damit gesammelt. Fazit? SolarForecast ist eher pessimistisch, SolCast eher optimistisch in der Prognose: werde wohl den Mittelwert verwenden. Generell scheinen die Prognosen recht vernünftig zu sein wobei es keine grossen Unterschiede zwischen einer Prognose am Abend vorher (um 22h) und am Morgen früh (um 7h) zu geben. Details siehe Graphiken im Anhang.

ch.eick

#31
Zitat von: ansgru am 02 März 2022, 07:54:45
Hallo zusammen,

ich habe unterdessen auch noch die Prognose von "SolarForecast" (nicht zu verwechseln mit "SolCast", Thread siehe: https://forum.fhem.de/index.php/topic,117864.1335.html) integriert und jetzt 2 Monate Erfahrung damit gesammelt. Fazit? SolarForecast ist eher pessimistisch, SolCast eher optimistisch in der Prognose: werde wohl den Mittelwert verwenden. Generell scheinen die Prognosen recht vernünftig zu sein wobei es keine grossen Unterschiede zwischen einer Prognose am Abend vorher (um 22h) und am Morgen früh (um 7h) zu geben. Details siehe Graphiken im Anhang.
Hallo,
was Du aus dem SolarForecast für die Leistungsprognose entnommen hast kommt ursprünglich von mir aus der Solar_forecast() Funktion :-)

Dies basiert auf den DWD rad1h Daten und wurde extra pessimistisch ausgelegt.
In meiner Funktion kann man dann mit einem fixen Faktor - bei mir momentan 1.2 - alle Werte etwas anheben.
Das Original Solar_forecast() verwendet für die Autokorrektur noch das DbLog/DbRep und errechnet stündliche korrekturfaktoren,
die dann ebenfalls mit einem Faktor nochmal angehoben oder abgesenkt werden können.

Die Werte um 07:00 und um 22:00 Uhr sind aufgrund der Winkel Korrektur für den Einstrahlungswinkel auf die Solar Module sehr schwierig.
Bei mir habe ich es zwischen 6:00 und 21:00 Uhr als Solar Zeit begrenzt. Je nach Sonnenstand aus dem Astro Modul werden einige Winkel
bewust verworfen, wodurch dann als Ergebnis 0 zurück kommt. Momentan ergeben sich beim heutigen Datum dann plausieble Werte von
8:00 bis 18:00 Uhr, wobei das die 0 Werte im Graphen sind.

Je nach Aufruf der Solar_forecast() Funktion wird die Leistungsprognose für heute oder morgen erstellt. Die Werte für morgen stehen dann
auch schon bereits in der DbLog und lassen sich in Grafana mit Angabe des morgigen Datums schon anschauen. Am aktuellen Tag können dann
beide Kurven verglichen werden und man erkennt die Korrektur des DWD.

Wolken, Regen und die Modultemperatur werden ebenfalls berücksichtigt.

VG Christian

EDIT: ich habe nochmal ein Bild der Prognose mit der realität angehängt.
Das ist ohne Autokorrektur und mit einem festen Faktor von 1.2 , der für meine Anlage festgelegt wurde.
Man sieht auch schön die verworfenen Werte vor 8:00 und nach 18:00 Uhr mit ihrem Wert von 0.
Die bunten Linien sind die einzelnen Strings mit Ost/Süd/West Ausrichtung, wobei im Westen 2 Strings (oben/unten) sind.
Morgens und Abends schalte ich auch noch das Schatten Management ein, wodurch der Ertrag rein optisch gesehen verbessert wurde,
Messwerte zum Unterschied habe ich dazu nicht.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Aurel_B

Hallo Christian,

vielen Dank für deine Nachricht, das sind sehr nützliche Infos! Im Moment passt die etwas pessimistischere Auslegung tiptop in's Konzept weil der Mittelwert von SolarForecast und SolCast eine ziemlich gute Prognose ergibt. Die Nulldurchgänge sind bei mir im Moment bei 6 & 18h -> vielleicht, weil wir etwas weiter südlich wohnen? Ich werde geg. die Prognosezeitpunkte anpassen.

Sehr cool an dieser Prognose ist z.B., das ich den Warmwasserspeicher bei Bedarf zusätzlich via Heizstab auf bis zu 70° aufheizen kann falls "magere" Tage prognostiziert werden. So habe ich quasi eine "thermische" Batterie :-)

Beste Grüsse, Anton

sn0000py

Hallo mal ne kurze Frage hier rein, seit der Sommerzeit, sind die Grafen von Solcast um eine Stunde verschoben, hat schon wer die Stelle korrigiert?

der-Lolo

Zitat von: ansgru am 15 Dezember 2021, 16:03:36
Hier als mal der Monat November dargestellt: grün ist der tatsächliche Ertrag, Pink die Prognose (jeweils am Vorabend um 22h ermittelt). So richtig zuverlässig sind die Prognosen nicht... Ich bin jetzt parallel mit SolarForecast (ist ein FHEM Modul) am schauen und kann dann in 1-2 Monaten einen Vergleich anstellen.

Und? Kannst Du nun einen vergleich zeigen..?
Wäre klasse.

Aurel_B

Oups, sorry, war einige Wochen nicht mehr hier. Wie gewünscht im Anhang die aktuellen Graphen (morgens: Prognose um 6h am selben Tag, abends: um 22h am Vortag).... generell ist die Vorhersage recht ordentlich, wie gehabt ist SolarForecast i.d.R. etwas pessimistischer als SolCast. Die Werte am Vorabend unterscheiden sich auch nicht wahnsinnig von den Prognosen morgens, d.h. ich kann Grossverbraucher abends bei günstigem Nachtstrom einschalten wenn die Prognose für den nächsten Tag mau ist.
Ich verwende im Moment nur die SolarForecast Werte um z.B. beim Boiler mit dem Heizstab (zusätzlich zur Wärmepumpe) das Warmwasser bis auf 72° zu erwärmen wenn die Prognose für den nächsten Tag mau ist -> so habe ich einen kleinen thermischen Speicher.
Bald kommt noch die Wärmepumpe, da werde ich wohl auch so Spielereien umsetzen um möglichst allen Strom lokal zu verwenden (auch wiederum abhängig von der Prognose)


J0EK3R

#36
Moin in die Runde :)

Aus den vorausgegangenen Posts dieses Threads und anderen Quellen hab ich mir ein funktionierendes SolCast Vorhersagesystem zusammengebastelt, das ich mit Euch teilen möchte.

Es gibt ein DbLog mit dem Namen LogDB und ein DbRep mit dem Namen LogDBRep_PV_Forecast_SQL für das Datenbank-Handling und eine Funktion forecast_in_DB_speichern in 99_myUtils.pm.
Außerdem für jede Dachfläche ein JsonMod - hier im Beispiel mit dem Namen SolCast_Sueddach.
Und ein DOIF mit dem Namen SolCast_Schedule, das für das Pollen und den Aufruf der Funktion forecast_in_DB_speichern zuständig ist.

Zunächst hier das DOIF, das zwischen 5 Uhr und 21 Uhr zu jeder vollen Stunde die Vorhersage von SolCast abholt und eine Minute später den Aufruf der Funktion forecast_in_DB_speichern in 99_myUtils.pm macht:

defmod SolCast_Schedule DOIF ################################################################################################################\
## 1 Daten von Solcast holen\
([05:00-21:00] and [:00])\
(set SolCast_Sueddach reread)\
\
################################################################################################################\
## 2 Daten in Datenbank speichern\
## \
DOELSEIF\
([05:00-21:00] and [:01])\
   ({forecast_in_DB_speichern('SolCast_Sueddach','LogDB','LogDBRep_PV_Forecast_SQL')})\
attr SolCast_Schedule DbLogExclude .*
attr SolCast_Schedule cmdState Get Data|Write Data
attr SolCast_Schedule do always
attr SolCast_Schedule verbose 0
attr SolCast_Schedule webCmd cmd_1:cmd_2
attr SolCast_Schedule webCmdLabel Get_Data :Write_Data :


Hier meine Definition des JsonMod SolCast_Sueddach.

Natürlich muss der Rooftop-Identifier und der API-Key angepasst werden!

Ich habe den Code der userreadings überarbeitet: SolCast liefert die Halb-Stunden-Werte nicht für den ganzen Tag, sondern nur ab eineinhalb Stunden vor dem Abfragezeitpunkt. Das bedeutet, dass die Summe der Stundenerträge im Laufe eines Tages immer kleiner wird, da die vorangegangenen Stundenerträge fehlen.
Deshalb speichere ich die gelieferten Stundenerträge intern in einem Hash mit den Uhrzeiten als Schlüssel (-> $hash->{Helper}{today}{$ttime}) und summiere sie dann zum Tagesertrag.

defmod SolCast_Sueddach JsonMod https://api.solcast.com.au/rooftop_sites/XXXX-YYYY-ZZZZ-AAAA/forecasts?format=json&api_key=ABC&hours=72
attr SolCast_Sueddach DbLogExclude .*
attr SolCast_Sueddach DbLogInclude forecast_today
attr SolCast_Sueddach event-on-change-reading .*
attr SolCast_Sueddach readingList multi(jsonPath('$.forecasts[*]'), concat('pv_estimate_', property('period_end')), property('pv_estimate'));;\
single(jsonPath('$.forecasts[0].period'),'period','');;
attr SolCast_Sueddach stateFormat forecast_today
attr SolCast_Sueddach userReadings forecast_today {\
use List::Util 'sum';;\
my ($date, $time) = split(" ", FmtDateTime(time()));;\
my $hash = $defs{$NAME};;\
my $readings = $hash->{READINGS};;\
foreach my $reading ( keys %{$readings} ) {\
if ($reading =~ /$date/) {\
my $val = ReadingsVal($NAME,$reading,0);;\
my $ttime = substr($reading, 23, 4);;\
$hash->{Helper}{today}{$ttime} = $val;;\
}\
}\
my $period = ReadingsVal($NAME, "period", 1);;\
$period =~ s/.*(\d\d).*/$1/;;\
my $values = $hash->{Helper}{today};;\
my $total = sum values %{$values};;\
$total /= (60/$period);;\
return $total;;\
},\
forecast_tomorrow \
{\
use List::Util 'sum';;\
use Time::Piece ();;\
use Time::Seconds;;\
my ($date, $time) = split(" ", FmtDateTime(time()));;\
$date = Time::Piece->strptime($date, '%Y-%m-%d');;\
$date += ONE_DAY;;\
$date = $date->strftime('%Y-%m-%d');;\
my $hash = $defs{$NAME};;\
my $readings = $hash->{READINGS};;\
foreach my $reading (keys %{$readings}) {\
if ($reading =~ /$date/) {\
my $val = ReadingsVal($NAME, $reading, 0);;\
my $ttime = substr($reading, 23, 4);;\
$hash->{Helper}{tomorrow}{$ttime} = $val;;\
}\
}\
my $period = ReadingsVal($NAME, "period", 1);;\
$period =~ s/.*(\d\d).*/$1/;;\
my $values = $hash->{Helper}{tomorrow};;\
my $total = sum values %{$values};;\
$total /= (60/$period);;\
return $total;;\
}


In 99_myUtils.pm habe ich folgenden Code definiert:

use Time::Piece;

# Braucht 3 Argumente: $name = Name des "Solcast" Devices, $dblog und $dbrep Namen der dblog/dbrep Devices.
# Bei jedem Aufruf wird der Forecast für morgen sowie alle aktuellen Prognosewerte gespeichert.
# Die Prognosewerte werden dabei überschrieben, alte Werte bleiben bestehen.
sub forecast_in_DB_speichern($$$) {
my ( $name, $dblog, $dbrep ) = @_;

# Dauer des Vorhersageintervalls in Minuten
my $period_m = ReadingsVal($name, "period", "PT30M");
$period_m =~ s/.*(\d\d).*/$1/;

my $val = ReadingsVal($name, "forecast_tomorrow", 0);
my $time = strftime('%Y-%m-%d %H:%M:%S', localtime(time + 60 * 60 * 24));

CommandSet(undef, $dblog." addCacheLine $time|$name|JSONMOD|forecast|forecast|$val");

# Readings nach Namen sortieren
my %hash = %{$defs{$name}{READINGS}};
my @pv_estimates = sort grep /pv_estimate/, keys %hash;

# Max/Min Forecast Zeitpunkt ermitteln
$pv_estimates[-1] =~ m/pv_estimate_(.*)/;
my $max = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1) -$period_m*60));

$pv_estimates[0] =~ m/pv_estimate_(.*)/;
my $min = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1) -$period_m*60));

# Alle alten Werte löschen, die aktualisiert werden sollen
CommandGet(undef, $dbrep." sqlCmdBlocking DELETE FROM history WHERE DEVICE='".$name."' AND TIMESTAMP>='".$min."' AND TIMESTAMP<='".$max."'");

foreach my $reading (@pv_estimates) {
$reading =~ m/pv_estimate_(.*)/;
$time = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1) -$period_m*60));

$val = ReadingsVal($name, $reading, 0) * 1000;

CommandSet(undef, $dblog." addCacheLine $time|$name|JSONMOD|pv_estimate|pv_estimate|$val");
}
};


Beste Grüße
J0EK3R

---
Änderungen:
2022.09.12: Vorhersageintervall "$period_m" wird berücksichtigt

DS_Starter

Guten Abend,

aktuell bin ich dabei die SolCast API in das SolarForecast Modul zu integrieren.

Ich habe mir die Beiträge in diesem Thread angesehen und dabei ist mir aufgefallen dass ihr wahrscheinlich übersehen habt die von der API gelieferte UTC-Zeit (YYYY-MM-DDThh:mm:ss.0000000Z) in die lokale Zeit zu wandeln.
Aktuell sind das 2 Stunden Differenz.
Möglicherweise habe ich die Umwandlung in euren Codes auch überlesen, aber wenn nicht, kann es einfach mit dem Modul ConvertTimeZone erledigt werden.

Grüße,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

J0EK3R

Moin Heiko :)

Zitataktuell bin ich dabei die SolCast API in das SolarForecast Modul zu integrieren.

...das wäre toll! :)

So wie ich das ausprobiert hab, wird die UTC-Zeit von str2time schon richtig umgewandelt:

Eingabe direkt in die Commandozeile von FHEM:

{strftime('%Y-%m-%d %H:%M:%S', localtime(str2time('2022-09-12T053000.0000000Z')))}
2022-09-12 07:30:00

Ohne "Z":

{strftime('%Y-%m-%d %H:%M:%S', localtime(str2time('2022-09-12T053000.0000000')))}
2022-09-12 05:30:00


Die Rohdaten von SolCast im JSON-Format sehen ja so aus:

{"pv_estimate":0.0463,"pv_estimate10":0.043984999999999996,"pv_estimate90":0.048615000000000005,"period_end":"2022-09-12T05:30:00.0000000Z","period":"PT30M"},
{"pv_estimate":0.1055,"pv_estimate10":0.100225,"pv_estimate90":0.110775,"period_end":"2022-09-12T06:00:00.0000000Z","period":"PT30M"},
{"pv_estimate":0.385,"pv_estimate10":0.36574999999999996,"pv_estimate90":0.40425000000000005,"period_end":"2022-09-12T06:30:00.0000000Z","period":"PT30M"},


Die Zeitstempel, die JsonMod verwendet, sind ja immer die des Endes der Vorhersage-Periode: period_end.

Da ich für die Darstellung in meinen Diagrammen den Startzeitpunkt habe, ziehe ich eine Stunde ab:

$time = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1) - 60 * 60));

...aber jetzt, wo ich drüber nachdenke, müsste es nicht die Länge der Vorhersage-Periode sein, also 30 Minuten!? Hmmm...


Beste Grüße
J0EK3R

DS_Starter

Moin,

ah ja, str2time  .... ich nehme alles zurück und behaupte das Gegenteil.  :)

Zitat
...aber jetzt, wo ich drüber nachdenke, müsste es nicht die Länge der Vorhersage-Periode sein, also 30 Minuten!? Hmmm..

Im Modul ist alles normiert auf Stundenbasis und die Angaben beziehen sich ebenfalls auf den Anfang der Stunde.
Deswegen gehe ich so vor zunächst die gelieferten Zeiten auf lokale Zeit umzuwandeln und dann abhängig von der Zeit entweder 30 Min oder 60 Min abzuziehen.

Zum Beipiel wird geliefert  period_end (umgewandelt)  2022-09-12 08:30:00  und  2022-09-12 09:00:00.
Vom ersten Date normiere ich auf 08 Uhr indem ich 30 auf 00 setze und von 09 ziehe ich 1 ab -> 08.

Die gelieferten Werte pv_estimate beider Zeiten werden dann mit ihrer Periode gewichtet zusammenaddiert (macht ihr auch so), im Prinzip:

total = pv_estimate1/(60/periode) + pv_estimate2/(60/periode)

Damit haben wir den Vorhersagewert dann umgewandelt auf den Anfang der jeweiligen Stunde lokaler Zeit.

Im Modul bin ich mit dem Einbau schon gut vorangekommen, aber es dauert noch einige Zeit. Doch das kommt.

Frage in die Runde.
Ich beziehe mich auf die freie Nutzung der API, d.h. man hat 50 Abfragen pro Tag frei. Für ein roofTop reicht das gut hin wenn z.B. 1 mal pro Stunde zwischen Sonnenauf- und untergang abgefragt wird.
Hat man aber mehr als ein roofTop, was jeweils mit einer eigenen ID separat abgefragt wird, dann wird es ggf. schon etwas enger.
Ich gehe davon aus, dass jede Abfrage in das Kontingent zählt und nicht pro roofTop ID oder sehe ich das falsch ?

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

J0EK3R

Moin Heiko :)

ZitatFrage in die Runde.
Ich beziehe mich auf die freie Nutzung der API, d.h. man hat 50 Abfragen pro Tag frei. Für ein roofTop reicht das gut hin wenn z.B. 1 mal pro Stunde zwischen Sonnenauf- und untergang abgefragt wird.
Hat man aber mehr als ein roofTop, was jeweils mit einer eigenen ID separat abgefragt wird, dann wird es ggf. schon etwas enger.
Ich gehe davon aus, dass jede Abfrage in das Kontingent zählt und nicht pro roofTop ID oder sehe ich das falsch ?

Ich denke, dass jede einzelne Abfrage zählt - also pro Account, nicht pro Rooftop.

Bei der kostenfreien Nutzung von SolCast kann man nur zwei Rooftops anlegen - braucht man mehr, muss man weitere Accounts anlegen.

Unter "Manage Account" gibt es übrigens einen Zähler für die "API Usage":
https://toolkit.solcast.com.au/account

Beste Grüße
J0EK3R

DS_Starter

Zitat
Bei der kostenfreien Nutzung von SolCast kann man nur zwei Rooftops anlegen - braucht man mehr, muss man weitere Accounts anlegen.

Guter Hinweis, danke. Das ist für die Modulimplementierung wichtig. Stichwort Account und Rooftop-ID Management.
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

paul79

#42
Hallo,
ich habe alles wie oben beschrieben Post von J0EK3R eingerichtet leider bekomme ich diesen Fehler.

2022.09.25 20:20:24 3: DbLog logdb -> added by addCacheLine - TS: 2022-10-02 18:00:00, Device: SolCast_Sueddach, Type: JSONMOD, Event: pv_estimate, Reading: pv_estimate, Value: 18.6, Unit:
2022.09.25 20:20:24 3: DbLog logdb -> added by addCacheLine - TS: 2022-10-02 18:30:00, Device: SolCast_Sueddach, Type: JSONMOD, Event: pv_estimate, Reading: pv_estimate, Value: 1.3, Unit:
2022.09.25 20:20:24 3: DbLog logdb -> added by addCacheLine - TS: 2022-10-02 19:00:00, Device: SolCast_Sueddach, Type: JSONMOD, Event: pv_estimate, Reading: pv_estimate, Value: 0, Unit:
2022.09.25 20:20:45 1: PERL WARNING: DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE 1=1 AND DEVICE = 'SolCast_Sueddach' AND TIMESTAMP >= STR_TO_DATE('2022-09-' at line 6 at ./FHEM/93_DbLog.pm line 3745.


Was kann da der Fehler sein? Es werden keine Daten in die DB geschrieben. (bin kein SQL-Experte)

Hat sich erledigt, lag am DbRep.

Gruß Paul
FHEM5.7 auf Pi3
Busware CUL433 (IT), JeeLink Lacrosse, HM-MOD-RPI-PCB, HM, TabletUI

J0EK3R

#43
Moinmoin paul79 :)

...ich kucke und grüble und kucke und grüble und kann nichts Auffälliges finden und kucke und seh erst jetzt:

Zitat
Hat sich erledigt, lag am DbRep.

Na dann: viel Spaß! :)

limes1337

Der Beitrag hier hat mir sehr geholfen Solcast einzubinden und so möchte ich meine optimierte Version nun auch zurück mit Euch teilen. Ich habe im Wesentlichen den Code von J0EK3R aufgegriffen und an folgenden Stellen verfeinert:

  • Die Url hat noch den Parameter "hours" bekommen, so dass ich mit hours=72 nur die nächsten 3 Tage abhole. Bei allen Tagen darüber hinaus dürften die Werte sowieso ungenau werden und so spart man einige Readings.
  • Ich habe bei den UserReadings etwas aufgeräumt, so dass das Device nicht "Solcast" heißen muss, sondern man einen beliebigen Namen wählen kann.
  • Ich habe das UserReading "forecast_overmorrow" ergänzt - also Vorhersage für Übermorgen.
  • Ich habe Die Kalkulation für den forecast_today so angepasst, dass nur noch Perioden berücksichtigt werden, die in der Zukunft liegen. (Solcast liefert immer einige Halbstunden Einträge die etwas in der Vergangenheit liegen). Mit der Veränderung kann ich nun genau sehen, wie viel heute voraussichtlich noch produziert ist und wenn ich es mit meinem tatsächlichen Tagesertrag meiner PV Anlage addiere, dann erhalte ich den kompletten voraussichtlichen Tagesertrag.

Falls ihr im Code noch Optimierungspotential findet, dann gerne her damit - Perl ist nicht meine Muttersprache, aber es funktioniert.  :)

Insgesamt bin ich momentan noch am schauen, wie die Forecasts zu den Actuals passen. Das werde ich weiter beobachten. Ich weiß, dass es auch noch das Modul "SolarForecast" gibt, aber ich möchte es recht einfach halten und bin der Meinung, dass bei solchen Vorhersagen viel Aufwand nicht unbedingt zu viel Mehrwert führt. Sollten meine Vorhersagen nicht zu den Tageswerten meiner PV Anlage passen, dann werde ich erst einmal mit dem Efficiency Factor, den man für jede Site bei Solcast setzen kann spielen. Das dürfte für meine Zwecke reichen, da ich sowieso nur mit den Tageswerten arbeite und keine Aktionen aus den Stundenvorhersagen ableite. So steuere ich bspw. die "Min+PV" oder "Nur PV" Modi meiner OpenWB Wallbox, je nachdem was die Vorhersage für die nächsten 72 Stunden ist.

Grüße,
limes

defmod tech.online.solcast_so2 JsonMod https://api.solcast.com.au/rooftop_sites/<SITE ID>/forecasts?format=json&api_key=<API KEY>&hours=72

attr tech.online.solcast_so2 readingList multi(jsonPath('$.forecasts[*]'), concat('pv_estimate_', property('period_end')), property('pv_estimate'));;\
single(jsonPath('$.forecasts[0].period'),'period','');;
attr tech.online.solcast_so2 room Technik
attr tech.online.solcast_so2 userReadings forecast_today {\
my $total = 0;;\
my $period = ReadingsVal($NAME, "period", 0);;\
$period =~ s/.*(\d\d).*/$1/;;\
my ($date, $time) = split(" ", FmtDateTime(time()));;\
my ($hour, $min, $sec) = split(":", $time);;\
$time = $hour . $min . "00";;\
my $hash = $defs{$NAME};;\
my $readings = $hash->{READINGS};;\
foreach my $reading ( keys %{$readings} ) {\
if ($reading =~ /$date/) {\
\
my ($dummy, $period_end) = split("T", $reading);;\
$period_end = substr($period_end, 0, 6);;\
\
if ($period_end > $time)\
{\
my $val = ReadingsVal($NAME,$reading,0);;\
$total += $val/(60/$period);;\
}\
}\
}\
return $total;;\
},\
forecast_tomorrow {\
use Time::Piece ();;\
use Time::Seconds;;\
\
my $total = 0;;\
my $period = ReadingsVal($NAME, "period", 0);;\
$period =~ s/.*(\d\d).*/$1/;;\
my ($date, $time) = split(" ", FmtDateTime(time()));;\
$date = Time::Piece->strptime($date, '%Y-%m-%d');;\
$date += ONE_DAY;;\
$date = $date->strftime('%Y-%m-%d');;\
my $hash = $defs{$NAME};;\
my $readings = $hash->{READINGS};;\
foreach my $reading (keys %{$readings}) {\
if ($reading =~ /$date/) {\
my $val = ReadingsVal($NAME, $reading, 0);;\
$total += $val/(60/$period);;\
}\
}\
return $total;;\
},\
forecast_overmorrow {\
use Time::Piece ();;\
use Time::Seconds;;\
\
my $total = 0;;\
my $period = ReadingsVal($NAME, "period", 0);;\
$period =~ s/.*(\d\d).*/$1/;;\
my ($date, $time) = split(" ", FmtDateTime(time()));;\
$date = Time::Piece->strptime($date, '%Y-%m-%d');;\
$date += ONE_DAY;;\
$date += ONE_DAY;;\
$date = $date->strftime('%Y-%m-%d');;\
my $hash = $defs{$NAME};;\
my $readings = $hash->{READINGS};;\
foreach my $reading (keys %{$readings}) {\
if ($reading =~ /$date/) {\
my $val = ReadingsVal($NAME, $reading, 0);;\
$total += $val/(60/$period);;\
}\
}\
return $total;;\
}