[Script] solarprognose.de (Full version)

Finde ihn speziell bei wechselhaften Wetter extrem, aber auch heute ist der Unterschied riesig:

Solarprognose.de => 51 kWh
SolCast.com => 36 kWh

Das ist schon ein großer Unterschied. Wenn man annimmt das heute so wie gestern wird, da hatte ich real 41 kWh dann liegt solcast schon recht gut!

Parsen warum nicht - ist immer ne frage ob man auf die Seite relativ „einfach“ kommt (Thema: Authentifizierung).

Gruß Heiko

Wie der Name schon sagt - Skriptbibliothek - keine Modul :slight_smile: Alles richtig gelesen?

Gruß Heiko

Ja, vor ein paar Tagen hatte ich mir das mal durchgelesen. Anscheinend aber nicht gemerkt :roll_eyes:

Aber ich lese halt auch viel den ganzen Tag…#

Ok, man braucht ein Login :slight_smile:
Ich werde mir dann das Solcast ansehen. Danke Pitti

Hallo Heiko,
habe auch dein aktuelles Skript am laufen mit dem Update vom v2.2.2024080. Wenn ich das Skript ausführe ist alles gut und nach einer Zeit bekomme ich immer ein Ausrufezeichen vor das Skript.

Die Variablen der Kategorie „Haus“ werden auch nicht befüllt. Bei der anlagen ID habe ich schon die ID des Standortes und die ID der Anlage eingefügt im Skript, beides ohne Erfolg.

Das Skript das ich nutze:

<?php

declare(strict_types=1);

################################################################################
# Script:   Amount.SolarForcast.ips.php
# Version:  2.2.20230326 / Update v2.2.20240801
# Author:   Heiko Wilknitz (@Pitti)
#
# Script zur Abholung und Aufbereitung der prognostizierten Solorproduktion
# von solarprognose.de.
#
# API
#   https://www.solarprognose.de/web/solarprediction/api/v1
#       ?access-token=ACCESS-TOKEN
#       &project=Hier Ihre Projekt-Website oder Ihre Kontakt-E-Mail
#       &item=ITEM
#       &id=ID
#       &type=hourly|daily
#       &_format=json|xml
#       &algorithm=mosmix|own-v1|clearsky
#       &day=DAY
#       &start_epoch_time=START_EPOCH_TIME&end_epoch_time=END_EPOCH_TIME
#       &start_day=START_DAY&end_day=END_DAY
#       &snomminixml=true # für snom VoIP Telefone
#
# ------------------------------ Installation ----------------------------------
#
# Dieses Skript richtet automatisch alle nötigen Objekte bei manueller
# Ausführung ein. Eine weitere manuelle Ausführung setzt alle benötigten Objekte
# wieder auf den Ausgangszustand.
#
# - Neues Skript erstellen
# - Diesen PHP-Code hineinkopieren
# - Abschnitt 'Konfiguration' mit eigenen Werten anpassen (__WWX austauschen)
# - Skript Abspeichern
# - Skript Ausführen
# - Visualisierung per Link auf entstandene Variablen erstellen
#
# ------------------------------ Changelog -------------------------------------
#
# 08.02.2023 - Initalversion (v1.0)
# 23.02.2023 - API Doc, Type fixes (v1.1)
# 15.03.2023 - Umstellung bzw. Erweiterung für mehrere Anlagen
#              und All-In-One Script (v2.0)
# 17.03.2023 - Fix für Archive Control (v2.1)
# 26.03.2023 - Fix Style & Logging (v2.2)
# 04.03.2024 - Fix für Archivdaten (v2.3)
#
# ------------------------------ Konfiguration ---------------------------------
#
# Global Debug Output Flag
$DEBUG = false;
#
# Globale Variable __WWX als Array via define() in __autoload definiert!!!
#
# Erste Anlage
$PVA['Haus'] = [
    'token'     => ['xxxxxxxxxxxxxxxxxxxx'],  // (string) erstezen durch => '<api-token>'
    'project'   => ['xxxxxxxxxxxxxx'],   // (string) erstezen durch => '<mail-adresse>'
    'id'        => ['xxxx'],     // (int) erstezen durch => <anlagen-id>
    'item'      => 'location',
    'format'    => 'json',
    'type'      => 'hourly', // 'daily';
    'start'     => 0,
    'end'       => 1,
];
#
# Weitere Anlage
# $PVA['Haus'] = [
#    'token'     => __WWX['SPD_TOKEN'],
#    'project'   => __WWX['SPD_MAIL'],
#    'id'        => __WWX['SPD_ID2'],
#    'item'      => 'location',
#    'format'    => 'json',
#    'type'      => 'daily';
#    'start'     => 0,
#    'end'       => 1,
# ];
#
################################################################################
#
# Requires include of the global function script via autoload (__autoload.php)
# or direct in the script (uncomment next line)!
require_once(IPS_GetKernelDir()."scripts".DIRECTORY_SEPARATOR.'System.Functions.ips.php');
# You can download it from here https://github.com/wilkware/ips-scripts
#
defined('WWX_FUNCTIONS') || die('Global function library not available!');

