Anzeige fuer den Pi ist jetzt die Solar-Seite im Anzeige-Modus
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>
This commit is contained in:
@@ -192,15 +192,20 @@ genau die Topics, die auf den Kacheln stehen (`tileTopics()` in `rooms.php`).
|
||||
| `settings` | `settings.php` | `settings.js`, `grundriss.js`, `energieflussKatalog.js`, `energiefluss.js`, `energieflussEinstellungen.js` | `settings.php?action=…` | — |
|
||||
| `logs` | `logs.php` | `logs.js` | `logs.php?action=…` | — |
|
||||
| `einfuehrung` | `einfuehrung.php` | `einfuehrung.js` | nichts — Folien und Bilder stehen in der Seite | — |
|
||||
| `anzeige` | `anzeige.php` (ganze Seite, ohne `header.php`/`footer.php`) | `anlageKatalog.js`, `anlage.js`, `speicher.js`, `energieflussKatalog.js`, `energiefluss.js`, `bewaesserungAnzeige.js`, `anzeige.js` | `speicher` | `solarManager/#`, `Gartenwasser/#` |
|
||||
| `anzeige` | `solar.php` im Anzeige-Modus | wie `solar`, dazu `anzeige.js` | wie `solar` | wie `solar` |
|
||||
|
||||
**Vollbildanzeige** (`?action=anzeige`) — Übersicht, Anlage und Speicher für ein
|
||||
festes Display, gebaut für den Raspberry Pi 3B+ mit 800 × 480 im Kioskmodus:
|
||||
schmale Leiste links, immer quer, nach zwei Minuten ohne Berührung zurück zur
|
||||
Übersicht, MQTT verbindet still neu (Punkt unten: grün/gelb/rot), alle sechs
|
||||
Stunden lädt die Seite neu. Ohne weitere Parameter läuft sie „ruhig“ — nur die
|
||||
Flüsse bewegen sich, in groben Stufen — und ohne Mauszeiger;
|
||||
`&animation=1` schaltet alle Animationen ein, `&maus=1` zeigt den Zeiger.
|
||||
**Anzeige-Modus** (`?action=anzeige`) — die Solar-Seite für ein festes Display,
|
||||
gebaut für den Raspberry Pi 3B+ mit 800 × 480 im Kioskmodus. In `index.php` eine
|
||||
Kopie des Eintrags `solar` mit `"anzeige" => true`: `header.php` lässt Kopfleiste
|
||||
und Menü weg und setzt eine schmale Leiste (Übersicht, Anlage, Speicher,
|
||||
Diagramme), `footer.php` den Fuß; die Realtime-Karte füllt einen Bildschirm,
|
||||
die Übersicht bleibt quer. Bedienfenster, Diagramme und Bewässerung kommen
|
||||
unverändert aus `solarMQTT.js`. `anzeige.js` ergänzt nur: zurück zur Übersicht
|
||||
nach zwei Minuten ohne Berührung (offene Fenster schließen), Verbindungspunkt
|
||||
(grün/gelb/rot) und Uhr in der Leiste, Neuladen alle sechs Stunden. Ohne
|
||||
weitere Parameter läuft sie „ruhig“ — nur die Flüsse bewegen sich, in groben
|
||||
Stufen — und ohne Mauszeiger; `&animation=1` schaltet alle Animationen ein,
|
||||
`&maus=1` zeigt den Zeiger.
|
||||
|
||||
Und dasselbe als Abhängigkeitsbild — von der Seite bis in den Speicher:
|
||||
|
||||
|
||||
+35
-21
@@ -3869,22 +3869,19 @@ svg.anl-plan.anl-hoch { max-height: none; }
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Vollbildanzeige (restricted/anzeige.php, js/solar/anzeige.js), z.B. am
|
||||
Raspberry Pi mit 800 x 480: schmale Leiste links, Ansicht auf voller Höhe.
|
||||
Anzeige-Modus (index.php?action=anzeige, js/solar/anzeige.js): die
|
||||
Solar-Seite auf einem festen Display, z.B. Raspberry Pi mit 800 x 480.
|
||||
Leiste links; die Realtime-Karte füllt genau einen Bildschirm, die
|
||||
Diagramme folgen darunter und rasten beim Wischen karteweise ein.
|
||||
========================================================================== */
|
||||
body.anzeige {
|
||||
margin: 0; height: 100vh; overflow: hidden;
|
||||
display: grid; grid-template-columns: 3.2rem minmax(0, 1fr);
|
||||
background: var(--ton-grund, #191d20); color: var(--ton-schrift, #e8ede9);
|
||||
font-family: "Poppins", system-ui, sans-serif; font-size: 14px;
|
||||
-webkit-tap-highlight-color: transparent; user-select: none;
|
||||
}
|
||||
html:has(body.anzeige) { scroll-snap-type: y proximity; scrollbar-width: none; }
|
||||
html:has(body.anzeige)::-webkit-scrollbar { display: none; }
|
||||
body.anzeige { -webkit-tap-highlight-color: transparent; }
|
||||
body.anzeige-ohne-maus,
|
||||
body.anzeige-ohne-maus * { cursor: none !important; }
|
||||
/* Die Seite lädt AdminLTE nicht - dessen Grundregeln fehlen hier. */
|
||||
body.anzeige [hidden] { display: none !important; }
|
||||
body.anzeige *, body.anzeige *::before, body.anzeige *::after { box-sizing: border-box; }
|
||||
|
||||
.anzeige .anzeige-leiste {
|
||||
position: fixed; left: 0; top: 0; bottom: 0; width: 3.2rem; z-index: 1030;
|
||||
display: flex; flex-direction: column; align-items: center; gap: .4rem; padding: .5rem 0;
|
||||
background: var(--ton-flaeche, #23282c); border-right: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
}
|
||||
@@ -3898,14 +3895,26 @@ body.anzeige *, body.anzeige *::before, body.anzeige *::after { box-sizing: bord
|
||||
.anzeige .anzeige-punkt.warn { background: #e8a33a; }
|
||||
.anzeige .anzeige-punkt.gut { background: #6cbe58; }
|
||||
.anzeige .anzeige-uhr { font-size: .72rem; font-weight: 600; color: var(--ton-schrift-2, #9aa6ad); font-variant-numeric: tabular-nums; }
|
||||
.anzeige .anzeige-inhalt { min-width: 0; height: 100vh; }
|
||||
.anzeige .anzeige-flaeche { box-sizing: border-box; height: 100vh; padding: .35rem; overflow-y: auto; scrollbar-width: none; }
|
||||
.anzeige .anzeige-flaeche::-webkit-scrollbar { display: none; }
|
||||
.anzeige .anzeige-flaeche[hidden] { display: none; }
|
||||
.anzeige #anzeige-fluss { overflow: hidden; padding: .2rem; }
|
||||
.anzeige #anzeige-fluss svg.enf { width: 100%; height: 100%; max-height: none; }
|
||||
/* Anlage und Speicher: die Umbrüche der Solar-Seite richten sich nach der
|
||||
Fensterbreite und würden am 800er-Display zu früh greifen. */
|
||||
|
||||
.anzeige .app-wrapper { display: block; }
|
||||
.anzeige .app-main { margin-left: 3.2rem; }
|
||||
.anzeige .app-content-header { display: none; }
|
||||
.anzeige .app-content { padding: 0 .35rem; }
|
||||
.anzeige .app-content .container-fluid { padding: 0; }
|
||||
.anzeige .app-content .row { --bs-gutter-x: 0; }
|
||||
.anzeige .app-content .card { scroll-snap-align: start; }
|
||||
|
||||
/* Realtime-Karte: ein ganzer Bildschirm, ohne Kopf - die Leiste ersetzt ihn. */
|
||||
.anzeige .card#energieflussKarte { height: 100vh; margin-bottom: .5rem !important; border: 0; border-radius: 0; background: transparent; }
|
||||
.anzeige .card#energieflussKarte .card-header { display: none !important; }
|
||||
.anzeige .card#energieflussKarte .card-body { height: 100%; padding: .2rem 0 !important; }
|
||||
.anzeige #energiefluss { height: 100%; overflow: hidden; }
|
||||
.anzeige #energiefluss svg.enf { width: 100%; height: 100%; max-height: none; }
|
||||
.anzeige #anlage,
|
||||
.anzeige #speicher { height: 100%; overflow-y: auto; scrollbar-width: none; }
|
||||
|
||||
/* Die Umbrüche von Anlage und Speicher richten sich nach der Fensterbreite
|
||||
und würden am 800er-Display zu früh greifen. */
|
||||
.anzeige .anl svg.anl-plan { max-height: calc(100vh - 7.5rem); }
|
||||
.anzeige .spk .spk-kennzahlen { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .35rem; }
|
||||
.anzeige .spk .spk-kachel { padding: .4rem .55rem .45rem; }
|
||||
@@ -3921,6 +3930,12 @@ body.anzeige *, body.anzeige *::before, body.anzeige *::after { box-sizing: bord
|
||||
.anzeige .spk .spk-werte small { font-size: .62rem; }
|
||||
.anzeige .spk .spk-gross b { font-size: 1.4rem; }
|
||||
|
||||
/* Bedienfenster: passen auf 480 px Höhe und lassen sich mit dem Finger bedienen. */
|
||||
.anzeige .modal-dialog { margin: .4rem auto; }
|
||||
.anzeige .modal-body { max-height: calc(100vh - 9rem); overflow-y: auto; }
|
||||
.anzeige .modal .form-range { height: 2rem; }
|
||||
.anzeige .modal .btn { min-height: 2.4rem; }
|
||||
|
||||
/* Ruhig (Vorgabe am Pi): alles Zierwerk aus, nur die Flüsse laufen - in
|
||||
groben Stufen, damit ein Raspberry Pi 3 nicht dauernd neu zeichnet. */
|
||||
.anzeige-ruhig *,
|
||||
@@ -3932,7 +3947,6 @@ body.anzeige *, body.anzeige *::before, body.anzeige *::after { box-sizing: bord
|
||||
.anzeige-ruhig .enf .enf-rueck .enf-strom { animation-direction: reverse !important; }
|
||||
.anzeige-ruhig .enf .enf-still .enf-strom,
|
||||
.anzeige-ruhig .enf.enf-pause .enf-strom { animation: none !important; }
|
||||
.anzeige-ruhig .enf .enf-strahlen,
|
||||
.anzeige-ruhig .enf .enf-koerper { transition: none; }
|
||||
|
||||
/* --- Karte: Umschalter Übersicht / Anlage -------------------------------- */
|
||||
|
||||
@@ -120,13 +120,13 @@ if (isset($_GET["addUser"])) {
|
||||
"scripts" => ["js/solar/logs.js"]],
|
||||
"einfuehrung" => ["template" => "einfuehrung.php", "mqtt" => false, "charts" => false, "meteogram" => false, "leaflet" => false,
|
||||
"scripts" => ["js/solar/einfuehrung.js"]],
|
||||
// Vollbild für ein festes Display (Raspberry Pi). "eigen": die Vorlage
|
||||
// ist eine ganze Seite, ohne header.php und footer.php.
|
||||
"anzeige" => ["template" => "anzeige.php", "eigen" => true, "mqtt" => true, "charts" => false, "meteogram" => false, "leaflet" => false,
|
||||
"scripts" => ["js/solar/anlageKatalog.js", "js/solar/anlage.js", "js/solar/speicher.js",
|
||||
"js/solar/energieflussKatalog.js", "js/solar/energiefluss.js",
|
||||
"js/solar/bewaesserungAnzeige.js", "js/solar/anzeige.js"]],
|
||||
];
|
||||
// Anzeige für ein festes Display (Raspberry Pi, 800 x 480): die Solar-Seite
|
||||
// ohne Kopfleiste und Menue, mit schmaler Leiste - header.php und
|
||||
// footer.php richten sich nach "anzeige", js/solar/anzeige.js macht den Rest.
|
||||
$pages["anzeige"] = $pages["solar"];
|
||||
$pages["anzeige"]["anzeige"] = true;
|
||||
$pages["anzeige"]["scripts"][] = "js/solar/anzeige.js";
|
||||
|
||||
// Unbekannte oder fehlende Aktion faellt auf die Solar-Seite zurueck.
|
||||
if (!isset($_GET["action"]) || !isset($pages[$_GET["action"]])) {
|
||||
@@ -134,13 +134,9 @@ if (isset($_GET["addUser"])) {
|
||||
}
|
||||
$page = $pages[$_GET["action"]];
|
||||
|
||||
if (!empty($page["eigen"])) {
|
||||
include "restricted/" . $page["template"];
|
||||
} else {
|
||||
include "restricted/header.php";
|
||||
include "restricted/" . $page["template"];
|
||||
include "restricted/footer.php";
|
||||
}
|
||||
} else {
|
||||
echo <<<ENDE
|
||||
<html>
|
||||
|
||||
+66
-85
@@ -1,122 +1,103 @@
|
||||
/* ==========================================================================
|
||||
Vollbildanzeige (restricted/anzeige.php): Übersicht, Anlage und Speicher
|
||||
für ein festes Display, z.B. den Raspberry Pi mit 800 x 480.
|
||||
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.
|
||||
|
||||
Dieselben Bausteine wie auf der Solar-Seite, nur anders verdrahtet:
|
||||
- immer quer (hochkantUnter: 0), das Display steht quer
|
||||
- antippbar sind nur Kreise, die eine andere Ansicht öffnen; Bedienfenster
|
||||
(Heizstab, Wallbox) gibt es hier nicht
|
||||
- nach LEERLAUF ohne Berührung zurück zur Übersicht
|
||||
- MQTT verbindet nach einem Abbruch still neu; der Punkt unten in der
|
||||
Leiste zeigt den Zustand (grün verbunden, gelb keine frischen Werte,
|
||||
rot getrennt). Kein alert() - am Display ist niemand, der ihn wegklickt.
|
||||
- alle NEU_LADEN Stunden lädt die Seite neu, damit ein Browser, der
|
||||
wochenlang läuft, keinen Speicher ansammelt und Änderungen am Code
|
||||
ankommen
|
||||
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
|
||||
========================================================================== */
|
||||
|
||||
var mqttData = {};
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const ADRESSE = "wss://mqtt.nas.el-wa.org:443"; // wie in solarMQTT.js
|
||||
const LEERLAUF = 2 * 60000;
|
||||
const NEU_LADEN = 6 * 3600000;
|
||||
const TAKT = typeof anzeigeRuhig !== "undefined" && anzeigeRuhig ? 2000 : 1000;
|
||||
const VERALTET = 30000;
|
||||
const THEMEN = [
|
||||
"solarManager/#",
|
||||
"Gartenwasser/vorn/Timers", "Gartenwasser/vorn/status", "Gartenwasser/vorn/WateringToday",
|
||||
"Gartenwasser/hinten/Timers", "Gartenwasser/hinten/status", "Gartenwasser/hinten/WateringToday",
|
||||
];
|
||||
|
||||
const $ = id => document.getElementById(id);
|
||||
let bild = null, anlage = null, speicher = null;
|
||||
let leerlaufUhr = null, geplant = false, verbunden = false, letzteDaten = 0;
|
||||
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) {
|
||||
document.querySelectorAll("[data-anzeige]").forEach(b => b.setAttribute("aria-pressed", b.dataset.anzeige === name ? "true" : "false"));
|
||||
document.querySelectorAll("[data-anzeige-flaeche]").forEach(f => { f.hidden = f.dataset.anzeigeFlaeche !== name; });
|
||||
wachHalten();
|
||||
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(() => zeige("fluss"), LEERLAUF);
|
||||
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 frisch = Date.now() - letzteDaten < VERALTET;
|
||||
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 – wird neu aufgebaut";
|
||||
punkt.title = verbunden && frisch ? "verbunden" : verbunden ? "verbunden, aber keine frischen Werte" : "Verbindung getrennt";
|
||||
}
|
||||
}
|
||||
|
||||
function uhr() {
|
||||
const d = new Date();
|
||||
const text = String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0");
|
||||
if ($("anzeigeUhr").textContent !== text) $("anzeigeUhr").textContent = text;
|
||||
}
|
||||
|
||||
function aktualisieren() {
|
||||
if (geplant) return;
|
||||
geplant = true;
|
||||
setTimeout(() => {
|
||||
geplant = false;
|
||||
bild.aktualisieren(mqttData);
|
||||
anlage.aktualisieren(mqttData);
|
||||
speicher.aktualisieren(mqttData);
|
||||
}, TAKT);
|
||||
}
|
||||
|
||||
function verbinden() {
|
||||
const client = mqtt.connect(ADRESSE, { rejectUnauthorized: false, reconnectPeriod: 5000, connectTimeout: 15000 });
|
||||
client.on("connect", () => {
|
||||
verbunden = true;
|
||||
client.subscribe(THEMEN);
|
||||
zustand();
|
||||
});
|
||||
const weg = () => { verbunden = false; zustand(); };
|
||||
client.on("close", weg);
|
||||
client.on("offline", weg);
|
||||
client.on("error", () => {});
|
||||
client.on("message", (topic, nachricht) => {
|
||||
mqttData[topic] = nachricht;
|
||||
if (topic.endsWith("/Timers")) wateringTimersLastSeen[topic] = Date.now();
|
||||
if (topic === "solarManager/P_Load") {
|
||||
letzteDaten = Date.now();
|
||||
aktualisieren();
|
||||
}
|
||||
});
|
||||
const uhr = String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0");
|
||||
if ($("anzeigeUhr").textContent !== uhr) $("anzeigeUhr").textContent = uhr;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const bewaesserung = () => wateringSymboleSetzen(id => document.getElementById(id));
|
||||
|
||||
bild = new Energiefluss($("anzeige-fluss"), {
|
||||
einstellungen: typeof energieflussEinstellungen !== "undefined" ? energieflussEinstellungen : {},
|
||||
hochkantUnter: 0,
|
||||
klickFilter: k => !!k.klick.ansicht,
|
||||
onKlick: k => zeige(k.klick.ansicht),
|
||||
onGezeichnet: bewaesserung,
|
||||
});
|
||||
bild.zeichnen();
|
||||
anlage = new Anlage($("anzeige-anlage"), { hochkantUnter: 0 });
|
||||
anlage.zeichnen();
|
||||
speicher = new Speicher($("anzeige-speicher"));
|
||||
speicher.zeichnen();
|
||||
if (!document.body.classList.contains("anzeige")) return;
|
||||
|
||||
document.querySelectorAll("[data-anzeige]").forEach(b => b.addEventListener("click", () => zeige(b.dataset.anzeige)));
|
||||
document.addEventListener("pointerdown", wachHalten, { passive: true });
|
||||
// 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 });
|
||||
|
||||
setInterval(() => { uhr(); zustand(); bewaesserung(); }, 1000);
|
||||
uhr();
|
||||
document.addEventListener("pointerdown", wachHalten, { passive: true });
|
||||
wachHalten();
|
||||
setInterval(zustand, 1000);
|
||||
zustand();
|
||||
verbinden();
|
||||
setTimeout(() => location.reload(), NEU_LADEN);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
onKlick(knoten), // Kreis mit klick-Ziel angetippt
|
||||
onVerschoben(id, x, y), // nur beim Bearbeiten
|
||||
onGezeichnet(), // nach jedem (Neu-)Zeichnen
|
||||
klickFilter(knoten), // optional: welche Kreise antippbar sind
|
||||
hochkantUnter: 720, // optional: px Breite, darunter hochkant (0 = nie)
|
||||
});
|
||||
bild.aktualisieren(mqttData);
|
||||
@@ -222,9 +221,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** Antippbar: hat ein Ziel, nicht im Bearbeiten, und opt.klickFilter lässt es zu. */
|
||||
/** Antippbar: hat ein Ziel und wird nicht gerade bearbeitet. */
|
||||
klickbar(k) {
|
||||
return !!k.klick && !this.bearbeiten && (!this.opt.klickFilter || this.opt.klickFilter(k));
|
||||
return !!k.klick && !this.bearbeiten;
|
||||
}
|
||||
|
||||
hochkantGewuenscht() {
|
||||
|
||||
@@ -196,7 +196,10 @@ function energieflussStarten() {
|
||||
knopf.addEventListener("click", function () { zeigeAnsicht(knopf.dataset.enfAnsicht); });
|
||||
});
|
||||
|
||||
// Anzeige-Modus (festes Display, js/solar/anzeige.js): immer quer.
|
||||
const anzeigeModus = document.body.classList.contains("anzeige");
|
||||
energiefluss = new Energiefluss(behaelter, {
|
||||
hochkantUnter: anzeigeModus ? 0 : undefined,
|
||||
einstellungen: typeof energieflussEinstellungen !== "undefined" ? energieflussEinstellungen : {},
|
||||
onKlick: function (knoten) {
|
||||
if (knoten.klick.ansicht) zeigeAnsicht(knoten.klick.ansicht);
|
||||
@@ -211,7 +214,7 @@ function energieflussStarten() {
|
||||
|
||||
const anlageBehaelter = document.getElementById("anlage");
|
||||
if (anlageBehaelter && typeof Anlage !== "undefined") {
|
||||
anlage = new Anlage(anlageBehaelter);
|
||||
anlage = new Anlage(anlageBehaelter, { hochkantUnter: anzeigeModus ? 0 : undefined });
|
||||
anlage.zeichnen();
|
||||
}
|
||||
const speicherBehaelter = document.getElementById("speicher");
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Vollbildanzeige für ein festes Display, gedacht für den Raspberry Pi mit
|
||||
* dem 7-Zoll-Display (800 x 480) im Kioskmodus:
|
||||
*
|
||||
* index.php?action=anzeige ruhige Animationen, kein Mauszeiger
|
||||
* index.php?action=anzeige&animation=1 alle Animationen (schnellere Geräte)
|
||||
* index.php?action=anzeige&maus=1 Mauszeiger sichtbar (zum Einrichten)
|
||||
*
|
||||
* Eine eigene Seite ohne Kopf, Seitenleiste und die Karten der Solar-Seite:
|
||||
* links eine schmale Leiste mit Übersicht, Anlage und Speicher, rechts die
|
||||
* Ansicht auf voller Höhe. Gezeichnet wird mit denselben Bausteinen wie auf
|
||||
* der Solar-Seite (energiefluss.js, anlage.js, speicher.js); verdrahtet
|
||||
* werden sie von js/solar/anzeige.js.
|
||||
*
|
||||
* index.php bindet für diese Seite weder header.php noch footer.php ein
|
||||
* ("eigen" in der Seitentabelle) - deshalb steht der Kopf hier selbst.
|
||||
*/
|
||||
require_once(__DIR__ . "/energiefluss.php");
|
||||
|
||||
$ruhig = empty($_GET["animation"]);
|
||||
$maus = !empty($_GET["maus"]);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="de" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<title>Energiefluss</title>
|
||||
<link rel="icon" type="image/png" href="assets/img/favicon.png" />
|
||||
<link rel="stylesheet" href="assets/fonts/font_poppins.css" />
|
||||
<link rel="stylesheet" href="css/bootstrap-icons.min.css" />
|
||||
<link rel="stylesheet" href="./css/solar.css?v=<?= filemtime("css/solar.css") ?>" />
|
||||
</head>
|
||||
<body class="anzeige<?= $ruhig ? " anzeige-ruhig" : "" ?><?= $maus ? "" : " anzeige-ohne-maus" ?>">
|
||||
<nav class="anzeige-leiste" aria-label="Ansicht">
|
||||
<button type="button" data-anzeige="fluss" aria-pressed="true" title="Übersicht"><i class="bi bi-diagram-3"></i></button>
|
||||
<button type="button" data-anzeige="anlage" aria-pressed="false" title="Anlage"><i class="bi bi-grid-3x2-gap"></i></button>
|
||||
<button type="button" data-anzeige="speicher" aria-pressed="false" title="Speicher"><i class="bi bi-battery-half"></i></button>
|
||||
<div class="anzeige-fuss">
|
||||
<span class="anzeige-punkt" id="anzeigeVerbindung" title="Verbindung wird aufgebaut"></span>
|
||||
<span class="anzeige-uhr" id="anzeigeUhr"></span>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="anzeige-inhalt">
|
||||
<div class="anzeige-flaeche" data-anzeige-flaeche="fluss" id="anzeige-fluss"></div>
|
||||
<div class="anzeige-flaeche" data-anzeige-flaeche="anlage" id="anzeige-anlage" hidden></div>
|
||||
<div class="anzeige-flaeche" data-anzeige-flaeche="speicher" id="anzeige-speicher" hidden></div>
|
||||
</main>
|
||||
<script>
|
||||
// Abweichungen dieses Hauses vom Katalog, siehe restricted/energiefluss.php.
|
||||
const energieflussEinstellungen = <?= json_encode((object)energieflussLaden(), JSON_UNESCAPED_UNICODE) ?>;
|
||||
const anzeigeRuhig = <?= $ruhig ? "true" : "false" ?>;
|
||||
</script>
|
||||
<script src="js/mqtt.min.js"></script>
|
||||
<?php foreach ($page["scripts"] as $script): ?>
|
||||
<script src="<?= $script ?>?v=<?= filemtime($script) ?>"></script>
|
||||
<?php endforeach; ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +1,4 @@
|
||||
<?php if (empty($page["anzeige"])): ?>
|
||||
<!--begin::Footer-->
|
||||
<footer class="app-footer">
|
||||
<!--begin::To the end-->
|
||||
@@ -12,6 +13,7 @@
|
||||
<!--end::Copyright-->
|
||||
</footer>
|
||||
<!--end::Footer-->
|
||||
<?php endif; ?>
|
||||
<div class="modal fade" id="modalEV" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
+27
-1
@@ -59,9 +59,34 @@ if (!isset($_GET["floor"]))
|
||||
<!--end::Head-->
|
||||
<!--begin::Body-->
|
||||
|
||||
<body class="layout-fixed sidebar-expand-lg bg-body-tertiary" data-bs-theme="dark">
|
||||
<?php
|
||||
// Anzeige-Modus (?action=anzeige, siehe index.php): dieselbe Seite fuer ein
|
||||
// festes Display, ohne Kopfleiste und Menue, dafuer mit schmaler Leiste.
|
||||
// ?animation=1 schaltet alle Animationen ein, ?maus=1 den Mauszeiger.
|
||||
$anzeige = !empty($page["anzeige"]);
|
||||
$koerperKlassen = "layout-fixed sidebar-expand-lg bg-body-tertiary";
|
||||
if ($anzeige) {
|
||||
$koerperKlassen .= " anzeige" . (empty($_GET["animation"]) ? " anzeige-ruhig" : "")
|
||||
. (empty($_GET["maus"]) ? " anzeige-ohne-maus" : "");
|
||||
}
|
||||
?>
|
||||
<body class="<?= $koerperKlassen ?>" data-bs-theme="dark">
|
||||
<?php if ($anzeige): ?>
|
||||
<!-- Leiste der Anzeige; verdrahtet in js/solar/anzeige.js -->
|
||||
<nav class="anzeige-leiste" aria-label="Ansicht">
|
||||
<button type="button" data-anzeige="fluss" aria-pressed="true" title="Übersicht"><i class="bi bi-diagram-3"></i></button>
|
||||
<button type="button" data-anzeige="anlage" aria-pressed="false" title="Anlage"><i class="bi bi-grid-3x2-gap"></i></button>
|
||||
<button type="button" data-anzeige="speicher" aria-pressed="false" title="Speicher"><i class="bi bi-battery-half"></i></button>
|
||||
<button type="button" data-anzeige="diagramme" aria-pressed="false" title="Diagramme"><i class="bi bi-graph-up"></i></button>
|
||||
<div class="anzeige-fuss">
|
||||
<span class="anzeige-punkt" id="anzeigeVerbindung" title="Verbindung wird aufgebaut"></span>
|
||||
<span class="anzeige-uhr" id="anzeigeUhr"></span>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<!--begin::App Wrapper-->
|
||||
<div class="app-wrapper">
|
||||
<?php if (!$anzeige): ?>
|
||||
<!--begin::Header-->
|
||||
<nav class="app-header navbar navbar-expand bg-body">
|
||||
<!--begin::Container-->
|
||||
@@ -214,3 +239,4 @@ if (!isset($_GET["floor"]))
|
||||
<!--end::Sidebar Wrapper-->
|
||||
</aside>
|
||||
<!--end::Sidebar-->
|
||||
<?php endif; ?>
|
||||
Reference in New Issue
Block a user