Anwendungsbeispiel JsonMod - SolCast Solar-Vorhersage abrufen

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

Vorheriges Thema - Nächstes Thema

freetz

Prima, das freut mich - vielleicht mache ich für die Batteriesteuerung mal einen eigenen Thread auf, wenn es dafür Interesse gibt, das würde nämlich hier wirklich nicht mehr zum Topic passen, da das dann über ModbusAttr läuft.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Aurel_B

Danke dir freetz für deine Arbeit! Ich habe diese etwas weiterentwickelt und zusätzlich noch ein UserReading für morgen erstellt sowie eine Funktion, welche bei jedem Aufruf die aktuellen Prognosewerte in einen dblog schreibt. Historische Werte werden dabei belassen, es werden nur die abgerufenen Werte überschrieben. Hintergrund: so kann ich mir einen Graphen plotten der mir eine Vorhersage liefert, aber auch einen Rückblick damit ich schauen kann, wie gut die Prognose stimmt. Das UserReading für morgen brauche ich um z.B. am Abend vorher gewisse Grossverbraucher mit dem günstigen Nachttarif laufen lassen zu können falls der prognostizierte Solarstrom nicht reichen sollte.

Hier das UserReading:


forecast_today {
my $total = 0;
my $period = ReadingsVal("SolCast", "period", 0);
$period =~ s/.*(\d\d).*/$1/;
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);
$total += $val/(60/$period);
}
}
return $total;
},
forecast_tomorrow {
use Time::Piece ();
use Time::Seconds;

my $total = 0;
my $period = ReadingsVal("SolCast", "period", 0);
$period =~ s/.*(\d\d).*/$1/;
my ($date, $time) = split(" ", FmtDateTime(time()));
my $date = Time::Piece->strptime($date, '%Y-%m-%d');
$date += ONE_DAY;
$date = $date->strftime('%Y-%m-%d');
my $hash = $defs{"SolCast"};
my $readings = $hash->{READINGS};
foreach my $reading (keys %{$readings}) {
if ($reading =~ /$date/) {
my $val = ReadingsVal("SolCast", $reading, 0);
$total += $val/(60/$period);
}
}
return $total;
}


Und hier die Funktion um die Vorhersage im dblog zu speichern (gehört in MyUtils):


# 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 ) = @_;
my $val = ReadingsVal($name, "forecast_tomorrow", 0);
my $time = strftime('%Y-%m-%d %H:%M:%S', localtime(time + 86400));
fhem("set ".$dblog." addCacheLine $time|$name|JSONMOD|forecast|forecast|$val");
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 = str2time($1);
$pv_estimates[0] =~ m/pv_estimate_(.*)/;
my $min = str2time($1);
# Alle alten Werte löschen die aktualisiert werden sollen
fhem("set ".$dbrep." sqlCmd DELETE FROM `history` WHERE DEVICE = '".$name."' AND `TIMESTAMP` >= FROM_UNIXTIME(".$min.") AND `TIMESTAMP` <= FROM_UNIXTIME(".$max.")");

foreach my $reading (@pv_estimates) {
$reading =~ m/pv_estimate_(.*)/;
$time = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1)));
$val = ReadingsVal($name, $reading, 0) * 1000;
fhem("set ".$dblog." addCacheLine $time|$name|JSONMOD|pv_estimate|pv_estimate|$val");
}
}


Die eigentliche Speicherung erfolgt dann in einem at:

defmod at_SolCast_Prognose_speichern at *22:00 {forecast_in_DB_speichern('SolCast','dblog','DB_Bereinigung_Kostal')}

