Gibt es Prognosedaten für die tägl.Erzeugungsmenge einer PV Anlage?

Ich bin da z.B. einen ganz anderen Weg gegangen.

Ich hole mir stündlich die Solarstrahlung von https://www.agrar.basf.de und schreibe die für meinen Wohnort in eine geloggte Variable.
Die wirklich erzeugten kWh der ganzen PV’s werden ich eine 2. Variable geloggt.
Aus dem Mittewert/Quotient der letzten 10 Tage aus beiden Variablen wird ein Korrekturfaktor berechnet.
Diesen Faktor nehme ich um mit der Solarstrahlung der nächsten Tage von BASF meine zu erwartenden kWh zu bestimmen.
Vorteil davon, ich brauche keine Ausrichtungen und Winkel berücksichtigen und auch eine ggf. bestehende Verschattung einzelner Teile im Verlauf des Jahres werden so berücksichtigt.

Das funktioniert bis auf wenig kWh sehr gut, Nebeltage sind aber auch da ein Problem, Schnee hingegen würde nach ein paar Tagen wieder „rausgerechnet“ werden, ebenso wie Modulalterung usw.

VG,
Doc

Hi, evtl. sind bei euch im DE Flachland die Vorhersagen ja besser.
Aber hier im AT Gebirge kann man das total knicken. Hab vor Jahren einigen Aufwand investiert leider ohne Erfolg.
Für eine Schön bzw. Schlechtwetterperiode mag es halbwegs hinkommen (+/-20%). Alles andere ist reines 50% Glücksspiel. Viel zu ungenau. Zumindest hier.
Das es auch bei längeren Phasen mit ungetrübtem Sonnenschein arg falsch liegen kann zeigte der heurige Winter. Über Wochen waren die Kollektoren wegen Schnee teilweise abgedeckt. max Leistung 100-400W gegenüber 2500 ohne Schnee.

Besser ist die Daten vom Vortag als Vorgabe für den nächsten Tag zu nehmen. Das trifft es viel besser als alle Wetterberichte.

gruß
bb

Hallo @Jannis,
ich bin heute auf Dein Script gestoßen und ich würde dies gerne ausprobieren. Leider scheint die URL welche Du in Deinem Script verwendest, nicht zu funktionieren, kann es sein das diese angepasst wurde?

Könntest Du in Deinem Script vielleicht noch ein Kommentar hinter Deine Variablen schreiben, damit man weiß wie die Zuordnung zu Deinem Bild aus dem Objektbaum ist?

Vielen Dank & Gruß.

fussi24

Hallo fussi24

$content = Sys_GetURLContent("https://api.solcast.com.au/rooftop_sites/Resource Id/forecasts?format=json&api_key=".$APIkey); // Resource Id ersetzen

die Resource Id muss man noch anpassen. wenn man sich registriert hat bei solcast.com dann auf forecast gehen und dort wird die adresse angegeben.

Hoffe das hilft Dir.

Einen nebligen(obwohl der Forecast es ein klein bisschen besser sieht) Gruß Jannis

Hallo @Jannis,
vielen Dank und die Url habe ich mittlerweile auch gefunden und der Zugriff funktioniert. Die Variablen konnte ich soweit auch nachbilden, nur ab der Zeile 60 könnte ich noch etwas Unterstützung bei den Variablen gebrauchen.

Welche sind das denn und welchen Typ benötigen diese?

@fussi24
Ich stand an der gleichen Stelle im Code mit den Fragezeichen wie du und habe mich gewundert, was das für Variablen sind ab Zeile 60.
Ich habe das so gedeutet:
In Zeile 60 wird in eine Variable des Type String ein Eintrag mit dem zu erwartetenden Ertrag am nächsten Tag gemacht. Diese Variable müsstest du zusätzlich noch anlegen und die Nummer 54219 mit derjenigen deiner Variablen ersetzen, falls du diese Angabe benötigst.
Ab Zeile 63 wird die Variable 43402 (ebenfalls eine zusätzliche des Typs Float) mit Daten der existierenden Variable 54081 (Ertrag des nächsten Tages) gefüllt. Dies basierend auf dem Timerevent um 23.45 welches die ID 33032 hat. Das hat bei mir aber so nicht funktioniert und ich habe das anders gelöst. Ab Zeile 63 habe ich folgenden Code im Einsatz:

//Falls der Script durch den Timer-Event um 23.45 aufgerufen wurde, den prognostizierten Ertrag für Morgen dediziert speichern
if ($_IPS['SENDER'] == "TimerEvent" && $_IPS['EVENT'] == "29454")
{
  Setvalue(41406,intval(GetValue(59674)));
}

29454 ist bei mir der erwähnte TimerEvent um 23.45
41406 ist die Variable, in welche ich den prognostizierten Ertrag für Morgen speichere. Diese Variable wird nur jeden Abend um 23.45 aktualisiert. Der Name der Variable heisst dann „Prognostizierter Ertrag heute“, weil wenn du tagsüber den Wert dieser Variable prüfst, bezieht er sich ja auf heute.
59674 ist bei mir die erste Variable aus dem Array mit den Tageswerten