require_once IPS_GetKernelDir() . 'scripts' . DIRECTORY_SEPARATOR . 'System.QuickChart.ips.php';

// INSTALLATION
if ($_IPS['SENDER'] == 'Execute') {
    // Event 1 mal am Tag
    $midnight = mktime(0, 0, 15);
    CreateEventByName($_IPS['SELF'], 'UpdateDaily', $midnight);
    // Event aller 1 Stunde von  05:00 bis 18:00 Uhr - TODO: Timer im Sommer vielleicht anpassen
    $from = mktime(5, 0, 15);
    $to = mktime(18, 0, 15);
    CreateEventByNameFromTo($_IPS['SELF'], 'UpdateHourly', 3, 1, $from, $to);
    // Variablen pro Anlage anlegen
    foreach ($PVA as $name => $plant) {
        // Kategorie erzeugen
        $cid = CreateCategoryByName($_IPS['SELF'], $name);
        $vid = CreateVariableByName($cid, 'Daten', 3);
        $vid = CreateVariableByName($cid, 'Tabellarischer Verlauf', 3, 10, 'Database', '~HTMLBox');
        $vid = CreateVariableByName($cid, 'Graphischer Verlauf', 3, 11, 'Graph', '~HTMLBox');
        $vid = CreateVariableByName($cid, 'Prognose Heute', 2, 20, '', '~Electricity');
        // Archivierung aktivieren (Typ: Zähler)
        RegisterArchive($vid, false);
        $vid = CreateVariableByName($cid, 'Prognose Morgen', 2, 21, '', '~Electricity');
        $vid = CreateVariableByName($cid, 'Aktuelle Stunde', 2, 22, '', '~Electricity');
    }
}
// WEBFRONT
elseif ($_IPS['SENDER'] == 'WebFront') {
    // Benutzer hat etwas geändert!
}
// VARIABLENAENDERUNG
elseif ($_IPS['SENDER'] == 'Variable') {
    // Varaible hat sich geändert!
}
// TIMER EVENT
elseif ($_IPS['SENDER'] == 'TimerEvent') {
    $event = IPS_GetName($_IPS['EVENT']);
    if ($event == 'UpdateDaily') {
        foreach ($PVA as $name => $plant) {
            // Kategorie erzeugen oder lesen
            $cid = CreateCategoryByName($_IPS['SELF'], $name);
            // Mitternacht - Reset auf 0
            $vid = CreateVariableByName($cid, 'Prognose Heute', 2);
            SetValueFloat($vid, 0);
            $vid = CreateVariableByName($cid, 'Prognose Morgen', 2);
            SetValueFloat($vid, 0);
            $vid = CreateVariableByName($cid, 'Aktuelle Stunde', 2);
            SetValueFloat($vid, 0);
        }
    } elseif ($event == 'UpdateHourly') {
        foreach ($PVA as $name => $plant) {
            // Kategorie erzeugen oder lesen
            $cid = CreateCategoryByName($_IPS['SELF'], $name);
            // von 08:00 bis 18:00 - TODO: Timer im Sommer vielleicht anpassen
            $data = UpdateForecast($plant);
            // Save
            $vid = CreateVariableByName($cid, 'Daten', 3);
            $json = json_encode($data);
            SetValueString($vid, $json);
            // aktuellen Werte abgleichen wenn notwendig
            $vid = CreateVariableByName($cid, 'Prognose Heute', 2);
            if ($data['Heute'] > 0) {
                $lv = GetValueFloat($vid);
                if ($lv < $data['Heute']) {
                    SetValueFloat($vid, $data['Heute']);
                } elseif ($lv == $data['Heute']) {
                    // Do nothing
                } else {
                    //Den letzten Wert, der in der Datenbank gespeichert wurde, holen
                    $aid = IPS_GetInstanceListByModuleID(ExtractGuid('Archive Control'))[0];
                    $last = AC_GetLoggedValues($aid, $vid, 0, 0, 1)[0];
                    AC_DeleteVariableData($aid, $vid, $last['TimeStamp'], 0);
                    SetValueFloat($vid, $data['Heute']);
                    IPS_Sleep(1000);
                    AC_ReAggregateVariable($aid, $vid);
                }
            }
            unset($data['Heute']);
            $vid = CreateVariableByName($cid, 'Prognose Morgen', 2);
            SetValueFloat($vid, $data['Morgen']);
            unset($data['Morgen']);
            $vid = CreateVariableByName($cid, 'Aktuelle Stunde', 2);
            SetValueFloat($vid, $data['Stunde']);
            unset($data['Stunde']);
            // SVG Chart
            $svg = DrawChart($data);
            $svg = str_replace(['1024pt', '325pt'], '100%', $svg);
            $vid = CreateVariableByName($cid, 'Graphischer Verlauf', 3);
            SetValueString($vid, $svg);
            // HTML Table
            $html = BuildHtml($data);
            $vid = CreateVariableByName($cid, 'Tabellarischer Verlauf', 3);
            SetValueString($vid, $html);
        }
    }
}