Prognosen siehe Anhang. Es besteht noch Optimierungsbedarf, im Moment habe ich alle meine Module (O, S & W) zusammengefasst zu einer Anlage (Südausrichtung). Wenn ich Zeit und Lust habe, splitte ich das auf 3 Anlagen mit der korrekten Ausrichtung und Neigung und aktualisiere dann meinen Code. Was mir auch schon aufgefallen ist: Nebel/"grauer Himmel" wird nicht richtig prognostiziert, so ist z.B. bei uns im Moment Hochnebel und der PV Ertrag entsprechend gering, das spiegelt sich aber nicht in der SolCast Prognose wieder (siehe auch 10. Oktober, das war auch so ein Tag wo bis am Mittag Hochnebel herrschte). Die DWD Werte kann ich leider nicht benutzen da keine Station bei mir in der Nähe ist.


DS_Starter

Hallo zusammen,

ich bin zufällig auf diesen Thread gestoßen.
Nur als Info ... ich hatte ursprünglich noch vor SolCast als weitere Datenquelle zu DWD in das SolarForecast Modul zu integrieren.
Mir war nur nicht klar ob es diesen Bedarf überhaupt gibt.

Meines Wissens können kostenfrei nur ca. 20 Abfragen bei SolCast pro Tag getätigt werden oder bin ich im Irrtum ?

Da das Modul Solarforecast ohne Datenbank arbeitet, benötigt es keine DbLog Definition. Dadurch ist es für die breite Masse der Nicht-DB User zugänglich was ein wesentliches Kriterium bei der Erstellung des Moduls war.
Vielleicht schaffe ich die Integration es über das Winterhalbjahr.
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

freetz

Es gibt da widersprüchliche Angaben, ich habe 50 Abfragen pro Tag, das reicht dicke, weil öfter als alle 30 Minuten eh' nicht aktualisiert wird, d.h. mit 48 käme man aus. Aber selbst die brauche ich nicht, weil die Sonne ja nicht 24 Stunden scheint. Selbst mit 20 Abfragen käme man im Sommer gut durch, wenn man einmal pro Stunde abfragt. Ich finde die Werte deutlich genauer als DWD, das ich vorher im Einsatz hatte.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

DS_Starter

Zitat... weil die Sonne ja nicht 24 Stunden scheint
Ja, stimmt natürlich. Es reicht ja von Sonnenauf- bis untergang. Die Angaben ziehe ich z.Z. aus dem DWD Device.
Benötigt man zur Abschätzung des Ertrages bei Verwendung von SolCast auch noch die Angaben zu Bewölkung bzw. Regen aus DWD oder sind diese Faktoren bei SolarCast schon mit berücksichtigt ?
Ich vermute SolCast liefert auch nur die Globalstrahlung ?

Meine Idee ist die Strahlungswerte von SolCast zu holen und natürlich noch die Bewölkung / Niederschlag als reduzierende Faktoren einzubeziehen wie es jetzt auch mit dem DWD Device funktioniert.
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

freetz

SolCast hat alles schon mit drin und die Ergebnisse sind wie gesagt deutlich präziser, weil man nicht auf die nächstgelegene DWD-Station angewiesen ist. Am besten, Du schaust Dir die API direkt auf deren Seiten mal an, dann wird es am deutlichsten.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Aurel_B

#21
@freetz: mich würde wunder nehmen, wie du die Präzision der SolCast Vorhersagen ermittelst? Schaust du am Ende des Tages wie gross die Abweichung ist? Oder im Tagesverlauf? Wie oft frägst du die Werte ab?

Als Vergleich: ich lasse einmal am Abend um 21:45 die Prognose abrufen um den morgigen Tag planen zu können. Manchmal sind die Prognosen extrem genau, manchmal liegen sie ordentlich daneben. Das scheint - wie weiter oben von mir bereits geschrieben - immer dann der Fall zu sein, wenn Bewölkung auftritt. Im Anhang habe ich einen Screenshot welcher den tatsächlichen Ertrag (grün) mit dem prognostizierten (gelb) vergleicht (für die letzten 8 Tage, mehr habe ich bisher nicht).

freetz

