Raeume ueber ihre feste Nummer: actors.room_id, Raum-Modal, Thermostat-Zweig
Geraete hingen ueber den Text "Etage/Raum" an ihrem Raum, das Raum-Modal zerlegte "EG_Bad" am Unterstrich, und das Thermostat-Topic wurde aus Etage und Name zusammengesetzt. Ein umbenannter Raum haette still alle Geraete, seinen Temperaturregler und sein Heizsymbol verloren. - actors.room (Text) -> actors.room_id, Fremdschluessel auf rooms, beim Loeschen eines Raums SET NULL. Alle 59 Zuordnungen uebernommen. - automations.floor: ENUM(UG,EG,OG,AG) -> Verweis auf floors. Eine neue Etage kann damit auch Automatiken tragen. - room.php nimmt ?room=<Nummer>; Solltemperatur geht an rooms.thermostat + /changeSetTemp. - homeMQTT.js: Heizsymbol, Regler und Ist-Werte ueber mqttZweig(thermostat) statt mqttData.Raumtemp[Etage][Name]. - Raumvorschlaege in den Einstellungen: Messwerte unter dem Thermostat- Zweig eines Raums statt fest Raumtemp/<Etage>/<Name>. - Schluessel in raumListe(), Katalog und Maske ist die Raumnummer als Text. Geprueft gegen den Stand davor: Startseite gleich bis auf das Klickziel, jede der 25 Kacheln oeffnet ihren eigenen Raum; Geraeteliste, Vorschlaege, Editor-Katalog und die eigenen Geraete je Kachel gleich. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+33
-12
@@ -192,7 +192,7 @@ const homeSVG = {
|
||||
// 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];
|
||||
const values = mqttZweig(room.thermostat);
|
||||
if (!values) return;
|
||||
if (typeof (values["Heating"]) != "undefined")
|
||||
el(room.id + "_heater").setAttribute("display", values["Heating"] == "false" ? "none" : "");
|
||||
@@ -276,8 +276,23 @@ function switchFloor(floor){
|
||||
|
||||
var mqttData = {};
|
||||
|
||||
function openHeaterSettings(heater){
|
||||
openRoomView(heater);
|
||||
/**
|
||||
* Ein Zweig des Nachrichtenbaums nach seinem Topic, z.B. "Raumtemp/EG/Bad".
|
||||
*
|
||||
* Frueher stand hier fest mqttData["Raumtemp"][Etage][Raum] - das setzte
|
||||
* voraus, dass jedes Thermostat unter Raumtemp/<Etage>/<Raumname> meldet.
|
||||
* Jetzt steht der Zweig am Raum (rooms.thermostat).
|
||||
*/
|
||||
function mqttZweig(topic) {
|
||||
if (!topic) return undefined;
|
||||
return String(topic).split("/").filter(t => t !== "")
|
||||
.reduce((knoten, teil) => knoten?.[teil], mqttData);
|
||||
}
|
||||
|
||||
/** Ein Raum aus homeRooms nach seiner festen Nummer. */
|
||||
function raumNachNummer(nr) {
|
||||
return (typeof homeRooms !== "undefined" ? homeRooms : [])
|
||||
.find(r => r.nr === Number(nr));
|
||||
}
|
||||
|
||||
document.addEventListener('readystatechange', function () {
|
||||
@@ -294,13 +309,19 @@ function switchFloor(floor){
|
||||
* oeffnen - vorher kam nur der Temperaturregler, die Rollladen im selben
|
||||
* Zimmer waren von hier gar nicht erreichbar.
|
||||
*
|
||||
* Welche Geraete dazugehoeren, sagt die Raumzuordnung (actors.room).
|
||||
* Welche Geraete dazugehoeren, sagt die Raumzuordnung (actors.room_id).
|
||||
* `raum` ist die feste Raumnummer (rooms.id).
|
||||
*/
|
||||
function openRoomView(raum) {
|
||||
const teile = raum.toString().split("_");
|
||||
document.getElementById("modal-title").innerHTML =
|
||||
teile[0] + " · " + teile.slice(1).join(" ")
|
||||
.replace("ue", "ü").replace("ae", "ä").replace("oe", "ö");
|
||||
const eintrag = raumNachNummer(raum);
|
||||
// Der Name kommt jetzt aus der Datenbank und darf Umlaute tragen. Die
|
||||
// Ersetzung bleibt fuer die alten Namen ("Kueche"), bis sie jemand
|
||||
// unter Einstellungen -> Grundriss umbenennt.
|
||||
const titel = eintrag
|
||||
? eintrag.floor + " · " + eintrag.mqtt.replace("ue", "ü").replace("ae", "ä").replace("oe", "ö")
|
||||
: "Raum";
|
||||
const modalTitel = document.getElementById("modal-title");
|
||||
modalTitel.textContent = titel;
|
||||
|
||||
// Der Speichern-Knopf gehoert allen Modals gemeinsam. Ein Klon ohne
|
||||
// Zuhoerer stellt sicher, dass nicht der Handler eines vorher
|
||||
@@ -330,7 +351,7 @@ function switchFloor(floor){
|
||||
if (slider) {
|
||||
bindModalSlider(slider, document.getElementById("modal-slider-label"),
|
||||
wert => wert + " °C");
|
||||
const stand = mqttData["Raumtemp"]?.[teile[0]]?.[teile[1]]?.["Set Temp[degC]"];
|
||||
const stand = mqttZweig(eintrag?.thermostat)?.["Set Temp[degC]"];
|
||||
slider.value = typeof stand !== "undefined" ? stand : 10;
|
||||
// Nur "input": das zeichnet die Anzeige, schickt aber nichts.
|
||||
slider.dispatchEvent(new Event("input"));
|
||||
@@ -345,7 +366,7 @@ function switchFloor(floor){
|
||||
// Fahrt aufmacht, saehe sonst den Stand von davor und nie wieder
|
||||
// etwas anderes: gezeichnet wird nur beim Oeffnen.
|
||||
koerper.querySelectorAll(".raum-geraet").forEach(k => jalousieVerfolgen(k, null));
|
||||
raumMesswerteAktualisieren(teile[0], teile[1]);
|
||||
raumMesswerteAktualisieren(eintrag?.thermostat);
|
||||
})
|
||||
.catch(fehler => { koerper.innerHTML = "Konnte den Raum nicht laden: " + fehler.message; });
|
||||
}
|
||||
@@ -504,8 +525,8 @@ function switchFloor(floor){
|
||||
* Der Browser hoert ohnehin schon auf Raumtemp/#, und ein Wert aus der
|
||||
* Datenbank waere neben dem Regler nur ein Stand von vorhin.
|
||||
*/
|
||||
function raumMesswerteAktualisieren(etage, raum) {
|
||||
const werte = mqttData["Raumtemp"]?.[etage]?.[raum];
|
||||
function raumMesswerteAktualisieren(thermostat) {
|
||||
const werte = mqttZweig(thermostat);
|
||||
if (!werte) return;
|
||||
document.querySelectorAll("#roomView [data-mqtt]").forEach(feld => {
|
||||
const wert = werte[feld.dataset.mqtt];
|
||||
|
||||
@@ -498,7 +498,7 @@ function kachelWertZeile(wert, i, kachel) {
|
||||
// Ohne Treffer beim ersten Geraet des eigenen Raums beginnen, sonst beim
|
||||
// ersten ueberhaupt - ein neuer Wert soll nicht im Nachbargeschoss starten.
|
||||
const ersterEigener = katalog.findIndex(
|
||||
(g) => kachel && g.floorKey === kachel.floor && g.raumKey === kachel.name);
|
||||
(g) => kachel && g.raumKey === kachel.nr);
|
||||
const gi = treffer ? treffer.gi : Math.max(0, ersterEigener);
|
||||
const wi = treffer ? treffer.wi : -1;
|
||||
|
||||
@@ -512,7 +512,9 @@ function kachelWertZeile(wert, i, kachel) {
|
||||
* in der gefilterten Liste - sonst zeigte die Auswahl nach dem Umsortieren
|
||||
* auf ein anderes Geraet.
|
||||
*/
|
||||
const eigen = (g) => kachel && g.floorKey === kachel.floor && g.raumKey === kachel.name;
|
||||
// Ueber die feste Raumnummer, nicht ueber den Namen - "Bad" gibt es auf
|
||||
// drei Etagen, und ein umbenannter Raum bliebe sonst ohne eigene Geraete.
|
||||
const eigen = (g) => kachel && g.raumKey === kachel.nr;
|
||||
const option = (g, index) => '<option value="' + index + '"'
|
||||
+ (index === gi ? " selected" : "") + ">"
|
||||
+ textSchuetzen(g.label + (g.raum && !eigen(g) ? " – " + g.raum : "")) + "</option>";
|
||||
|
||||
Reference in New Issue
Block a user