$ids1d=array(59674,

Ich hoffe es ist klar, was ich meine. Irgendwie werden die Variablennamen beim kopieren des Codes nicht mehr mitübernommen. Das macht das Lesen eines (fremden) scriptes etwas umständlicher…

Danke für den Tipp, die API und Script Vorlage.

Ich war auch noch nicht so ganz glücklich und hab es mal auf meine Bedürfnisse angepasst. Einfach nur 3 Werte heute, morgen, übermorgen
Aufruf täglich 4 Uhr.

<?php

$APIkey = "########";  // todo API Key eintragen
$RooftopID = "#######"; // Todo Rooftop ID eintragen

$id_heute = 35643; // todo: 3x eigene variablen IDs eintragen
$id_morgen = 57369;
$id_uebermorgen = 18522;

$content = Sys_GetURLContent("https://api.solcast.com.au/rooftop_sites/".$RooftopID."/forecasts?format=json&api_key=".$APIkey); 
$json = json_decode($content,true);
$forecasts=$json['forecasts'];

$PVFC_monat = [];   // die FC Werte werden einfach als Tag (index) in das Array geschrieben
$ltag ="";
for ($i = 0; $i < sizeof($forecasts); $i++) 
{
    // Zeitpunkt und FC 
    $ts = strtotime($forecasts[$i]["period_end"]);
    $pv_val = floatval($forecasts[$i]["pv_estimate"]);
   
    $tag = date("d",$ts);

    if ($ltag ==""){
        $ltag = $tag;
    }

    @$PVFC_monat[$tag]=$PVFC_monat[$tag] + ($pv_val/2);      // pv summieren, /2 wegen Halbstunden angabe

    if ($ltag <>$tag){
        $ltag =$tag;
    }
}


$tag=date("d",time());
SetValue($id_heute, $PVFC_monat[$tag]);
$tag=date("d",time()+ (3600*24) );
SetValue($id_morgen, $PVFC_monat[$tag]);
$tag=date("d",time()+ (3600*24*2) );
SetValue($id_uebermorgen, $PVFC_monat[$tag]);
1 „Gefällt mir“

Hallo zusammen,

auch ich bin an dem Thema dran und möchte Euch mal meine Version 0.1 vorstellen:

Das Skript kann für 1 oder mehrere Solaranlagen den Forecast ausgeben über folgende Schnittstellen:

  1. solarcast.com (Kostenlose Registrierung erforderlich)
  2. forecast.soloar(keine Registrierung erforderlich)
  3. Eigene Berechnung (Kostenloser Account bei openweathermap notwendig).

Das Skript erstellt pro Anlage eine Kategorie mit entsprechenden Variablen zum heutigen und morgigen Forecast. Folgende prognostizierte Erträge
morgens, mittags, gesamt
(Bitte entsprechen über Timer einplanen).

über den Parameter HTML_COMPARE = true kann man die Vorhersagen vergleichen in einer Tabelle (HTMLBox).

<?php
/* Forecast einer PV Analage berechnen 
   Klasse kann 2 Forecast Provider lesen
   1. https://toolkit.solcast.com.au/world-api
   2. https://api.forecast.solar/
   3. Eigene Berechnung anhand Ausrichtung, Sonnenstand und Bewölkung von https://openweathermap.org/

  (c) 2022, STELE99
*/

/* Array der PV Anlagen definieren
   kwp:         Installierte Kilowatt Peak als String mit . für nachkommastellen
   azimuth:     Ausrichtung gegen Süden 0=Süden, -90=Osten, 90=Westen
   tilt:        Neigung der Anlage 0=flach, Senkrecht =90
   verlust:     Faktor um Leistungsverluste etc. zu kompensieren
   lon:         Längengrad des PV Standortes als String mit . für nachkommastellen
   lat:         Breitengrad des PV Standortes als String mit . für nachkommastellen
   efficiency:  Wirkungungsgrad der Anlage (zb. Abfall durch Beschattung etc. ) 0-100
*/

$PVA["PV1"]  = [ "kwp"        => "6.7", 
                  "azimuth"    => 60,
                  "tilt"       => 15,
                  "efficiency" => 90,                  
                  "lon"        => "6.129772606",
                  "lat"        => "50.124873309"];

$PVA["PV2"] = [ "kwp"        => "8.0", 
                  "azimuth"    => -30,
                  "tilt"       => 0,
                  "efficiency" => 85,                  
                  "lon"        => "7.929372606",
                  "lat"        => "43.025873309"];

/* Wie wird der ForeCast berechnet 
1 = Solcast
2 = forecast.solar
3 = eigen
*/
$CALC_METHOD = 3;

/* Solcast API-KEY für Forecast Variante 1*/
$SO_APIKEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

/* Openweathermap () für Forecast eigene Berechnung Variante 3  APPID - API KEY */
$OW_APPID    = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

/* Verlgeich der Vorhersagemodelle in HTML Variable (Ausgabeüber String Variable) */
$HTML_COMPARE     = true;

/* Alle Forecast Daten als JSON String in Variable speichern */
$SAVE_TO_VAR      = true;

/* Wie stark hat Bewölkung Auswirkung auf Leistung (Faktor (linear)) Leistungsreduktion = Bewölkung * Faktor*/
$V3_CLOUD_FAKTOR  = 0.75;

/*------------------------------- PROGRAM CODE, NO CHANGE HERE --------------------------------------------*/

// Falls noch nicht existend, Profil anlegen für kwh
$profname = "kWh";
if(!IPS_VariableProfileExists($profname)) {
    // kWh Profil anlegen
    $id = IPS_CreateVariableProfile ($profname, 2);
    IPS_SetVariableProfileIcon($profname, "EnergyStorage");
    IPS_SetVariableProfileText($profname, "", "kWh");
};

// Anlagen auswerten und je Anlage Forecast ermiteln und in einer Kategorie speichern:
foreach($PVA as $Aname => $A){
    $catID = @IPS_GetCategoryIDByName ($Aname, $_IPS['SELF']);
    // Kategroie pro PV Anlage erstellen
    if(empty($catID)){
        $catID = IPS_CreateCategory();
        IPS_SetName($catID, $Aname); // Kategorie benennen
        IPS_SetParent($catID,  $_IPS['SELF']); // Kategorie einsortieren unter dem Objekt mit der ID "12345"
    }
    $pv = new SEPVForecast($A);
    switch($CALC_METHOD){
        case 1: $fc = $pv->getForecast($A);
                break;

        case 2: $fc = $pv->getForecast2($A);
                break;

        case 3: $fc = $pv->getForecast3($A);
                break;
    }
    
    // Werte in Variablen schreiben ==========================================

    // Wenn Job vor 8h dann wird der aktuelle Tag noch ausgewertet
    $idVar1 = CreateVariableByName($catID,"PV heute 0-12h",   2, "kWh");
    $idVar2 = CreateVariableByName($catID,"PV heute Gesamt",   2, "kWh");
    if(date('H') < 9 ){
        SetValue($idVar1, $fc[0]["morgens"]);
        SetValue($idVar2, $fc[0]["gesamt"]);
    }
    $idVar = CreateVariableByName($catID,"PV heute 12-24h",   2, "kWh");
    if(date('H')<13){
        SetValue($idVar, $fc[0]["mittags"]);
    } 
       
    // Werte für morgen.
    $idVar = CreateVariableByName($catID,"PV morgen Gesamt",   2, "kWh");
    SetValue($idVar, $fc[1]["gesamt"]);

    $idVar = CreateVariableByName($catID,"PV morgen 8-12h",   2, "kWh");
    SetValue($idVar, $fc[1]["morgens"]);
    
    $idVar = CreateVariableByName($catID,"PV morgen 12-21h",   2, "kWh");
    SetValue($idVar, $fc[1]["mittags"]);

    // Ausgabe Vergleichstabelle der unterschiedlichen Varianten
    if($HTML_COMPARE == true){        
        $fcA[1] = $pv->getForecast($A);
        $fcA[2] = $pv->getForecast2($A);
        $fcA[3] = $pv->getForecast3($A);
             
        // Charts aufbauen und in eigene Variable ausgeben.
        for($day = 0; $day < 2; $day++){
            $str = "";
            $data = "";
            $chartUID = strtolower($Aname.$day);
            $daytxt = ($day==0 )? "heute" : "morgen";
            
            for($h = 4; $h < 23; $h++){
                $e = @$fcA[1][$day][$h];
                $hour = $h;
                if(!empty($hour))$data .= "['$hour', ".str_replace(",", ".", floatval(@$e["pv_estimate"])).", ".str_replace(",", ".", floatval(@$fcA[2][$day][$hour]["pv_estimate"])).", ".str_replace(",", ".", floatval(@$fcA[3][$day][$hour]["pv_estimate"])).", ".@intval($fcA[3][$day][$hour]["clouds"])."],\n";
            }
            
            $data = substr($data, 0, strlen($data)-2);
            
            
            $str .="<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>
                        <script type='text/javascript'>
                        google.charts.load('current', {'packages':['corechart']});
                        google.charts.setOnLoadCallback(drawChart".$chartUID.");

                        function drawChart".$chartUID."() {
                            var data".$chartUID." = google.visualization.arrayToDataTable([
                            ['Uhrzeit', 'solcast ".round($fcA[1][$day]["gesamt"],0)."kWh', 'forecast.solar ".round($fcA[2][$day]["gesamt"],0)."kWh', 'eigen ".round($fcA[3][$day]["gesamt"],0)."kWh', 'Bewölkung'],
                        $data
                            ]);

                            var options = {
                            title: 'PV Vorhersagemodelle für $Aname, $daytxt',
                            titleTextStyle: {color: '#FFFFFF'},
                            backgroundColor: '#1F3041',
                            colors: ['#F2F3AE', '#FC9E4F', '#F4442E', '#FFFFFF'],
                            hAxis: { gridlines: {color: '#576471'},
                                     textStyle: {color: '#FFF'},
                                     baselineColor:{color: '#FFF'},
                                     title: 'Uhrzeit' ,
                                     titleTextStyle:{color: '#FFF'},
                                    },
                            
                            vAxes: { 0:{
                                        gridlines: {color: '#576471', count: 5}, 
                                        minorGridlines: { color: 'transparent', count: 0 }, 
                                        textStyle:{color: '#FFF'}, 
                                        baselineColor:{color: '#FFF'},
                                        title: 'kWh', 
                                        titleTextStyle:{color: '#FFF'},
                                        viewWindowMode:'maximized',
                                        viewWindow: { min: 0}
                                        
                                      }, 
                                      3:{
                                        gridlines: {color: 'transparent', count: 0}, 
                                        minorGridlines: { count: 0 }, 
                                        textStyle:{color: '#FFF'}, 
                                        baselineColor:{color: '#FFF'},
                                        title: 'Bewölkung', 
                                        titleTextStyle:{color: '#FFF'},
                                        viewWindowMode:'maximized',
                                        viewWindow: {max: 100, min: 0}
                                  } },

                            tooltip: {isHtml: true},
                            series:{    0:{targetAxisIndex:0, type: 'line'},
                                        1:{targetAxisIndex:0, type: 'line'},
                                        2:{targetAxisIndex:0, type: 'line', lineWidth: 3},
                                        3:{targetAxisIndex:3, type:'area', areaOpacity:0.25, lineWidth:0  }},

                            legend: {textStyle: {color: 'white'}, position: 'bottom'},
                            curveType: 'function'
                            };

                            var chart = new google.visualization.AreaChart(document.getElementById('chart".$chartUID."'));

                            chart.draw(data".$chartUID.", options);
                        }
                        </script>
                        <div id='chart".$chartUID."' style='width: 100%; height: 400px'></div>";
            
            $idVar = CreateVariableByName($catID,"Forecast-Chart $Aname $daytxt",   3, "~HTMLBox");

            if((date("H") < 11 && $day == 0 ) || $day != 0){
                SetValue($idVar, $str);
            }
        }

    }

    if($SAVE_TO_VAR){
        $str = json_encode($fc);
        $idVar = CreateVariableByName($catID,"ForecastJSON",   3, "");
        SetValue($idVar, $str);
    }

}



class SEPVForecast {

    private $ow_cache = 3600; // OpenWeather Cache
    private $so_cache = 3600 * 2;
    private $fc_cache = 3600 * 2;

    public  $fc;

    /* ForeCast PV with SolCast ========================================================================= */
    function getForecast($A){
        global $SO_APIKEY;
        global $SO_UTC;
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];
        if($A["azimuth"] > 0){
            $azimuth = 180 - $A["azimuth"];
        }elseif($A["azimuth"] < 0){
            $azimuth = -180 - $A["azimuth"];
        }else{
            $azimuth = 0;
        }        

        $url    = "https://api.solcast.com.au/world_pv_power/forecasts?latitude=$lat&longitude=$lon&capacity=$kwp&tilt=".$A["tilt"]."&azimuth=$azimuth&hours=48&format=json&api_key=$SO_APIKEY";

        $fcache = $_IPS['SELF']."_so_".md5(serialize($A)).".cache";
        if(time() - @filemtime($fcache) > $this->so_cache){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $sodata = json_decode(file_get_contents($fcache));
        $fc = [];
        $hcount =0;
        $hour_old="";
        foreach($sodata->forecasts as $o){
            $hour = date("G",strtotime($o->period_end));
            $day  = date("z",strtotime($o->period_end)) - date("z");
            $fc[$day][$hour] = [
                                "hour"           =>  $hour,
                                "pv_estimate"    => $o->pv_estimate,
                                ];
            $hour_old = $hour;
        }

        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->so_fc = $fc;
        return $fc;
    }

    /* ForeCast PV with forecast.solar ========================================================================= */
    function getForecast2($A){
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];
        $url    = "https://api.forecast.solar/estimate/$lat/$lon/".$A["tilt"]."/".$A["azimuth"]."/$kwp";
        $fcache =  $_IPS['SELF']."_fc_".md5(serialize($A)).".cache";
        if(time() - @filemtime($fcache) > $this->fc_cache ){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $data = json_decode(file_get_contents($fcache));
        $fc = [];
        foreach($data->result->watts as $t => $watts){
            $hour = date("G",strtotime($t));
            $day  = date("z",strtotime($t)) - date("z");
            $fc[$day][$hour] = [
                                "hour"           =>  $hour,
                                "pv_estimate"    => @$fc[$day][$hour]["pv_estimate"] + ($watts / 1000),
                                ];
        }

        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->fc = $fc;
        return $fc;
    }

    /* ForeCast PV eigene Ermittlung====================================================================== */
    function getForecast3($A){
        global $OW_APPID;
        global $V3_CLOUD_FAKTOR;
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];

        // Wetterdaten lesen und cachen
        $url = "https://api.openweathermap.org/data/2.5/onecall?lat=$lat&lon=$lon&exclude=minutely,alerts,current&units=metric&lang=de_de&appid=$OW_APPID";
        $fcache =  $_IPS['SELF']."_ow".md5($A["lon"].$A["lat"]).".cache";
        if(time() - @filemtime($fcache) > $this->ow_cache){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $data = json_decode(file_get_contents($fcache));

       foreach($data->hourly as $h){
            $day     =  date("z", $h->dt) - date("z");
            $hour    =  date("G", $h->dt);
            $clouds  = $h->clouds;
            #$clouds = 0;
            
            $ret        = $this->calcSun($h->dt, $lon, $lat);
            $sun_azimuth    = $ret["azimuth"];
            $sun_elevation  = $ret["elevation"];

            /* Kalkulation des Ertrages
               Daten von https://echtsolar.de/wp-content/uploads/2021/02/Ausrichtungstabelle-Photovoltaik-in-Deutschland-768x705.png
               Formel über Newton Polynom: https://de.planetcalc.com/9023/
            */
            
            $lf = 100;
            $az_abw = round(abs($sun_azimuth - 180 - $A["azimuth"]),1);
            #$lf_minusA =  round(0.002019* pow( $az_abw, 2) -0.02878 * $az_abw + 0.5471, 1); // Formel via funktion aus 3-4 punkten
            if($az_abw > 180){
                $lf_minusA = 100;
            }else{
                $lf_minusA = (-0.00000000147) * pow( $az_abw, 5) + (0.00000057668) * pow ($az_abw, 4) + (-0.00008107497) * pow ($az_abw, 3) + (0.00559429998 * pow ($az_abw, 2)) + (0.05160253657 * $az_abw);
            }
            #echo "$hour h: $sun_azimuth : $az_abw -> $lf_minusA\n";
            
            $lf = $lf - $lf_minusA;
            #echo "Azimuth $lf_minusA >> $lf \n";

            // Neigungswikel und Sonne            
            $elev_abw = 90 - $sun_elevation + $A["tilt"];
            $x = $elev_abw;
            #$lf_minusE  =  round( 0.0000474    * pow( $elev_abw, 3) + 0.002798 * pow( $elev_abw, 2) + 0.2894 * $elev_abw - 2.453, 1);
            $lf_minusE  = (-0.00000000184772 * pow($x, 6)) + (0.00000055691964 * pow($x, 5)) + (-0.00006230158730 * pow($x, 4)) + (0.00319568452381 * pow($x, 3)) + (-0.06371230158730 * pow($x, 2)) + (-0.13880952380952 * $x) + 14;
            if($sun_elevation < 0) $lf_minusE = 100; // Sonnenuntergang
            $lf_minusE = round($lf_minusE,1);
            $lf = $lf - $lf_minusE;
            #echo "$hour: A: -$lf_minusA E:-$lf_minusE : $lf\n";
            

            // Bewölkung hängt von der Wolkendicke und von dem Einstrahlungswinkel ab.
            $lf_minusC = (pow($clouds,2.4)/600) * $V3_CLOUD_FAKTOR;
            
            #echo $clouds.": " .$lf_minusC."\n";
            $lf = $lf - $lf_minusC;
            #echo "Clouds $clouds >> $lf \n";

            $lf = ($lf < 0 )? 0 : $lf;


            $fc[$day][$hour] = [
                                "day"            =>  $day,
                                "hour"           =>  $hour,
                                "clouds"         =>  $clouds,
                                "pv_estimate"    =>  $A["kwp"] * ($lf / 100) * $A["efficiency"]/100,
                                ];        
        }

        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->fc = $fc;
        return $fc;
    }


    private function calcSun($ts, $dLongitude, $dLatitude){
        // Correction Timezone
        $ts = $ts - 3600;

        $iYear = date("Y", $ts);
        $iMonth = date("m", $ts);
        $iDay = date("d", $ts);
        $dHours = date("H", $ts);
        $dMinutes = date("i", $ts);
        $dSeconds = date("s", $ts);

        $pi = 3.14159265358979323846;
        $twopi = (2*$pi);
        $rad = ($pi/180);
        $dEarthMeanRadius = 6371.01;	// In km
        $dAstronomicalUnit = 149597890;	// In km

        // Calculate difference in days between the current Julian Day
        // and JD 2451545.0, which is noon 1 January 2000 Universal Time

        // Calculate time of the day in UT decimal hours
        $dDecimalHours = floatval($dHours) + (floatval($dMinutes) + floatval($dSeconds) / 60.0 ) / 60.0;
        

        // Calculate current Julian Day

        $iYfrom2000 = $iYear;//expects now as YY ;
        $iA= (14 - ($iMonth)) / 12;
        $iM= ($iMonth) + 12 * $iA -3;
        $liAux3=(153 * $iM + 2)/5;
        $liAux4= 365 * ($iYfrom2000 - $iA);
        $liAux5= ( $iYfrom2000 - $iA)/4;
        $dElapsedJulianDays= floatval(($iDay + $liAux3 + $liAux4 + $liAux5 + 59)+ -0.5 + $dDecimalHours/24.0);

        // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
        // ecliptic in radians but without limiting the angle to be less than 2*Pi
        // (i.e., the result may be greater than 2*Pi)

        $dOmega= 2.1429 - 0.0010394594 * $dElapsedJulianDays;
        $dMeanLongitude = 4.8950630 + 0.017202791698 * $dElapsedJulianDays; // Radians
        $dMeanAnomaly = 6.2400600 + 0.0172019699 * $dElapsedJulianDays;
        $dEclipticLongitude = $dMeanLongitude + 0.03341607 * sin( $dMeanAnomaly ) + 0.00034894 * sin( 2 * $dMeanAnomaly ) -0.0001134 -0.0000203 * sin($dOmega);
        $dEclipticObliquity = 0.4090928 - 6.2140e-9 * $dElapsedJulianDays +0.0000396 * cos($dOmega);

        // Calculate celestial coordinates ( right ascension and declination ) in radians
        // but without limiting the angle to be less than 2*Pi (i.e., the result may be
        // greater than 2*Pi)

        $dSin_EclipticLongitude = sin( $dEclipticLongitude );
        $dY1 = cos( $dEclipticObliquity ) * $dSin_EclipticLongitude;
        $dX1 = cos( $dEclipticLongitude );
        $dRightAscension = atan2( $dY1,$dX1 );
        if( $dRightAscension < 0.0 ) $dRightAscension = $dRightAscension + $twopi;
        $dDeclination = asin( sin( $dEclipticObliquity )* $dSin_EclipticLongitude );

        // Calculate local coordinates ( azimuth and zenith angle ) in degrees

        $dGreenwichMeanSiderealTime = 6.6974243242 +	0.0657098283 * $dElapsedJulianDays + $dDecimalHours;

        $dLocalMeanSiderealTime = ($dGreenwichMeanSiderealTime*15 + $dLongitude)* $rad;
        $dHourAngle = $dLocalMeanSiderealTime - $dRightAscension;
        $dLatitudeInRadians = $dLatitude * $rad;
        $dCos_Latitude = cos( $dLatitudeInRadians );
        $dSin_Latitude = sin( $dLatitudeInRadians );
        $dCos_HourAngle= cos( $dHourAngle );
        $dZenithAngle = (acos( $dCos_Latitude * $dCos_HourAngle * cos($dDeclination) + sin( $dDeclination )* $dSin_Latitude));
        $dY = -sin( $dHourAngle );
        $dX = tan( $dDeclination )* $dCos_Latitude - $dSin_Latitude * $dCos_HourAngle;
        $dAzimuth = atan2( $dY, $dX );
        if ( $dAzimuth < 0.0 )
            $dAzimuth = $dAzimuth + $twopi;
        $dAzimuth = $dAzimuth / $rad;
        // Parallax Correction
        $dParallax = ($dEarthMeanRadius / $dAstronomicalUnit) * sin( $dZenithAngle);
        $dZenithAngle = ($dZenithAngle + $dParallax) / $rad;
        $dElevation = 90 - $dZenithAngle;
            
        return Array("azimuth" => $dAzimuth, "elevation" => $dElevation);
    }


}


// Helper Funktion
function CreateVariableByName($id, $name, $type, $profile = "")
{
    # type: 0=boolean, 1 = integer, 2 = float, 3 = string;
    global $_IPS;
    $vid = @IPS_GetVariableIDByName($name, $id);
    if($vid === false)
    {
        $vid = IPS_CreateVariable($type);
        IPS_SetParent($vid, $id);
        IPS_SetName($vid, $name);
        IPS_SetInfo($vid, "this variable was created by script #".$_IPS['SELF']);
        if($profile !== "") { IPS_SetVariableCustomProfile($vid, $profile); }
    }
    return $vid;
}



Habe das Skript mal bei mir eingebunden.
Bekomme derzeit einige Warnungen beim Ausführen bzw. den Json String passt auch wohl nicht ganz.

Notice: Undefined property: stdClass::$hourly in /var/lib/symcon/scripts/12013.ips.php on line 360

Warning: Invalid argument supplied for foreach() in /var/lib/symcon/scripts/12013.ips.php on line 360

Notice: Undefined variable: fc in /var/lib/symcon/scripts/12013.ips.php on line 418

Warning: Invalid argument supplied for foreach() in /var/lib/symcon/scripts/12013.ips.php on line 418

Notice: Undefined variable: fc in /var/lib/symcon/scripts/12013.ips.php on line 433

Notice: Undefined variable: fc in /var/lib/symcon/scripts/12013.ips.php on line 434

Notice: Trying to access array offset on value of type null in /var/lib/symcon/scripts/12013.ips.php on line 142

Notice: Trying to access array offset on value of type null in /var/lib/symcon/scripts/12013.ips.php on line 142

Notice: Trying to access array offset on value of type null in /var/lib/symcon/scripts/12013.ips.php on line 142

Notice: Trying to access array offset on value of type null in /var/lib/symcon/scripts/12013.ips.php on line 142

Hat einer schonmal Versucht die Optimierungsfunktoon von SolCast mit einzubinden?

Gruß

Vielen Dank für das Skript! Ist es möglich, die Werte auch Stundenweise über Solcast abzurufen? Ich würde gerne die Aufheizphase meines Warmwassers nach hinten schieben falls voraussichtlich in den nächsten x Stunden genug PV Energie zur Verfügung stehen würde.

Vielen Dank vorab!

Hallo zusammen,

die o.g. fehler von @n0b0dy90 kommen vermutlich daher, dass Du keine gültige Subscription von OWM hast, das neues Script nutzt die BrightSky API von DWD - da gibt’s die Daten ohne Subscription.

@Moritz_312 ich habe das Script nochmals etwas überarbeitet und angepasst.
Es gibt jetzt die Möglichkeit die Wetterdaten von DWD abzurufen, ohne Abo.

Ich habe das Script noch etwas erweitert:

  • Der Temperaturkoeffizient der Module kann angegeben werden (Leistungsreduktion bei Hitze)
  • DWD statt OpenWeathermap (Ohne Subscription)
  • Beschattung der Anlage durch ein Objekt wird berücksichtigt, wenn notwendig

Hier das neue Script:

<?php
/* Forecast einer PV Analage berechnen 
   Klasse kann 2 Forecast Provider lesen
   1. https://toolkit.solcast.com.au/world-api
   2. https://api.forecast.solar/
   3. Eigene Berechnung anhand Ausrichtung, Sonnenstand und Bewölkung von https://openweathermap.org/ oder brightsky (dwd-mosmix)

  (c) 2022, STELE99
*/

/* Array der PV Anlagen definieren
   kwp:         Installierte Kilowatt Peak als String mit . für nachkommastellen
   azimuth:     Ausrichtung gegen Süden 0=Süden, -90=Osten, 90=Westen
   tilt:        Neigung der Anlage 0=flach, Senkrecht =90
   verlust:     Faktor um Leistungsverluste etc. zu kompensieren
   lon:         Längengrad des PV Standortes als String mit . für nachkommastellen
   lat:         Breitengrad des PV Standortes als String mit . für nachkommastellen
   efficiency:  Wirkungungsgrad der Anlage (zb. Abfall durch Beschattung etc. ) 0-100
   cloudeffect: Auswirkung bei Bewölkung (0-100) Ertragsreduktion in Prozent
   horizon: Grad des Horizontes (Bei Bergen wg. Sonnenaufgang)
   tempkoeff: Temperaturkoeffizient der PV Module 
   obj_direction: Beschattung durch ein Objekt, Himmelsrichtung des Objektes in Grad
   obj_height: Höhe des Objektes in meter
   obj_size: Größe des Objektes (Abdeckung prozentualer Anteil des Schattens auf die PV Anlage)
   obj_effect: Auswirkung auf die Reduktion des Ertrages
*/


$PVA["Dach"]  = [ "kwp"        => "6.7", 
                  "azimuth"    => 60,
                  "tilt"       => 15,
                  "efficiency" => 90,                  
                  "pvtype"     => "N",   // N=Normale Dachfläche D= PV in Dachform geständert, Ausrichtung der offenen seite = azimuth
                  "lon"        => "6.829772606",
                  "lat"        => "45.524873309",
                  "tempkoeff"  => 0.34,
                  "cloudeffect" => 90,   // Effekt für Leistungsreduktion bei Bewölkung
                  "horizon" => 15, // Horizont für Einfallswinkel Sonne (Horizont ca. 5 Grad, dach jedoch 15 etwas gedreht weniger)
                  ];

$PVA["Garage"] = [ "kwp"        => "8.0", 
                  "azimuth"     => -50, // eigentlich sind es 30 aber soll ist vergleich zeigt leichte verschiebung vom abend - also mehr nach rechts drehen
                  "tilt"        => 10,
                  "pvtype"      => "D",   // D= Dachform geständert, Ausrichtung der offenen seite = azimuth
                  "efficiency"  => 105,
                  "cloudeffect" => 60,   // Effekt für Leistungsreduktion bei Bewölkung in Prozent
                  "lon"         => "10.29772606",
                  "lat"         => "4.024873309",
                  "tempkoeff"   => 0.38,       // Temperaturkoeffizient lt. Datenblatt
                  "horizon"     => 8,             // Horizont für Einfallswinkel Sonne
                  
                  // Beschattungsobjekt
                  "obj_direction" => 58.4,   // Himmelsrichtung des Beschattungsobjektes Grad von Norden =0
                  "obj_distance"  => 8,      // Abstand des Objektes in Meter
                  "obj_height"    => 4,      // Höhe des Objektes in Meter
                  "obj_size"      => 50,    // Prozentualer Abdeckungsanteil der PV Anlage durch Objekt (Mittelwert)
                  "obj_effect"    => 0.65    // Azuswirkung der Beschattung auf Ertrag (kwp mit gemessenem Ertrag bei Beschattung (grob))
                  ];

/* Wie wird der ForeCast berechnet 
1 = Solcast
2 = forecast.solar
3 = eigen
*/
$CALC_METHOD = 3;

/* Solcast API-KEY für Forecast Variante 1*/
$SO_APIKEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

/* Wetterdienst für Vorhersage der Bewölkung für ForeCast Version 3 (eigen) */
$WEATHER = "dwd";  // dwd (Deutscher Wetterdienst Mosmix über brightsky)
#$WEATHER = "owm";  // owm (Open Weather Map - bitte unten APPID angeben für API Aufruf)

/* Openweathermap () für Forecast eigene Berechnung Variante 3  APPID - API KEY */
$OW_APPID    = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

/* Verlgeich der Vorhersagemodelle in HTML Tabelle (Ausgabeüber String Variable) */
$HTML_COMPARE     = true;

/* Alle Forecast Daten als JSON String in Variable speichern */
$SAVE_TO_VAR      = true;

/* Wie stark hat Bewölkung Auswirkung auf Leistung (Faktor (linear)) Leistungsreduktion = Bewölkung * Faktor*/
$V3_CLOUD_FAKTOR  = 0.55;

/*------------------------------- PROGRAM CODE, NO CHANGE HERE --------------------------------------------*/

// Falls noch nicht existend, Profil anlegen für kwh
$profname = "kWh";
if(!IPS_VariableProfileExists($profname)) {
    // kWh Profil anlegen
    $id = IPS_CreateVariableProfile ($profname, 2);
    IPS_SetVariableProfileIcon($profname, "EnergyStorage");
    IPS_SetVariableProfileText($profname, "", "kWh");
};

// Anlagen auswerten und je Anlage Forecast ermiteln und in einer Kategorie speichern:
foreach($PVA as $Aname => $A){
    $catID = @IPS_GetCategoryIDByName ($Aname, $_IPS['SELF']);
    // Kategroie pro PV Anlage erstellen
    if(empty($catID)){
        $catID = IPS_CreateCategory();
        IPS_SetName($catID, $Aname); // Kategorie benennen
        IPS_SetParent($catID,  $_IPS['SELF']); // Kategorie einsortieren unter dem Objekt mit der ID "12345"
    }
    $pv = new SEPVForecast($A);
    switch($CALC_METHOD){
        case 1: $fc = $pv->getForecast($A);
                break;

        case 2: $fc = $pv->getForecast2($A);
                break;

        case 3: $fc = $pv->getForecast3($A);
                break;
    }
    
    // Werte in Variablen schreiben ==========================================

    // Wenn Job vor 8h dann wird der aktuelle Tag noch ausgewertet
    $idVar1 = CreateVariableByName($catID,"PV heute 0-12h",   2, "kWh");
    $idVar2 = CreateVariableByName($catID,"PV heute Gesamt",   2, "kWh");
    if(date('H') < 9 ){
        SetValue($idVar1, $fc[0]["morgens"]);
        SetValue($idVar2, $fc[0]["gesamt"]);
    }
    $idVar = CreateVariableByName($catID,"PV heute 12-24h",   2, "kWh");
    if(date('H')<13){
        SetValue($idVar, $fc[0]["mittags"]);
    } 
       
    // Werte für morgen.
    $idVar = CreateVariableByName($catID,"PV morgen Gesamt",   2, "kWh");
    SetValue($idVar, $fc[1]["gesamt"]);

    $idVar = CreateVariableByName($catID,"PV morgen 8-12h",   2, "kWh");
    SetValue($idVar, $fc[1]["morgens"]);
    
    $idVar = CreateVariableByName($catID,"PV morgen 12-21h",   2, "kWh");
    SetValue($idVar, $fc[1]["mittags"]);

    // Ausgabe Vergleichstabelle der unterschiedlichen Varianten
    if($HTML_COMPARE == true){        
        $fcA[1] = $pv->getForecast($A);
        $fcA[2] = $pv->getForecast2($A);
        $fcA[3] = $pv->getForecast3($A);
             
        // Charts aufbauen und in eigene Variable ausgeben.
        for($day = 0; $day < 2; $day++){
            $str = "";
            $data = "";
            $chartUID = strtolower($Aname.$day);
            $daytxt = ($day==0 )? "heute" : "morgen";
            
            for($h = 4; $h < 23; $h++){
                $e = @$fcA[1][$day][$h];
                $hour = $h;
                if(!empty($hour))$data .= "['$hour', ".str_replace(",", ".", floatval(@$e["pv_estimate"])).", ".str_replace(",", ".", floatval(@$fcA[2][$day][$hour]["pv_estimate"])).", ".str_replace(",", ".", floatval(@$fcA[3][$day][$hour]["pv_estimate"])).", ".@intval($fcA[3][$day][$hour]["clouds"])."],\n";
            }
            
            $data = substr($data, 0, strlen($data)-2);
            
            
            $str .="<div id='sechart_$chartUID'>
                    <div id='chart".$chartUID."' style='width: 100%; height: 400px'></div>
                    <script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>
                        <script type='text/javascript'>
                            google.charts.load('current', {'packages':['corechart']});
                            google.charts.setOnLoadCallback(drawChart".$chartUID.");

                            function drawChart".$chartUID."() {
                                var data".$chartUID." = google.visualization.arrayToDataTable([
                                ['Uhrzeit', 'solcast ".round($fcA[1][$day]["gesamt"],0)."kWh', 'forecast.solar ".round($fcA[2][$day]["gesamt"],0)."kWh', 'eigen ".round($fcA[3][$day]["gesamt"],0)."kWh', 'Bewölkung'],
                            $data
                                ]);

                                var options = {
                                title: 'PV Vorhersagemodelle für $Aname, $daytxt',
                                titleTextStyle: {color: '#FFFFFF'},
                                backgroundColor: '#1F3041',
                                colors: ['#F2F3AE', '#FC9E4F', '#F4442E', '#FFFFFF'],
                                hAxis: { gridlines: {color: '#576471'},
                                        textStyle: {color: '#FFF'},
                                        baselineColor:{color: '#FFF'},
                                        title: 'Uhrzeit' ,
                                        titleTextStyle:{color: '#FFF'},
                                        },
                                
                                vAxes: { 0:{
                                            gridlines: {color: '#576471', count: 5}, 
                                            minorGridlines: { color: 'transparent', count: 0 }, 
                                            textStyle:{color: '#FFF'}, 
                                            baselineColor:{color: '#FFF'},
                                            title: 'kWh', 
                                            titleTextStyle:{color: '#FFF'},
                                            viewWindowMode:'maximized',
                                            viewWindow: { min: 0}
                                            
                                        }, 
                                        3:{
                                            gridlines: {color: 'transparent', count: 0}, 
                                            minorGridlines: { count: 0 }, 
                                            textStyle:{color: '#FFF'}, 
                                            baselineColor:{color: '#FFF'},
                                            title: 'Bewölkung', 
                                            titleTextStyle:{color: '#FFF'},
                                            viewWindowMode:'maximized',
                                            viewWindow: {max: 100, min: 0}
                                    } },

                                tooltip: {isHtml: true},
                                series:{    0:{targetAxisIndex:0, type: 'line'},
                                            1:{targetAxisIndex:0, type: 'line'},
                                            2:{targetAxisIndex:0, type: 'line', lineWidth: 3},
                                            3:{targetAxisIndex:3, type:'area', areaOpacity:0.25, lineWidth:0  }},

                                legend: {textStyle: {color: 'white'}, position: 'bottom'},
                                curveType: '' // oder function
                                };
                                var chart = new google.visualization.AreaChart(document.getElementById('chart".$chartUID."'));
                                chart.draw(data".$chartUID.", options);
                            }
                        </script>
                    </div>";
                        
            
            $idVar = CreateVariableByName($catID,"Forecast-Chart $Aname $daytxt",   3, "~HTMLBox");
            if((date("H") < 11 && $day == 0 ) || $day != 0){
                SetValue($idVar, $str);
            }
        }

    }

    if($SAVE_TO_VAR){
        $str = json_encode($fc);
        $idVar = CreateVariableByName($catID,"ForecastJSON",   3, "");
        SetValue($idVar, $str);
    }

}



class SEPVForecast {

    private $w_cache = 3600; // Weather Cache
    private $so_cache = 3600 * 2;
    private $fc_cache = 3600 * 2;

    public  $fc;

    /* ForeCast PV with SolCast ========================================================================= */
    function getForecast($A){
        global $SO_APIKEY;
        global $SO_UTC;
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];
        if($A["azimuth"] > 0){
            $azimuth = 180 - $A["azimuth"];
        }elseif($A["azimuth"] < 0){
            $azimuth = -180 - $A["azimuth"];
        }else{
            $azimuth = 0;
        }        

        $url    = "https://api.solcast.com.au/world_pv_power/forecasts?latitude=$lat&longitude=$lon&capacity=$kwp&tilt=".$A["tilt"]."&azimuth=$azimuth&hours=48&format=json&api_key=$SO_APIKEY";

        $fcache = $_IPS['SELF']."_so_".md5(serialize($A)).".cache";
        if(time() - @filemtime($fcache) > $this->so_cache){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $sodata = json_decode(file_get_contents($fcache));
        $fc = [];
        $hcount =0;
        $hour_old="";
        foreach($sodata->forecasts as $o){
            $hour = date("G",strtotime($o->period_end));
            $day  = date("z",strtotime($o->period_end)) - date("z");
            $fc[$day][$hour] = [
                                "hour"           =>  $hour,
                                "pv_estimate"    => $o->pv_estimate,
                                ];
            $hour_old = $hour;
        }

        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->so_fc = $fc;
        return $fc;
    }

    /* ForeCast PV with forecast.solar ========================================================================= */
    function getForecast2($A){
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];
        $url    = "https://api.forecast.solar/estimate/$lat/$lon/".$A["tilt"]."/".$A["azimuth"]."/$kwp";
        $fcache =  $_IPS['SELF']."_fc_".md5(serialize($A)).".cache";
        if(time() - @filemtime($fcache) > $this->fc_cache ){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $data = json_decode(file_get_contents($fcache));
        $fc = [];
        foreach($data->result->watts as $t => $watts){
            $hour = date("G",strtotime($t));
            $day  = date("z",strtotime($t)) - date("z");
            $fc[$day][$hour] = [
                                "hour"           =>  $hour,
                                "pv_estimate"    => @$fc[$day][$hour]["pv_estimate"] + ($watts / 1000),
                                ];
        }

        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->fc = $fc;
        return $fc;
    }

    /* ForeCast PV eigene Ermittlung====================================================================== */
    function getForecast3($A){
        global $OW_APPID;
        global $V3_CLOUD_FAKTOR;
        global $WEATHER;
        $lon = $A["lon"];
        $lat = $A["lat"];
        $kwp = $A["kwp"];

        // Wetterdaten lesen und cachen
        switch($WEATHER){
            case "owm":
                    $url = "https://api.openweathermap.org/data/2.5/onecall?lat=$lat&lon=$lon&exclude=minutely,alerts,current&units=metric&lang=de_de&appid=$OW_APPID";
                break;
            default:
                    $url = "https://api.brightsky.dev/weather?date=".date("Y-m-d")."&last_date=".date("Y-m-d", time()+3600*24*3)."&lat=$lat&lon=$lon";
        }
        $fcache =  $_IPS['SELF']."_w".md5($WEATHER.$A["lon"].$A["lat"]).".cache";
        if(time() - @filemtime($fcache) > $this->w_cache){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Error:' . curl_error($ch);
            }
            curl_close($ch);            
            file_put_contents($fcache, $result);
        }
        $data = json_decode(file_get_contents($fcache), true);
    
        // Wetterservice Datena aufbereiten je nach Service
        switch($WEATHER){
            case "owm": // OpenWeather
                    foreach($data["hourly"] as $w){
                        $ts = $w["dt"];
                        $day     =  date("z", $ts) - date("z");
                        $hour    =  date("G", $ts);
                        
                        $fcE["ts"] = $ts;
                        $fcE["dateiso"] = date("Y-m-d, H:i:s", $ts);
                        $fcE["day"] = $day;
                        $fcE["hour"] = $hour;
                        $fcE["clouds"] = $w["clouds"];
                        $fcE["temperature"] = $w["temp"];
                        $fcE["visibility"] = $w["visibility"];
                        $fcE["precipitation"] = @$w["rain"] + @$w["snow"];
                        $fcW[] = $fcE;
                    }   
                    break; 
            default: // dwd-mosmix
                    foreach($data["weather"] as $w){
                        $ts = strtotime($w["timestamp"]);
                        $day = date("z", $ts) - date("z");
                        $hour = date("G", $ts);
                        
                        $fcE["ts"] = $ts;
                        $fcE["dateiso"] = date("Y-m-d, H:i:s", $ts);
                        $fcE["day"] = $day;
                        $fcE["hour"] = $hour;
                        $fcE["clouds"] = $w["cloud_cover"];
                        $fcE["temperature"] = $w["temperature"];
                        $fcE["visibility"] = $w["visibility"];
                        $fcE["precipitation"] = $w["precipitation"];
                        $fcW[] = $fcE;
                        
                    }        
                break;
        }
       for($cnt=0; $cnt <= 48; $cnt++){
            $fcE = $fcW[$cnt];
            $day     =  $fcE["day"];
            $hour    =  $fcE["hour"];
            $clouds  =  $fcE["clouds"];
            $temp    =  $fcE["temperature"];
            #print_r($fcE);

            $lf = 100;            
            $ret        = $this->calcSun($fcE["ts"], $lon, $lat);
            $sun_azimuth    = $ret["azimuth"];
            $sun_elevation  = $ret["elevation"];

            /* --------- Kalkulation der Beschattung egal wie die Anlage ausgerichtet ist. */
            if(isset($A["obj_direction"])){
                // 2x berechnen und mittelwert bilden für volle stunde und 30min
                for($x=0; $x <=1; $x++){
                    $time = $fcE["ts"] + $x * 1800;
                    
                    $sunpos = $this->calcSun($time, $lon, $lat);
                    $alpha   = deg2rad($sunpos["elevation"]);
                    $azimuth = $sunpos["azimuth"];
                    $shadeAngle  = $azimuth - $A["obj_direction"] - 90;
                    $shadeLength = round($A["obj_height"] / (tan($alpha) ),2);
                    
                    if($shadeLength < $A["obj_distance"] || $shadeAngle >0){
                        $lf_minusShadeA[$x] = 100;
                    }else{
                        $lf_minusShadeA[$x] = $lf*($A["obj_size"]/100)*$A["obj_effect"] + $lf*( 1 - ($A["obj_size"]/100));
                    }
                }
                $lf_minusShade = ($lf_minusShadeA[0] + $lf_minusShadeA[1]) / 2;
                $lf = $lf_minusShade;
            }

            /* ------------ Kalkulation des Ertrages
               Daten von https://echtsolar.de/wp-content/uploads/2021/02/Ausrichtungstabelle-Photovoltaik-in-Deutschland-768x705.png
               Formel über Newton Polynom: https://de.planetcalc.com/9023/
            */
            if($A["pvtype"] == "D"){
                // Dachständerung /\/\/\ 
                /* 1/2 der Leistung muss um 90 grad nach ost und 90 grad nach west gedreht werden
                */
                $lfA = $lf_minusShade;
                $lfB = $lf_minusShade;

                $az_abwA = round(abs($sun_azimuth - 180 + 90 - $A["azimuth"]),1);
                $az_abwB = round(abs($sun_azimuth - 180 - 90 - $A["azimuth"]),1);
                #$lf_minusA =  round(0.002019* pow( $az_abw, 2) -0.02878 * $az_abw + 0.5471, 1); // Formel via funktion aus 3-4 punkten
                if($az_abwA > 180 ){
                    $lf_minusAA = 90;
                }else{
                    #$lf_minusAA = (-0.00000000147) * pow( $az_abwA, 5) + (0.00000057668) * pow ($az_abwA, 4) + (-0.00008107497) * pow ($az_abwA, 3) + (0.00559429998 * pow ($az_abwA, 2)) + (0.05160253657 * $az_abwA);
                    $lf_minusAA = sin( (1/58) * $az_abwA + 155.5) * 26 + 26;
                }
                if($az_abwB > 180 ){
                    $lf_minusBA = 90;
                }else{
                    #$lf_minusBA = (-0.00000000147) * pow( $az_abwB, 5) + (0.00000057668) * pow ($az_abwB, 4) + (-0.00008107497) * pow ($az_abwB, 3) + (0.00559429998 * pow ($az_abwB, 2)) + (0.05160253657 * $az_abwB);
                    $lf_minusBA = sin( (1/58) * $az_abwB + 155.5) * 26 + 26; // Mit Daten aus Tabelle und näherung über probieren der Sinus-Funktion
                }                
                #echo "$hour h: $sun_azimuth : $az_abw -> $lf_minusA\n";
                
                $lfA = $lfA - $lf_minusAA * 0.90; // fällt schwächer ins gewicht
                $lfB = $lfB - $lf_minusBA * 0.90; // fällt schwächer ins gewicht
                #echo "Azimuth $lf_minusA >> $lf \n";

                // Neigungswikel und Sonne            
                $elev_abw = 90 - $sun_elevation  - $A["tilt"];
                #echo "h: $hour - $elev_abw\n";
                $x = $elev_abw;
                #$lf_minusE  =  round( 0.0000474    * pow( $elev_abw, 3) + 0.002798 * pow( $elev_abw, 2) + 0.2894 * $elev_abw - 2.453, 1);
                #$lf_minusE  = (-0.00000000184772 * pow($x, 6)) + (0.00000055691964 * pow($x, 5)) + (-0.00006230158730 * pow($x, 4)) + (0.00319568452381 * pow($x, 3)) + (-0.06371230158730 * pow($x, 2)) + (-0.13880952380952 * $x) + 14;
                $lf_minusE   = (1/100) * pow ($x, 2); // Neue Formel anhand Tabellen und Werten 

                if($sun_elevation < @$A["horizon"] + 5) $lf_minusE = 50; // Sonnenuntergang            
                if($sun_elevation < @$A["horizon"] ) $lf_minusE = 100; // Sonnenuntergang
                $lf_minusE = round($lf_minusE,1);
                $lfA = $lfA - $lf_minusE  * 0.9; // fällt schwächer ins gewicht;
                $lfB = $lfB - $lf_minusE  * 0.9; // fällt schwächer ins gewicht;

                // Bewölkung hängt von der Wolkendicke und von dem Einstrahlungswinkel ab.
                $lf_minusC = (pow($clouds,2.4)/600) * $A["cloudeffect"]/100;
                #$lf_minusC = 100;
                $lfA = $lfA - $lf_minusC;
                $lfB = $lfB - $lf_minusC;
                $lfA = ($lfA< 0 )? 0 : $lfA;                
                $lfB = ($lfB< 0 )? 0 : $lfB;                
                
                $pv_estimate = ( $A["kwp"] / 2) * ($lfA / 100) * $A["efficiency"]/100;
                $pv_estimate += ( $A["kwp"] / 2) * ($lfB / 100) * $A["efficiency"]/100;

                #echo "$hour: $pv_estimate (Schatten: $lf_minusShade, Azimut $lf_minusAA - $lf_minusBA, Elv: $lf_minusE, Cloud: $lf_minusC)\n";

            }else{
                $az_abw = round(abs($sun_azimuth - 180 - $A["azimuth"]),1);
                #$lf_minusA =  round(0.002019* pow( $az_abw, 2) -0.02878 * $az_abw + 0.5471, 1); // Formel via funktion aus 3-4 punkten
                if($az_abw > 180){
                    $lf_minusA = 100;
                }else{
                    $lf_minusA = (-0.00000000147) * pow( $az_abw, 5) + (0.00000057668) * pow ($az_abw, 4) + (-0.00008107497) * pow ($az_abw, 3) + (0.00559429998 * pow ($az_abw, 2)) + (0.05160253657 * $az_abw);
                }
                #echo "$hour h: $sun_azimuth : $az_abw -> $lf_minusA\n";
                
                $lf = $lf - $lf_minusA;
                #echo "Azimuth $lf_minusA >> $lf \n";

                // Neigungswikel und Sonne            
                $elev_abw = 90 - $sun_elevation  - $A["tilt"];
                $x = $elev_abw;
                #$lf_minusE  =  round( 0.0000474    * pow( $elev_abw, 3) + 0.002798 * pow( $elev_abw, 2) + 0.2894 * $elev_abw - 2.453, 1);
                #$lf_minusE  = (-0.00000000184772 * pow($x, 6)) + (0.00000055691964 * pow($x, 5)) + (-0.00006230158730 * pow($x, 4)) + (0.00319568452381 * pow($x, 3)) + (-0.06371230158730 * pow($x, 2)) + (-0.13880952380952 * $x) + 14;
                $lf_minusE   = (1/100) * pow ($x, 2); // Neue Formel anhand Tabellen und Werten 

                if($sun_elevation < @$A["horizon"] + 5) $lf_minusE = 50; // Sonnenuntergang            
                if($sun_elevation < @$A["horizon"] ) $lf_minusE = 100; // Sonnenuntergang
                $lf_minusE = round($lf_minusE,1);
                $lf = $lf - $lf_minusE;

                
                
                // Bewölkung hängt von der Wolkendicke und von dem Einstrahlungswinkel ab.
                $lf_minusC = (pow($clouds,2.4)/600) * $A["cloudeffect"]/100;             
                #echo $clouds.": " .$lf_minusC."\n";
                $lf = $lf - $lf_minusC;
                #echo "Clouds $clouds >> $lf \n";
                $lf = ($lf < 0 )? 0 : $lf;                
                $pv_estimate = $A["kwp"] * ($lf / 100) * $A["efficiency"]/100;
            }
            
           // Temperaturverlust
           #$temp = 0;
           if($temp > 18){
               $tempDelta = $temp - 18;
               // Annahme MaxTemp = 50 bei 5 Grad Unterschied und keine Wolken
               $tempMinus = $A["tempkoeff"] * (( (2.917 * $temp) - 27.5) - 25 ) * (100 - $clouds) / 100;
               #echo "$hour: $tempMinus\n";
               $pv_estimate = $pv_estimate * (100-$tempMinus)/100;
           }


           $pv_estimate = round($pv_estimate,1);
           # echo "$hour: A: $sun_azimuth -$lf_minusA, E: $sun_elevation (Abw: $elev_abw) -$lf_minusE, Clouds: $clouds -$lf_minusC, PVE: $pv_estimate\n";
            $fc[$day][$hour] = [
                                "ts"             =>  $fcE["ts"],
                                "day"            =>  $day,
                                "hour"           =>  $hour,
                                "clouds"         =>  $clouds,
                                "temperature"    =>  $fcE["temperature"],
                                "precipitation"  =>  $fcE["precipitation"],
                                "visibility"     =>  $fcE["visibility"],
                                "pv_estimate"    =>  $pv_estimate,
                                ];        
        }
        #print_r($fc);
        //Morgen und Mittagswerte
        foreach($fc as $d => $day){
                $morgens = 0;
                $mittags = 0;
                foreach($day as $hour){
                    if($hour["hour"] <13 ){
                        $morgens += $hour["pv_estimate"];
                    }else{
                        $mittags += $hour["pv_estimate"];
                    }
                }
                $fc[$d]["morgens"] = $morgens * $A["efficiency"] / 100;
                $fc[$d]["mittags"] = $mittags * $A["efficiency"] / 100;
                $fc[$d]["gesamt"]  = ($morgens + $mittags)  * $A["efficiency"] / 100;
        }
        
        $this->fc = $fc;
        return $fc;
    }


    private function calcSun($ts, $dLongitude, $dLatitude){
        // Correction Timezone
        $ts = $ts - 2*3600;

        $iYear = date("Y", $ts);
        $iMonth = date("m", $ts);
        $iDay = date("d", $ts);
        $dHours = date("H", $ts);
        $dMinutes = date("i", $ts);
        $dSeconds = date("s", $ts);

        $pi = 3.14159265358979323846;
        $twopi = (2*$pi);
        $rad = ($pi/180);
        $dEarthMeanRadius = 6371.01;	// In km
        $dAstronomicalUnit = 149597890;	// In km

        // Calculate difference in days between the current Julian Day
        // and JD 2451545.0, which is noon 1 January 2000 Universal Time

        // Calculate time of the day in UT decimal hours
        $dDecimalHours = floatval($dHours) + (floatval($dMinutes) + floatval($dSeconds) / 60.0 ) / 60.0;
        

        // Calculate current Julian Day

        $iYfrom2000 = $iYear;//expects now as YY ;
        $iA= (14 - ($iMonth)) / 12;
        $iM= ($iMonth) + 12 * $iA -3;
        $liAux3=(153 * $iM + 2)/5;
        $liAux4= 365 * ($iYfrom2000 - $iA);
        $liAux5= ( $iYfrom2000 - $iA)/4;
        $dElapsedJulianDays= floatval(($iDay + $liAux3 + $liAux4 + $liAux5 + 59)+ -0.5 + $dDecimalHours/24.0);

        // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
        // ecliptic in radians but without limiting the angle to be less than 2*Pi
        // (i.e., the result may be greater than 2*Pi)

        $dOmega= 2.1429 - 0.0010394594 * $dElapsedJulianDays;
        $dMeanLongitude = 4.8950630 + 0.017202791698 * $dElapsedJulianDays; // Radians
        $dMeanAnomaly = 6.2400600 + 0.0172019699 * $dElapsedJulianDays;
        $dEclipticLongitude = $dMeanLongitude + 0.03341607 * sin( $dMeanAnomaly ) + 0.00034894 * sin( 2 * $dMeanAnomaly ) -0.0001134 -0.0000203 * sin($dOmega);
        $dEclipticObliquity = 0.4090928 - 6.2140e-9 * $dElapsedJulianDays +0.0000396 * cos($dOmega);

        // Calculate celestial coordinates ( right ascension and declination ) in radians
        // but without limiting the angle to be less than 2*Pi (i.e., the result may be
        // greater than 2*Pi)

        $dSin_EclipticLongitude = sin( $dEclipticLongitude );
        $dY1 = cos( $dEclipticObliquity ) * $dSin_EclipticLongitude;
        $dX1 = cos( $dEclipticLongitude );
        $dRightAscension = atan2( $dY1,$dX1 );
        if( $dRightAscension < 0.0 ) $dRightAscension = $dRightAscension + $twopi;
        $dDeclination = asin( sin( $dEclipticObliquity )* $dSin_EclipticLongitude );

        // Calculate local coordinates ( azimuth and zenith angle ) in degrees

        $dGreenwichMeanSiderealTime = 6.6974243242 +	0.0657098283 * $dElapsedJulianDays + $dDecimalHours;

        $dLocalMeanSiderealTime = ($dGreenwichMeanSiderealTime*15 + $dLongitude)* $rad;
        $dHourAngle = $dLocalMeanSiderealTime - $dRightAscension;
        $dLatitudeInRadians = $dLatitude * $rad;
        $dCos_Latitude = cos( $dLatitudeInRadians );
        $dSin_Latitude = sin( $dLatitudeInRadians );
        $dCos_HourAngle= cos( $dHourAngle );
        $dZenithAngle = (acos( $dCos_Latitude * $dCos_HourAngle * cos($dDeclination) + sin( $dDeclination )* $dSin_Latitude));
        $dY = -sin( $dHourAngle );
        $dX = tan( $dDeclination )* $dCos_Latitude - $dSin_Latitude * $dCos_HourAngle;
        $dAzimuth = atan2( $dY, $dX );
        if ( $dAzimuth < 0.0 )
            $dAzimuth = $dAzimuth + $twopi;
        $dAzimuth = $dAzimuth / $rad;
        // Parallax Correction
        $dParallax = ($dEarthMeanRadius / $dAstronomicalUnit) * sin( $dZenithAngle);
        $dZenithAngle = ($dZenithAngle + $dParallax) / $rad;
        $dElevation = 90 - $dZenithAngle;
            
        return Array("azimuth" => $dAzimuth, "elevation" => $dElevation);
    }


}