#----------------------------------- Functions ---------------------------------

function UpdateForecast($plant)
{
    $url = 'https://www.solarprognose.de/web/solarprediction/api/v1?access-token=' .
        $plant['token'] . '&project=' .
        $plant['project'] . '&item=' .
        $plant['item'] . '&id=' .
        $plant['id'] . '&type=' .
        $plant['type'] . '&_format=' .
        $plant['format'] . '&algorithm=own-v1&start_day=' .
        $plant['start'] . '&end_day=' .
        $plant['end'];
    //EchoDebug('URL: ', $url);
    $json = file_get_contents($url);
    //EchoDebug('Daten :', $json);
    $result = [];
    if ($json !== false) {
        $data = json_decode($json, true);
        // Heute, Morgen und aktuelle Stunde
        $ad = date('d.m.Y');
        $at = date('H') . ':00';
        $result['Heute'] = 0;
        $result['Morgen'] = 0;
        $result['Stunde'] = 0;
        // Stundenwerte
        foreach ($data['data'] as $key => $values) {
            // Tag
            $dd = date('d.m.Y', $key);
            // Uhrzeit
            $dt = date('H:i', $key);
            // Werte hochzählen
            if ($ad == $dd) { // Heute
                $result['Heute'] += $values[0];
            } else { // Morgen
                $result['Morgen'] += $values[0];
            }
            if (($ad == $dd) && ($at == $dt)) {
                $result['Stunde'] = $values[0];
            }
            // Pro Tag ein Feld
            if (!isset($result[$ad])) {
                $result[$ad] = [];
            }
            // Stundenwerte und akkumulierten Werte
            $result[$dd][$dt] = $values;
        }
    }
    return $result;
}

