Solar: Anlage-Ansicht neu, im Stil der Energiefluss-Uebersicht

Der alte Plan (pvplan.svg) ist ersetzt durch einen Katalog der Anlage
(js/solar/anlageKatalog.js: Flaechen, Wechselrichter, echte Lage jeder
Platte) und einen Renderer (js/solar/anlage.js):

- Flaechen mit Leistung und Anteil als Balken
- Lageplan: Farbe stufenlos nach Leistung im Vergleich zu den staerksten
  Platten der Flaeche, Warnzeichen nur bei genug Licht unter 70 % des
  Medians, "ohne Daten" wenn der Wechselrichter nichts meldet;
  Auftritt, Lichtwelle bei Sonne, pulsierende Warnung; hochkant gedreht
  auf schmalen Schirmen
- Detail zu Platte, String oder Wechselrichter (Eingaenge als Balken,
  Auslastung, Temperatur), Verlauf je Platte ab Seitenaufruf
- Wechselrichterliste mit Zustand ok / hochgerechnet / keine Daten

Die Flaechen im Sonnenring der Uebersicht kommen jetzt aus demselben
Katalog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 17:56:37 +02:00
co-authored by Claude Opus 5
parent a59277e33e
commit de2892f7a7
9 changed files with 834 additions and 230 deletions
+81
View File
@@ -0,0 +1,81 @@
/* ==========================================================================
Katalog der Anlage-Ansicht (Solar-Seite, Karte "Realtime" -> "Anlage").
Beschreibt die PV-Anlage dieses Hauses: Flächen, Wechselrichter und jede
Platte mit ihrer tatsächlichen Lage. Gezeichnet wird er von
js/solar/anlage.js, ohne dass der Renderer eine Fläche beim Namen kennt.
Die Lagen stammen aus dem früheren Plan in realtime.svg (Einheiten wie
dort, Platte 70 x 40, Zeichenfläche etwa 1250 x 740).
Die Leistung kommt aus solarManager/P_PVn - ein Eintrag je Eingang, in der
Reihenfolge von solarManager.py -, der Zustand der Geräte aus
solarManager/invertersN/... .
flaechen [{id, name, farbe, umriss: "x,y x,y ..." | {x,y,w,h}}]
wechselrichter[{nr, name, modell, eingaenge: [P_PVn-Index, ...]}]
nr = N in solarManager/invertersN
strings Platten ohne eigenen Messwert (in Reihe am Gen24):
[{id, name, flaeche, eingang, farbe, platten: [[x,y,w,h], ...]}]
platten [{eingang, flaeche, nr?, x, y, w, h}] - w/h ohne Angabe 70/40;
nr ist die Beschriftung (#14), sonst "Eingang n"
nord {x, y, winkel} für den Nordpfeil
========================================================================== */
const ANLAGE_KATALOG = (function () {
"use strict";
// Dach, String A: vier Spalten stehend, darunter liegend, rechts stehend.
const dachA = [];
[600, 640, 680].forEach(x => [80, 150, 220, 290].forEach(y => dachA.push([x - 40, y, 40, 70])));
[80, 150, 220].forEach(y => dachA.push([680, y, 40, 70]));
[[790, 290], [720, 330], [790, 330], [870, 290], [870, 330], [940, 330]].forEach(([x, y]) => dachA.push([x, y, 70, 40]));
[1160, 1120, 1080].forEach(x => dachA.push([x - 40, 300, 40, 70]));
// Dach, String B: drei Reihen stehend, etwas breitere Platten.
const dachB = [[1160, 200], [1115, 200], [1070, 200], [1160, 130], [1115, 130], [1070, 130], [1025, 130],
[1160, 60], [1115, 60], [1070, 60]].map(([x, y]) => [x - 45, y, 45, 70]);
const stehend = (eingang, x, y) => ({ eingang, flaeche: "veranda", x, y, w: 40, h: 70 });
const carport = (eingang, nr, x, y) => ({ eingang, flaeche: "carport", nr, x, y });
return {
flaechen: [
{ id: "dach", name: "Dach", farbe: "#f7c000",
umriss: ["560,80 720,80 720,300 1160,300 1160,370 560,370", "980,60 1160,60 1160,265 980,265"] },
{ id: "veranda", name: "Veranda", farbe: "#f78d00", umriss: { x: 385, y: 35, w: 300, h: 520 } },
{ id: "carport", name: "Carport", farbe: "#f75a1e", umriss: { x: 85, y: 495, w: 380, h: 240 } },
],
wechselrichter: [
{ nr: 0, name: "Gen24", modell: "Fronius Symo Gen24", eingaenge: [0, 1] },
{ nr: 1, name: "Veranda UG2", modell: "Hoymiles (DTU-BI)", eingaenge: [2, 3] },
{ nr: 2, name: "Veranda UG/OG1", modell: "Hoymiles, 4 Eingänge", eingaenge: [4, 5, 6, 7] },
{ nr: 3, name: "Veranda OG24", modell: "Hoymiles, 6 Eingänge", eingaenge: [8, 9, 10, 11, 12, 13] },
{ nr: 4, name: "Carport 16", modell: "Hoymiles HMS-2250-6T", eingaenge: [14, 15, 16, 17, 18, 19] },
{ nr: 5, name: "Carport 712", modell: "Hoymiles HMS-2250-6T", eingaenge: [20, 21, 22, 23, 24, 25] },
{ nr: 6, name: "Carport 1316", modell: "Hoymiles HMS-1800-4T", eingaenge: [26, 27, 28, 29] },
{ nr: 7, name: "Carport 1720", modell: "Hoymiles HMS-1600-4T", eingaenge: [30, 31, 32, 33] },
],
strings: [
{ id: "A", name: "String A", flaeche: "dach", eingang: 0, farbe: "#f7c000", platten: dachA, schild: [640, 222] },
{ id: "B", name: "String B", flaeche: "dach", eingang: 1, farbe: "#f7a000", platten: dachB, schild: [1070, 168] },
],
platten: [
stehend(7, 400, 50), stehend(6, 400, 120), stehend(3, 400, 200), stehend(2, 400, 270),
stehend(5, 460, 50), stehend(4, 460, 120), stehend(9, 460, 200), stehend(8, 460, 270),
stehend(11, 460, 350), stehend(10, 460, 420),
{ eingang: 12, flaeche: "veranda", x: 500, y: 500 }, { eingang: 13, flaeche: "veranda", x: 600, y: 500 },
carport(14, 1, 100, 510), carport(15, 2, 100, 550), carport(16, 3, 100, 590), carport(17, 4, 100, 630),
carport(21, 7, 170, 550), carport(20, 8, 170, 510), carport(19, 6, 170, 590), carport(18, 5, 170, 630),
carport(25, 12, 240, 510), carport(24, 11, 240, 550), carport(23, 10, 240, 590), carport(22, 9, 240, 630),
carport(29, 16, 310, 510), carport(28, 15, 310, 550), carport(27, 14, 310, 590), carport(26, 13, 310, 630),
carport(32, 19, 380, 550), carport(31, 18, 380, 590), carport(30, 17, 380, 630),
carport(33, 20, 200, 680),
],
nord: { x: 1235, y: 45, winkel: 10 },
};
})();