// Helper Funktion
function CreateVariableByName($id, $name, $type, $profile = "")
{
    # type: 0=boolean, 1 = integer, 2 = float, 3 = string;
    global $_IPS;
    $vid = @IPS_GetVariableIDByName($name, $id);
    if($vid === false)
    {
        $vid = IPS_CreateVariable($type);
        IPS_SetParent($vid, $id);
        IPS_SetName($vid, $name);
        IPS_SetInfo($vid, "this variable was created by script #".$_IPS['SELF']);
        if($profile !== "") { IPS_SetVariableCustomProfile($vid, $profile); }
    }
    return $vid;
}



Und hier habe ich mal einen Soll-IST Vergleich für mein Script:



Moin,

das ist wohl möglich.
Läuft auf jedenfall seit gestern Abend.

Hatte aber noch glaube ich einen kleinen Fehler gefunden für den Forcast mit Solcast.
Wenn man bei azimuth einen Wert eingibt wird es unten angepasst, sodass dieses dann auch wieder zu den Daten bei Solcast passt. Leider bei 0 Grad bleibt es 0 Grad, eigentlich sollte das bei mir dann -180 sein.

Als weiteres wäre interessant ob du dich schon mal mit der Optimierung via Solcast auseinander gesetzt hast.
Mein Kollege hast das ganze Via NoteRed gelöst und nun passen die Werte, sehr sehr gut zu seiner Anlage.