function BuildHtml($data)
{
    // Rows
    $rows = array_keys($data);
    // cols
    $cols = max(count($data[$rows[0]]), count($data[$rows[1]]));
    // html
    $html = '';
    $html .= '<table class="wwx">';
    foreach ($data as $day => $hours) {
        $count = 0;
        $th = '<thead class="orange"><th><center>' . $day . '</center></th>';
        $tr1 = '<tr><td>kW/h</td>';
        $tr2 = '<tr><td>&sum; kWh</td>';
        foreach ($hours as $hour => $values) {
            $th .= '<th>' . $hour . '</th>';
            $tr1 .= '<td>' . $values[0] . '</td>';
            $tr2 .= '<td>' . $values[1] . '</td>';
            $count++;
        }
        for ($i = $count; $i < $cols; $i++) {
            $th .= '<th>-</th>';
            $tr1 .= '<td>-</td>';
            $tr2 .= '<td>-</td>';
        }
        $html .= $th . '</thead>';
        $html .= $tr1 . '</tr>';
        $html .= $tr2 . '</tr>';
    }
    $html .= '</table>';
    return $html;
}

function DrawChart($data)
{
    $axis_x = [];
    $axis_y = [];
    // prepeare dataset
    foreach ($data as $day => $hours) {
        foreach ($hours as $hour => $values) {
            $axis_x[] = '\'' . $hour . '\'';
            $axis_y[] = intval($values[0] * 1000);
        }
    }
    // new chart object
    $chart = new QuickChart(['width' => 1024, 'height' => 325, 'format' => 'svg']);
    // chart config
    $chart->setConfig("{
    type: 'line',
    data: {
        labels: [" . implode(',', $axis_x) . "],
        datasets: [
        {
            backgroundColor: 'rgba(255, 125, 0, 0.1)',
            borderColor: 'rgb(255, 125, 0)',
            borderWidth: 1,
            lineTension: 0.4,
            pointRadius: 1,
            fill: true,
            data: [" . implode(',', $axis_y) . "]
        }]
    },
    options: {
        legend: {
            labels: {
                fontColor: 'rgb(255, 255, 255)'
            },
            display: false
        },
        scales: {
        xAxes: [{
            ticks: {
                fontColor: '#fff',
            },
            gridLines: {
                color: 'rgba(211, 211, 211, 0.2)',
                borderDash: [5,5]
            },
            scaleLabel: {
            fontColor: '#fff',
            display: false,
            labelString: 'Uhrzeit'
            }
        }],
        yAxes: [{
            ticks: {
                fontColor: '#fff'
            },
            gridLines: {
                color: 'rgba(211, 211, 211, 0.2)',
                borderDash: [5,5]
            },
            scaleLabel: {
            fontColor: '#fff',
            display: true,
            labelString: 'Leistung (kW)'
            }
        }]
        }
    }
    }");
    return $chart->toBinary();
}

################################################################################

Hast du eine Idee woran das liegen kann?

VG
Stefan

Hi Stefan,

Setzt doch mal Debug auf true und lass Dir mal die URL ausgeben (EchoDebug auskommentieren) und dann die URL direkt im Browser aufrufen und schauen was passiert.

Gruß Heiko

Wenn ich die URL im Browser eingebe mit meinem Token bekomme ich eine XML angezeigt, richtig?

Hallo Heiko,
hast du das Skript noch in Benutzung?

LG
Stefan

Eigentlich sollte da ein JSON zurück kommen.

Nein, es läuft glaube noch bei mir, aber bin von der Anzeige auf solcast umgestiegen. Einfach bessere Werte.

Bin gerade auf Messe, deshalb etwas langsam im Antworten

Ok, bei SolCast habe ich das gleiche Problem. Es kommen keine Werte rein.

Das komische ist von Solarprognose habe ich noch ein anderes Skript am laufen von @hfichtinger und das funktioniert. Dann kann es schon mal am API Schlüssel nicht liegen.

Dann noch viel Spaß auf der Messe.

LG

1 „Gefällt mir“

Ich verstehe es nicht, habe jetzt bestimmt schon gefühlte 100x die Skripte durchgeschaut, finde keine Fehler mit meinen Angaben. Bei SolCast gibt man ja nur den API Token ein und die RID.

Ich schau mir das morgen mal an, bin leider noch auf der Rückreise von der DMEXCO

1 „Gefällt mir“