Wenn Du SolCast selber nutzt, weißt Du ja, dass es da direkt im Backend die Möglichkeit die Vorhersage mit den Estimated Actuals zu vergleichen. Darüber hinaus übermittele ich auch meine vom WR ermittelten Erträge an SolCast, so dass da noch mal eine Optimierung stattfindet. Da sehe ich das dann noch mal genauer.

Und klar, SolCast kann nicht 24h hellsehen, deswegen frage ich die Werte auch alle halbe Stunde ab. Die können sich dann schon mal ändern, so wie beim DWD auch, nur ist SolCast meiner Erfahrung nach da deutlich genauer. Ich merke das ganz konkret daran, dass ich es mit SolCast schaffe, meine Batterie aufgrund der Prognose zum spätmöglichsten Zeitpunkt zu laden und sie dann in den allermeisten Fällen trotzdem noch voll wird. Beim DWD hat das so gut wie nie geklappt.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Aurel_B

#23
Ah danke dir, wusste nicht, dass man die tatsächlichen Erträge senden kann. Habe irgendwo gelesen, dass es das Tuning nicht mehr gibt und mich daher gar nie mehr damit beschäftigt. Auf https://articles.solcast.com.au/en/articles/2442084-send-rooftop-site-measurements-via-our-api steht beschrieben, wie's geht.

Meine Frage an dich: hättest du zufälligerweise eine Skript oder FHEM Code wie du die Daten des WRs an SolCast sendest? Hätte jetzt spontan gesagt, ich sende jede Stunde den Stundenertrag etwa in so:


{
my $Stand_jetzt = ReadingsVal("WR","Total_yield",undef);
my $Letzter_Stand = ReadingsVal("WR","Total_yield_Stand_vorher_Wh",undef);
my $Zeitdauer = ReadingsAge("WR","Total_yield_Stand_vorher_Wh",undef);
fhem("setreading WR Total_yield_Stand_vorher_Wh ".$Stand_jetzt);
my $Ertrag_seit_letztem_Stand = $Stand_jetzt - $Letzter_Stand;
# $Zeitdauer in ISO8601 umrechnen und alles an SolCast senden
}


Man könnte auch "oldreadings" verwenden, so ist es aber transparenter für mich...

