Hallo,
das Warten hat ein Ende - die Vorgeschichte zum Script kann man hier nachlesen => Abfrage Solarprognose!
Ich mache hier nur ein neuen Thread auf um das Script besser supporten zu können.
Wie im anderen Thread schon gesagt, das Script ist nicht im Stil „fire & forget“, sondern man muss noch paar Sachen anpassen bzw. konfigurieren.
Grob sind das folgende Dinge:
- API Key auf solarprognose.de beantragen und bekommen
- PV Anlage dort entsprechend konfigurieren
- API-Daten im Script entsprechend eintragen
- Script einmal in der Konsole ausführen
- Archivierung (siehe Script) für den Tageswert einschalten und auf Zähler setzen
- Timer für stündliches und tägliches Ereignis einrichten
- Webfront den eigenen Bedürfnissen zusammenbauen
HINWEIS/VORRAUSSETZUNG:
- Meine globale Script-Bibliothek wurde installiert
- Das Quickchart-Skript wurde installiert
- Das Script nutzt meinen WwxSkin
- Das Script nutzt nur die „freie Version“ von solarprognose.de, also 1 Tag in die Zukunft
Von der Objektstruktur sollte es dann so aussehen:
Das UpdateHourly Ereignis sieht so aus:
Und das Script kommt jetzt:
<?php
declare(strict_types=1);
################################################################################
# Script: Ammount.SolarForcast.ips.php
# Version: 1.1.20230223
# 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' den eigenen Gegebenheiten anpassen
# - 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)
#
# ------------------------------ Konfiguration ---------------------------------
#
# Global Debug Output Flag
$DEBUG = false;
#
# Solar Prognose API Parameter
$SP_TOKEN = '<API-KEY hier zwischen den Hochkommas reinkopieren>';
$SP_ITEM = 'location';
$SP_PROJECT = '<API-MAILADRESSE hier zwischen den Hochkommas reinkopieren>';
$SP_FORMAT = 'json';
$SP_TYPE = 'hourly'; // 'daily';
$SP_ID = <<LOCATION-ID hier reinkopieren>;
$SP_START = 0;
$SP_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') {
$vid = CreateVariableByName($_IPS['SELF'], 'Vorhersage', 3, 0, 'Graph', '~HTMLBox');
$vid = CreateVariableByName($_IPS['SELF'], 'Tagesprognose', 2, 1, '', '~Electricity'); // TODO: Archivierung aktivieren (Typ: Zähler)
$vid = CreateVariableByName($_IPS['SELF'], 'Stundenprognose', 2, 2, '', '~Electricity');
$vid = CreateVariableByName($_IPS['SELF'], 'Aktuelle Leistung', 3, 3, 'EnergyProduction', '~HTMLBox');
}
// 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') {
// Mitternacht - Reset auf 0
$vid = CreateVariableByName($_IPS['SELF'], 'Tagesprognose', 2);
SetValue($vid, 0);
$vid = CreateVariableByName($_IPS['SELF'], 'Stundenprognose', 2);
SetValue($vid, 0);
} elseif ($event == 'UpdateHourly') {
// von 05:00 bis 21:00 - TODO: Timer im Sommer vielleicht anpassen
$data = UpdateForecast($SP_TOKEN, $SP_PROJECT, $SP_ITEM, $SP_ID, $SP_TYPE, $SP_FORMAT, $SP_START, $SP_END);
// aktuellen Werte abgleichen wenn notwendig
$vid = CreateVariableByName($_IPS['SELF'], 'Tagesprognose', 2);
$lv = GetValue($vid);
if ($lv < $data['Tageswert']) {
SetValue($vid, $data['Tageswert']);
} elseif ($lv > $data['Tageswert']) {
//Den letzten Wert, der in der Datenbank gespeichert wurde, holen
$last = AC_GetLoggedValues(38732, $vid, 0, 0, 1)[0];
AC_DeleteVariableData(38732, $vid, $last['TimeStamp'], 0);
SetValue($vid, $data['Tageswert']);
}
$vid = CreateVariableByName($_IPS['SELF'], 'Stundenprognose', 2);
SetValue($vid, $data['Stundenwert']);
// SVG Chart
$vid = CreateVariableByName($_IPS['SELF'], 'Aktuelle Leistung', 3);
$svg = DrawChart($data['Stundenwert']);
$svg = str_replace(['220pt', '120pt'], '100%', $svg);
SetValue($vid, $svg);
// HTML Table
$html = BuildHtml($data);
$vid = CreateVariableByName($_IPS['SELF'], 'Vorhersage', 3);
SetValue($vid, $html);
}
}
#----------------------------------- Functions ---------------------------------
function UpdateForecast($token, $project, $item, $id, $type, $format, $start, $end, $day = null)
{
$url = "https://www.solarprognose.de/web/solarprediction/api/v1?access-token=$token&project=$project&item=$item&id=$id&type=$type&_format=$format&algorithm=own-v1&start_day=$start&end_day=$end";
//EchoDebug('URL: ', $url);
$json = file_get_contents($url);
//EchoDebug('Daten :', $json);
$result = [];
if ($json !== false) {
$data = json_decode($json, true);
// aktueller Tag und aktuelle Stunde
$ad = date('d.m.Y');
$at = date('H') . ':00';
$result['Tageswert'] = 0;
$result['Stundenwert'] = 0;
// Stundenwerte
foreach ($data['data'] as $key => $values) {
// Tag
$dd = date('d.m.Y', $key);
// Uhrzeit
$dt = date('H:i', $key);
// Tageswert hochzählen
if ($ad == $dd) {
$result['Tageswert'] += $values[0];
}
if (($ad == $dd) && ($at == $dt)) {
$result['Stundenwert'] = $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)
{
unset($data['Tageswert']);
unset($data['Stundenwert']);
// 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>∑ 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($value)
{
$int = intval($value * 1000);
// new chart object
$chart = new QuickChart(['width' => 220, 'height' => 120, 'format' => 'svg']);
// chart config
$chart->setConfig("{
type: 'gauge',
data: {
datasets: [
{
data: [2500, 5000, 7500],
value: $int,
minValue: 0,
backgroundColor: ['red', 'orange', 'green'],
borderWidth: 1,
},
],
},
options: {
legend: {
display: false,
},
title: {
display: false,
text: 'Aktuelle Leistung',
position: 'bottom',
},
needle: {
radiusPercentage: 0,
widthPercentage: 2,
lengthPercentage: 40,
color: '#c0c0c0',
},
valueLabel: {
fontSize: 8,
backgroundColor: 'transparent',
color: '#fff',
formatter: function (value, context) {
return value.toLocaleString('de-DE') + ' kW';
},
bottomMarginPercentage: 10,
},
plugins: {
datalabels: {
display: 'auto',
formatter: function (value, context) {
return context.chart.data.labels[context.dataIndex/100];
},
color: '#fff',
font: {
weight: 'bold',
size: 6,
}
},
},
},
}");
return $chart->toBinary();
}
################################################################################
Viel Erfolg
Heiko