Gruß

Timo Feldker

Hallo
Ich habe meine Standortdaten eingegeben
Warum ist nur bei der Garage eine Verschattung drin, kann ich das einfach so kopieren?
Ich verstehe auch die Ausrichtung von Nord aus nicht, wenn die Anlage -10 Grad ausgerichtet ist, und der Baum steht von der anlge aus gesehen -20 Grad, dann lege ich den Schatten auf 150 Grad von Nord aus gesehen?

Und ich habe Fehlermeldungen.

Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 286
Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 286
Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 173
Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 173
Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 286
Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 286
Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 173
Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 173

Servus @berndh ,

wenn Du nur eine Anlage hast, kannst Du ein Array also ZB $PVA[„Dach“] Komplett löschen oder Auskommentieren. also so
/* $PVA[„DACH“]

]; */

Ich habe 2 Anlagen deshalb Dach und Garage. Beim Dach habe ich keine Verschattung drin.
Ausrichtung wie folgt:

PV Anlage hat - 30Grad Abweichung zu 0 (süd) (= azimut)
Das objekt befindet sich aus PV Anlagen sicht in … Grad Nord:
Hier beispiel

Hallo
Dann hatte ich mir das schon richtig überlegt.
Aber leider gibt es immer noch einige Fehlermeldungen.

Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 293

Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 293

Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 136

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 141

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 144

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 147

Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 293

Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 293

Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 180

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 180

Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 293

Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 293

Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 136

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 141

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 144

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 147