PS: Ah und einfach damit es irgenwo festgehalten ist falls mal jemand danach suchen sollte: ich habe auch noch mit "Forecast.Solar" rumgespielt (https://forecast.solar/), das taugt nun gar nix, dort wird Tag für Tag ein Ertrag von ca. 9.5kWh +-400W prognostiziert mit keinem erkennbaren Zusammenhang zum tatsächlichen Ertrag.

Aurel_B

Sorry, es ist früh am Morgen ;D Steht ja ganz oben auf der Seite geschrieben, dass es das Tuning nicht mehr gibt und es daher keinen Sinn macht, die Daten zu senden. Jetzt stehe ich gerade völlig auf dem Schlauch. Was genau sendest du denn an SolCast und welchen Effekt hat das?

freetz

#25
Ja, da steht, dass es das Tuning (schon länger) nicht mehr gibt, aber angeblich für Bestandskunden weiter angeboten wird. Ich bin aber erst seit Juli dabei, also nach der Ankündigung von oben und kann sagen, dass bei mir zuerst da stand, dass noch zu wenige Daten da sind, aber nach einiger Zeit gab's dann den grünen Haken (s. Anhang).
Ist aber letztlich für die Fragestellung egal, denn das Tuning soll ja eher so Faktoren wie Verschattung etc. berücksichtigen. Das fällt i.d.R. aber nicht so extrem ins Gewicht, zumindest nicht so deutlich wie die Unterschiede zwischen DWD und SolCast Vorhersage auch ohne Tuning schon waren.

Mit Deinem Schnipsel kann ich jetzt auf die Schnelle nichts anfangen, hier ist meine entsprechende FHEM Config:

defmod SolCast_Reporting HTTPMOD https://api.solcast.com.au/rooftop_sites/... 0
attr SolCast_Reporting bodyDecode utf-8
attr SolCast_Reporting extractAllJSON 1
attr SolCast_Reporting replacement01Mode expression
attr SolCast_Reporting replacement01Regex {{([^}]+)}}
attr SolCast_Reporting replacement01Value ReadingsVal($name, $1, "")
attr SolCast_Reporting room Solar
attr SolCast_Reporting set01Data {"measurement": {"period_end": "{{period_end}}","period": "{{reporting_interval_ISO8601}}","total_power": $val}}
attr SolCast_Reporting set01Name pvProduction
attr SolCast_Reporting setHeader1 Content-Type: application/json
attr SolCast_Reporting setHeader2 Accept: */*
attr SolCast_Reporting stateFormat [SolCast_Reporting:value]
attr SolCast_Reporting userReadings reporting_interval {ReadingsVal($NAME, "reporting_interval", 300)},\
reporting_interval_ISO8601 {return "PT" . ReadingsVal($NAME, "reporting_interval", 300) / 60 . "M"},\
period_end {return strftime('%Y-%m-%dT%H:%M:%SZ', gmtime(time))}\


defmod di_reset_production DOIF ([+[SolCast_Reporting:reporting_interval]]) \
(setreading SolCast_Reporting period_end {strftime('%Y-%m-%dT%H:%M:%SZ', gmtime(time))},\
set SolCast_Reporting pvProduction {(ReadingsVal("BydBattery","avg_production","N/A")/1000)},\
setreading BydBattery avg_production_counter 0,\
setreading BydBattery avg_production 0,\
setreading BydBattery avg_production_sum 0)


Und hier noch der Ausschnitt aus dem userReading des Batterie-Devices "BydBattery":

avg_production_counter:Meter_Power.* {
  ReadingsVal($NAME,"avg_production_counter",0)+1;
},

avg_production_sum:Meter_Power.* {
  ReadingsVal($NAME,"avg_production_sum",0) + ReadingsVal($NAME, "pvProduction",0);
},

avg_production:Meter_Power.* {
  my $aps = ReadingsVal($NAME,"avg_production_sum",0);
  my $apc = ReadingsVal($NAME, "avg_production_counter", 0);
  if ($apc > 0) {
    return sprintf("%.1f", $aps/$apc);
  } else {
    return 0;
  }
}


Ich hoffe, das hilft weiter...
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Aurel_B

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.

sig10680

Zitat von: ansgru am 17 Oktober 2021, 10:55:47
Danke dir freetz für deine Arbeit! Ich habe diese etwas weiterentwickelt und zusätzlich noch ein UserReading für morgen erstellt sowie eine Funktion, welche bei jedem Aufruf die aktuellen Prognosewerte in einen dblog schreibt. Historische Werte werden dabei belassen, es werden nur die abgerufenen Werte überschrieben. Hintergrund: so kann ich mir einen Graphen plotten der mir eine Vorhersage liefert, aber auch einen Rückblick damit ich schauen kann, wie gut die Prognose stimmt. Das UserReading für morgen brauche ich um z.B. am Abend vorher gewisse Grossverbraucher mit dem günstigen Nachttarif laufen lassen zu können falls der prognostizierte Solarstrom nicht reichen sollte.

Hier das UserReading:


forecast_today {
my $total = 0;
my $period = ReadingsVal("SolCast", "period", 0);
$period =~ s/.*(\d\d).*/$1/;
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);
$total += $val/(60/$period);
}
}
return $total;
},
forecast_tomorrow {
use Time::Piece ();
use Time::Seconds;

my $total = 0;
my $period = ReadingsVal("SolCast", "period", 0);
$period =~ s/.*(\d\d).*/$1/;
my ($date, $time) = split(" ", FmtDateTime(time()));
my $date = Time::Piece->strptime($date, '%Y-%m-%d');
$date += ONE_DAY;
$date = $date->strftime('%Y-%m-%d');
my $hash = $defs{"SolCast"};
my $readings = $hash->{READINGS};
foreach my $reading (keys %{$readings}) {
if ($reading =~ /$date/) {
my $val = ReadingsVal("SolCast", $reading, 0);
$total += $val/(60/$period);
}
}
return $total;
}


