From 79a55aeafd30d433143eccd8e1baf891043330ab Mon Sep 17 00:00:00 2001 From: Moirtz Wagner Date: Mon, 31 Aug 2026 22:55:58 +0200 Subject: [PATCH] Kacheln zeigen frei gewaehlte Messwerte, Heizung nur wo eine haengt Drei Sachen an den Kacheln und am Raum-Modal. Die Platzhalter sind nur noch Striche. Vorher stand dort "---- hPa", gefuellt wurde die Zeile aber mit der Solltemperatur - eine Einheit, die nie kam, an einer Stelle, die etwas anderes zeigt. Der Heizungs-Reiter erscheint nur noch, wo auch ein Thermostat haengt. Frueher entschied das "hat der Raum eine Kachel" - das stimmte, solange nur Raeume mit Thermostat eine bekamen. Seit auch Kueche und Technik eine haben, bekamen sie einen Regler fuer eine Heizung, die es dort nicht gibt. Jetzt zaehlt, ob im Raum ein Geraet der Bedienform "heizung" steht. Und eine Kachel zeigt jetzt ein bis drei frei gewaehlte Messwerte. In restricted/rooms.php steht je Raum unter "werte", welche das sind: topic, optional pfad (Schluessel in einer JSON-Nachricht), einheit, stellen. Ohne Angabe bleibt es bei den drei Thermostatwerten samt Heizsymbol, also genau wie bisher - nur diese Raeume zeichnen die Symbole ueberhaupt noch. Alles kommt live ueber MQTT, auch die beiden Shelly-Zaehler: sie schicken ihre sechzehn Werte als eine JSON-Nachricht auf Power_EG/status/em:0, aus der "pfad" den gesuchten Schluessel greift. Der Browser meldet nicht mehr fest "Raumtemp/#" an, sondern die Zweige, die die Raumtabelle nennt - derzeit vier statt vierzig einzelner Topics. Damit steht auf EG Technik die Leistung (gemessen 293 W), auf UG Technik Leistung und Wasserzaehler (78 W, 400,4 m3). Raeume ohne Messwert tragen ihren Namen und oeffnen den Raum; ein leeres Rechteck saehe aus wie ein Fehler. Co-Authored-By: Claude Opus 5 --- ajax/room.php | 23 +++++++------ js/solar/homeMQTT.js | 69 ++++++++++++++++++++++++++++++------- restricted/home.php | 36 +++++++++++++++---- restricted/rooms.php | 82 +++++++++++++++++++++++++++++++++++++++----- 4 files changed, 173 insertions(+), 37 deletions(-) diff --git a/ajax/room.php b/ajax/room.php index 49b82ac..36c6ee7 100644 --- a/ajax/room.php +++ b/ajax/room.php @@ -84,18 +84,18 @@ $etage = $teile[0] ?? ""; $name = $teile[1] ?? ""; $raumKey = $etage . "/" . $name; -// Hat der Raum ein Thermostat? Nur dann gibt es etwas zu heizen. -$hatThermostat = false; -foreach (allRooms() as $raum) { - if ($raum["floor"] === $etage && $raum["mqtt"] === $name) { - $hatThermostat = isset($raum["x"]); // Kachel = Thermostat vorhanden - } -} - -// Alles im Raum, sortiert nach Bedienform. Das Thermostat selbst faellt -// heraus: es wird oben zum Schieberegler und braucht daneben keine zweite -// Bedienung - "Solltemperatur" stand vorher zweimal im Modal. +// Alles im Raum, sortiert nach Bedienform. Das Thermostat selbst wird nicht +// als Karte gezeichnet: es wird zum Schieberegler im Heizungs-Reiter und +// braucht daneben keine zweite Bedienung - "Solltemperatur" stand sonst +// zweimal im Modal. +// +// Ob es einen Heizungs-Reiter gibt, entscheidet genau das: haengt in diesem +// Raum ein Thermostat? Frueher stand hier "hat der Raum eine Kachel" - das +// stimmte, solange nur Raeume mit Thermostat eine bekamen. Seit auch Kueche +// und Technik eine haben, bekamen sie einen Heizungsregler fuer eine +// Heizung, die es dort nicht gibt. $katalog = deviceCatalog(); +$hatThermostat = false; $gruppen = []; foreach ($katalog as $d) { if ($d["room"] !== $raumKey) { @@ -103,6 +103,7 @@ foreach ($katalog as $d) { } $form = bedienform($d); if ($form === "heizung") { + $hatThermostat = true; continue; } $gruppen[$form][] = $d; diff --git a/js/solar/homeMQTT.js b/js/solar/homeMQTT.js index 58c2cf5..6f6549a 100644 --- a/js/solar/homeMQTT.js +++ b/js/solar/homeMQTT.js @@ -13,7 +13,10 @@ const homeMQTT = { client.on("message", messageReceived); client.on("connect", function () { - client.subscribe("Raumtemp/#"); + // Welche Zweige gebraucht werden, sagt die Raumtabelle: seit eine + // Kachel jeden Messwert zeigen kann, reicht Raumtemp allein nicht + // mehr. homeTopics kommt aus restricted/rooms.php. + homeTopics.forEach(function (topic) { client.subscribe(topic); }); }); client.on("error", function (error) { //alert("MQTT Error: " + error); @@ -51,25 +54,67 @@ const homeSVG = { fillElementArray: function () { }, + /** + * Eine Nachricht aus dem Baum holen. mqttData ist nach den Teilen des + * Topics verschachtelt, siehe setNestedProp() weiter oben. + */ + ausTopic: function (mqttData, topic) { + return topic.split("/").reduce(function (zweig, teil) { + return zweig && zweig[teil]; + }, mqttData); + }, + + /** + * Einen Kachelwert lesen und hinschreiben. + * + * "pfad" ist gesetzt, wenn das Geraet mehrere Werte in einer einzigen + * JSON-Nachricht schickt - die beiden Shelly-Zaehler tun das. "stellen" + * schneidet Nachkommastellen ab; ohne Angabe bleibt der Text so, wie das + * Geraet ihn meldet. + */ + kachelWert: function (mqttData, wert) { + const roh = homeSVG.ausTopic(mqttData, wert.topic); + if (typeof roh === "undefined") return null; + let text = String(roh); + if (wert.pfad) { + try { + const daten = JSON.parse(text); + if (!(wert.pfad in daten)) return null; + text = String(daten[wert.pfad]); + } catch (fehler) { + return null; // noch keine vollstaendige Nachricht + } + } + if (typeof wert.stellen === "number" && text !== "" && !isNaN(Number(text))) { + text = Number(text).toFixed(wert.stellen); + } + // Schmales Leerzeichen zwischen Zahl und Einheit, wie es sich gehoert. + return wert.einheit ? text + "\u2009" + wert.einheit : text; + }, + updateValuesMQTT: function (mqttData) { - // homeRooms liefert restricted/rooms.php (in home.php eingebettet). - // Jeder Raum bekommt die gleiche Behandlung - Raeume kommen dort dazu, - // nicht hier. + // homeRooms liefert restricted/rooms.php (in home.php eingebettet), + // mitsamt den Werten, die auf der Kachel stehen sollen. Jeder Raum + // bekommt die gleiche Behandlung - Raeume und ihre Werte kommen dort + // dazu, nicht hier. homeRooms.forEach(function (room) { - const values = mqttData["Raumtemp"]?.[room.floor]?.[room.mqtt]; - if (!values) return; // Topic noch nicht empfangen const el = (part) => document.getElementById(room.floor + "_" + part); + room.werte.forEach(function (wert, i) { + const text = homeSVG.kachelWert(mqttData, wert); + const feld = el("w" + i + "_" + room.id); + if (text !== null && feld) feld.innerHTML = text; + }); + + // Heizsymbol und Pufferbetrieb gibt es nur, wo ein Thermostat + // haengt - anderswo sind die Elemente gar nicht gezeichnet. + if (!room.heizung) return; + const values = mqttData["Raumtemp"]?.[room.floor]?.[room.mqtt]; + if (!values) return; if (typeof (values["Heating"]) != "undefined") el(room.id + "_heater").setAttribute("display", values["Heating"] == "false" ? "none" : ""); if (typeof (values["mode"]) != "undefined") el(room.id + "_buffer").setAttribute("display", values["mode"] == "Overheating" ? "" : "none"); - if (typeof (values["Set Temp[degC]"]) != "undefined") - el("pres_" + room.id).innerHTML = Math.floor(values["Set Temp[degC]"]) + "\u2009\u00b0C"; - if (typeof (values["Temp[degC]"]) != "undefined") - el("tmp_" + room.id).innerHTML = values["Temp[degC]"] + "\u2009\u00b0C"; - if (typeof (values["rHum[%]"]) != "undefined") - el("hum_" + room.id).innerHTML = values["rHum[%]"] + "\u2009%rF"; }); } diff --git a/restricted/home.php b/restricted/home.php index 1e8250f..a424707 100644 --- a/restricted/home.php +++ b/restricted/home.php @@ -107,15 +107,36 @@ > - + + [12], 2 => [9, 16], 3 => [5, 11.5, 16.5]]; + $y = $zeilen[count($room["werte"])] ?? []; +?> ,)" onclick="openHeaterSettings('_');" cursor="pointer"> + _heater" href="#heater" display="none" /> _buffer" href="#buffer" display="none" /> + - " y="5" x="12" text-anchor="middle">---- hPa - " x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C - " x="12" dy="1.2em" text-anchor="middle">-- %rF + + + + + $wert): ?> + + " x="12" y="" + text-anchor="middle">– + @@ -198,8 +219,11 @@