Notice:  Undefined property: stdClass::$forecasts in /var/lib/symcon/scripts/51293.ips.php on line 293

Warning:  Invalid argument supplied for foreach() in /var/lib/symcon/scripts/51293.ips.php on line 293

Notice:  Undefined offset: 0 in /var/lib/symcon/scripts/51293.ips.php on line 180

Notice:  Undefined offset: 1 in /var/lib/symcon/scripts/51293.ips.php on line 180

Einträge sind aktuell so

$PVA["DachSued"]  = [ "kwp"        => "3.7", 
                  "azimuth"    => -10,
                  "tilt"       => 10,
                  "efficiency" => 90,                  
                  "pvtype"     => "N",   // N=Normale Dachfläche D= PV in Dachform geständert, Ausrichtung der offenen seite = azimuth
                  "lon"        => "7.237692458510471",
                  "lat"        => "51.4470046794594",
                  "tempkoeff"  => 0.34,
                  "cloudeffect" => 90,   // Effekt für Leistungsreduktion bei Bewölkung
                  "horizon" => 15, // Horizont für Einfallswinkel Sonne (Horizont ca. 5 Grad, dach jedoch 15 etwas gedreht weniger)

                  // Beschattungsobjekt
                  "obj_direction" => 160,   // Himmelsrichtung des Beschattungsobjektes Grad von Norden =0
                  "obj_distance"  => 8,      // Abstand des Objektes in Meter
                  "obj_height"    => 20,      // Höhe des Objektes in Meter
                  "obj_size"      => 70,    // Prozentualer Abdeckungsanteil der PV Anlage durch Objekt (Mittelwert)
                  "obj_effect"    => 0.5    // Azuswirkung der Beschattung auf Ertrag (kwp mit gemessenem Ertrag bei Beschattung (grob))
                  ];