Und hier die Funktion um die Vorhersage im dblog zu speichern (gehört in MyUtils):


# 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 ) = @_;
my $val = ReadingsVal($name, "forecast_tomorrow", 0);
my $time = strftime('%Y-%m-%d %H:%M:%S', localtime(time + 86400));
fhem("set ".$dblog." addCacheLine $time|$name|JSONMOD|forecast|forecast|$val");
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 = str2time($1);
$pv_estimates[0] =~ m/pv_estimate_(.*)/;
my $min = str2time($1);
# Alle alten Werte löschen die aktualisiert werden sollen
fhem("set ".$dbrep." sqlCmd DELETE FROM `history` WHERE DEVICE = '".$name."' AND `TIMESTAMP` >= FROM_UNIXTIME(".$min.") AND `TIMESTAMP` <= FROM_UNIXTIME(".$max.")");

foreach my $reading (@pv_estimates) {
$reading =~ m/pv_estimate_(.*)/;
$time = strftime('%Y-%m-%d %H:%M:%S', localtime(str2time($1)));
$val = ReadingsVal($name, $reading, 0) * 1000;
fhem("set ".$dblog." addCacheLine $time|$name|JSONMOD|pv_estimate|pv_estimate|$val");
}
}


Die eigentliche Speicherung erfolgt dann in einem at:

defmod at_SolCast_Prognose_speichern at *22:00 {forecast_in_DB_speichern('SolCast','dblog','DB_Bereinigung_Kostal')}

Prognosen siehe Anhang. Es besteht noch Optimierungsbedarf, im Moment habe ich alle meine Module (O, S & W) zusammengefasst zu einer Anlage (Südausrichtung). Wenn ich Zeit und Lust habe, splitte ich das auf 3 Anlagen mit der korrekten Ausrichtung und Neigung und aktualisiere dann meinen Code. Was mir auch schon aufgefallen ist: Nebel/"grauer Himmel" wird nicht richtig prognostiziert, so ist z.B. bei uns im Moment Hochnebel und der PV Ertrag entsprechend gering, das spiegelt sich aber nicht in der SolCast Prognose wieder (siehe auch 10. Oktober, das war auch so ein Tag wo bis am Mittag Hochnebel herrschte). Die DWD Werte kann ich leider nicht benutzen da keine Station bei mir in der Nähe ist.

Hallo,
ich habe bei mir auch Solcast mit JsonMod eingebunden und es läuft!
Würde auch ein Plot mir Vorhersage ohne DBlog funktionieren! Wenn ja wie müsste man dies anstellen!

mfg Sig10680

Aurel_B

Zitat von: sig10680 am 26 Januar 2022, 12:14:23
Hallo,
ich habe bei mir auch Solcast mit JsonMod eingebunden und es läuft!
Würde auch ein Plot mir Vorhersage ohne DBlog funktionieren! Wenn ja wie müsste man dies anstellen!

mfg Sig10680

Mit meinem Ergänzungscode? Nope, da sind SQL Befehle und so drin die nur mit DBlog gehen. Grundsätzlich sollte es aber auch mit einem FileLog gehen falls sich jemand die Mühe macht, den Code entsprechend umzuschreiben.

sig10680

Zitat von: ansgru am 27 Januar 2022, 20:27:27
Mit meinem Ergänzungscode? Nope, da sind SQL Befehle und so drin die nur mit DBlog gehen. Grundsätzlich sollte es aber auch mit einem FileLog gehen falls sich jemand die Mühe macht, den Code entsprechend umzuschreiben.
Danke für die Info