no message
This commit is contained in:
@@ -3,7 +3,10 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>PV_Forecast</title>
|
<title>PV_Forecast</title>
|
||||||
|
|
||||||
|
<!-- Externes Script: kann je nach CSP/Mixed-Content blockiert sein -->
|
||||||
<script src="https://code.highcharts.com/highcharts.js"></script>
|
<script src="https://code.highcharts.com/highcharts.js"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body { font-family: sans-serif; margin: 0; padding: 12px; }
|
body { font-family: sans-serif; margin: 0; padding: 12px; }
|
||||||
#chart { height: 420px; width: 100%; }
|
#chart { height: 420px; width: 100%; }
|
||||||
@@ -21,14 +24,36 @@
|
|||||||
<div id="chart"></div>
|
<div id="chart"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const instanceId = {INSTANCE_ID};
|
const metaEl = document.getElementById("meta");
|
||||||
const endpoint = `/hook/solcastcompare?instance=${instanceId}&action=data`;
|
|
||||||
|
// JS-Fehler sichtbar machen (sonst: schwarze Seite, keine Ahnung warum)
|
||||||
|
window.onerror = function (msg, url, line, col) {
|
||||||
|
metaEl.textContent = `JS-Fehler: ${msg} (${line}:${col})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Symcon ersetzt {{INSTANCE_ID}} mit einer ZAHL (z.B. 12345)
|
||||||
|
const instanceId = Number("{{INSTANCE_ID}}");
|
||||||
|
|
||||||
|
|
||||||
|
if (!Number.isFinite(instanceId) || instanceId <= 0) {
|
||||||
|
metaEl.textContent = "Fehler: INSTANCE_ID wurde nicht korrekt eingesetzt.";
|
||||||
|
throw new Error("Invalid INSTANCE_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Absoluter Endpoint (robuster als nur /hook/..., vor allem bei Proxies)
|
||||||
|
const endpoint =
|
||||||
|
`${location.protocol}//${location.host}` +
|
||||||
|
`/hook/solcastcompare?instance=${instanceId}&action=data`;
|
||||||
|
|
||||||
let chart;
|
let chart;
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
|
metaEl.textContent = "Lade Daten…";
|
||||||
const r = await fetch(endpoint, { cache: "no-store" });
|
const r = await fetch(endpoint, { cache: "no-store" });
|
||||||
if (!r.ok) throw new Error("HTTP " + r.status);
|
if (!r.ok) {
|
||||||
|
const text = await r.text().catch(() => "");
|
||||||
|
throw new Error(`HTTP ${r.status} ${text ? "- " + text : ""}`.trim());
|
||||||
|
}
|
||||||
return await r.json();
|
return await r.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +62,16 @@
|
|||||||
? new Date(data.meta.forecast_cached_at * 1000).toLocaleString()
|
? new Date(data.meta.forecast_cached_at * 1000).toLocaleString()
|
||||||
: "unbekannt";
|
: "unbekannt";
|
||||||
|
|
||||||
document.getElementById("meta").textContent = `Forecast Cache: ${cachedAt}`;
|
|
||||||
|
|
||||||
const forecast = data?.series?.forecast ?? [];
|
const forecast = data?.series?.forecast ?? [];
|
||||||
const actual = data?.series?.actual ?? [];
|
const actual = data?.series?.actual ?? [];
|
||||||
|
|
||||||
|
metaEl.textContent = `Forecast Cache: ${cachedAt} | Forecast: ${forecast.length} | Ist: ${actual.length}`;
|
||||||
|
|
||||||
|
if (typeof Highcharts === "undefined") {
|
||||||
|
metaEl.textContent = "Fehler: Highcharts konnte nicht geladen werden (CSP/Mixed Content/CDN).";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!chart) {
|
if (!chart) {
|
||||||
chart = Highcharts.chart("chart", {
|
chart = Highcharts.chart("chart", {
|
||||||
title: { text: "PV: Erwartung vs. Tatsächlich" },
|
title: { text: "PV: Erwartung vs. Tatsächlich" },
|
||||||
@@ -66,7 +96,7 @@
|
|||||||
const data = await loadData();
|
const data = await loadData();
|
||||||
render(data);
|
render(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
document.getElementById("meta").textContent = "Fehler beim Laden: " + e.message;
|
metaEl.textContent = "Fehler beim Laden: " + (e?.message ?? e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ class PV_Forecast extends IPSModule
|
|||||||
|
|
||||||
$mins = max(1, (int)$this->ReadPropertyInteger("RefreshMinutes"));
|
$mins = max(1, (int)$this->ReadPropertyInteger("RefreshMinutes"));
|
||||||
$this->SetTimerInterval("UpdateForecastTimer", $mins * 60 * 1000);
|
$this->SetTimerInterval("UpdateForecastTimer", $mins * 60 * 1000);
|
||||||
|
|
||||||
|
// Hook registrieren (hier ist es zuverlässig)
|
||||||
|
$this->RegisterHook("/hook/solcastcompare");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function RequestAction($Ident, $Value)
|
public function RequestAction($Ident, $Value)
|
||||||
|
|||||||
Reference in New Issue
Block a user