$PVA["DachWest"] = [ "kwp"        => "3.7", 
                  "azimuth"    => 80,
                  "tilt"       => 10,
                  "efficiency" => 90,                  
                  "pvtype"     => "N",   // N=Normale Dachfläche D= PV in Dachform geständert, Ausrichtung der offenen seite = azimuth
                  "lon"        => "7.237692458510471",
                  "lat"        => "51.4470046794594",
                  "tempkoeff"  => 0.34,
                  "cloudeffect" => 90,   // Effekt für Leistungsreduktion bei Bewölkung
                  "horizon" => 15, // Horizont für Einfallswinkel Sonne (Horizont ca. 5 Grad, dach jedoch 15 etwas gedreht weniger)
                  
                  // Beschattungsobjekt
                  "obj_direction" => 160,   // Himmelsrichtung des Beschattungsobjektes Grad von Norden =0
                  "obj_distance"  => 8,      // Abstand des Objektes in Meter
                  "obj_height"    => 20,      // Höhe des Objektes in Meter
                  "obj_size"      => 70,    // Prozentualer Abdeckungsanteil der PV Anlage durch Objekt (Mittelwert)
                  "obj_effect"    => 0.5    // Azuswirkung der Beschattung auf Ertrag (kwp mit gemessenem Ertrag bei Beschattung (grob))
                  ];

Dach ist ein Zeltdach Süd und West belegt, siehe Avatar.

habs gefunden:
Setze mal den Parameter:
$HTML_COMPARE = false;

Problem ist, dass Du die Funktion zum Vergleich von mehreren Vorhersagemodellen aktiv ist, Du aber keinen Key von Solcast etc. eingetragen hast.

Übrigens bin ich grad am Testen eines komplett neuen Ansatzes.
Machine Learning - Künstliche Intelligenz :smiley:

Und zwar lernt IPS anhand Sonnenstand, und Globalstrahlung (vom DWD) deinen PV Ertrag vorherzusagen.
Bin grad am ausprobieren, wie lange das Modell einlernzeit benötigt, ich glaube aber, dass man schon sehr gut in 2 Tagen da steht.

1 „Gefällt mir“

Hallo,
ich hatte auch die Fehlermeldung… funktioniert nun.
Danke.

Grüße
Björn

Ciao Stele99

Das finde ich ein gaaaaaanz cooler Ansatz. Da bin nun gespannt was wir noch von dir lesen werden.

Viele Grüsse
Roberto