Statt einer eigenen Vorlage mit nachgebauter Verdrahtung: ?action=anzeige ist der Eintrag solar mit "anzeige" => true. header.php laesst Kopfleiste und Menue weg und setzt die schmale Leiste (neu: Diagramme), footer.php den Fuss; die Realtime-Karte fuellt einen Bildschirm, Diagramme folgen darunter. Damit gehen am Display auch die Bedienfenster (Heizstab, Wallboxen, Bewaesserung) und die Diagramme - alles aus solarMQTT.js. anzeige.js bleibt fuer Leerlauf, Verbindungspunkt, Uhr und Neuladen; restricted/anzeige.php, "eigen" in index.php und klickFilter entfallen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
4.4 KiB
JavaScript
104 lines
4.4 KiB
JavaScript
/* ==========================================================================
|
|
Anzeige-Modus der Solar-Seite (index.php?action=anzeige) für ein festes
|
|
Display, gebaut für den Raspberry Pi 3B+ mit 800 x 480.
|
|
|
|
Die Seite selbst ist die Solar-Seite: solarMQTT.js zeichnet Übersicht,
|
|
Anlage, Speicher und Diagramme und öffnet die Bedienfenster. header.php
|
|
lässt Kopfleiste und Menü weg und setzt stattdessen die schmale Leiste
|
|
links; die Übersicht bleibt quer (energieflussStarten() in solarMQTT.js
|
|
fragt nach der Klasse "anzeige" am body).
|
|
|
|
Hier steht nur, was ein Display ohne Bediener braucht:
|
|
- Leiste: Übersicht, Anlage, Speicher, Diagramme
|
|
- nach LEERLAUF ohne Berührung zurück zur Übersicht, ganz nach oben
|
|
- Punkt in der Leiste: grün verbunden, gelb keine frischen Werte,
|
|
rot getrennt
|
|
- alle NEU_LADEN Stunden neu laden - ein Browser, der wochenlang läuft,
|
|
sammelt sonst Speicher an, und Änderungen am Code kämen nie an
|
|
========================================================================== */
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
const LEERLAUF = 2 * 60000;
|
|
const NEU_LADEN = 6 * 3600000;
|
|
const VERALTET = 30000;
|
|
|
|
const $ = id => document.getElementById(id);
|
|
let leerlaufUhr = null;
|
|
let letzteNachricht = null, letzteZeit = 0;
|
|
|
|
function leisteSetzen(name) {
|
|
document.querySelectorAll("[data-anzeige]").forEach(b =>
|
|
b.setAttribute("aria-pressed", b.dataset.anzeige === name ? "true" : "false"));
|
|
}
|
|
|
|
function karte() {
|
|
return $("energieflussKarte");
|
|
}
|
|
|
|
/** Eine Ansicht der Realtime-Karte zeigen - über ihren eigenen Umschalter. */
|
|
function zeige(name) {
|
|
if (name === "diagramme") {
|
|
// Die nächste Spalte nach der Realtime-Karte - dazwischen steht ein <script>.
|
|
let ziel = karte() && karte().closest("[class*=col-]").nextElementSibling;
|
|
while (ziel && !ziel.matches("[class*=col-]")) ziel = ziel.nextElementSibling;
|
|
if (ziel) ziel.scrollIntoView({ behavior: "instant", block: "start" });
|
|
leisteSetzen("diagramme");
|
|
return;
|
|
}
|
|
window.scrollTo({ top: 0, behavior: "instant" });
|
|
const knopf = document.querySelector('[data-enf-ansicht="' + name + '"]');
|
|
if (knopf) knopf.click();
|
|
leisteSetzen(name);
|
|
}
|
|
|
|
function wachHalten() {
|
|
clearTimeout(leerlaufUhr);
|
|
leerlaufUhr = setTimeout(() => {
|
|
const offen = document.querySelector(".modal.show");
|
|
if (offen && window.bootstrap) bootstrap.Modal.getOrCreateInstance(offen).hide();
|
|
zeige("fluss");
|
|
}, LEERLAUF);
|
|
}
|
|
|
|
function zustand() {
|
|
const nachricht = window.mqttData && mqttData["solarManager/P_Load"];
|
|
if (nachricht && nachricht !== letzteNachricht) { letzteNachricht = nachricht; letzteZeit = Date.now(); }
|
|
const verbunden = typeof solarMqttClient !== "undefined" && solarMqttClient && solarMqttClient.connected;
|
|
const frisch = Date.now() - letzteZeit < VERALTET;
|
|
const punkt = $("anzeigeVerbindung");
|
|
const klasse = "anzeige-punkt" + (verbunden && frisch ? " gut" : verbunden ? " warn" : "");
|
|
if (punkt.className !== klasse) {
|
|
punkt.className = klasse;
|
|
punkt.title = verbunden && frisch ? "verbunden" : verbunden ? "verbunden, aber keine frischen Werte" : "Verbindung getrennt";
|
|
}
|
|
const d = new Date();
|
|
const uhr = String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0");
|
|
if ($("anzeigeUhr").textContent !== uhr) $("anzeigeUhr").textContent = uhr;
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
if (!document.body.classList.contains("anzeige")) return;
|
|
|
|
document.querySelectorAll("[data-anzeige]").forEach(b => b.addEventListener("click", () => zeige(b.dataset.anzeige)));
|
|
// Klick auf Sonne oder Batterie wechselt über den Umschalter der Karte -
|
|
// die Leiste zieht nach.
|
|
document.querySelectorAll("[data-enf-ansicht]").forEach(b =>
|
|
b.addEventListener("click", () => leisteSetzen(b.dataset.enfAnsicht)));
|
|
window.addEventListener("scroll", () => {
|
|
const k = karte();
|
|
if (!k) return;
|
|
const unten = k.getBoundingClientRect().bottom < window.innerHeight / 2;
|
|
const aktiv = document.querySelector("[data-enf-ansicht].active");
|
|
leisteSetzen(unten ? "diagramme" : aktiv ? aktiv.dataset.enfAnsicht : "fluss");
|
|
}, { passive: true });
|
|
|
|
document.addEventListener("pointerdown", wachHalten, { passive: true });
|
|
wachHalten();
|
|
setInterval(zustand, 1000);
|
|
zustand();
|
|
setTimeout(() => location.reload(), NEU_LADEN);
|
|
});
|
|
})();
|