Raum-Modal: Bedienelemente statt Kommandoliste
Das Modal zeigte jedes Kommando so, wie es in der Datenbank steht: eine
Jalousie kam mit acht Rohbefehlen daher, darunter "Winken", die Farbe einer
Lampe als drei Zahlenfelder 0-255, ein Stromzaehler als abgeschnittene
Textzeile. Die Solltemperatur stand doppelt da - einmal als Schieberegler,
einmal als Zahlenfeld der Thermostat-Karte.
Jetzt entscheidet restricted/roomControls.php, welches Geraet welches
Bedienelement bekommt, und zwar an seinen Faehigkeiten statt am Typnamen:
hat es ein "setClosure"? ein An/Aus-Paar? drei Parameter rot/gruen/blau?
Damit bekommt auch ein neu gefundenes Geraet sein passendes Element, ohne
dass jemand einen Typnamen nachtraegt.
Beschattung Auf/Stop/Zu, darunter Position und Neigung als Schieber
auf dem zuletzt gemeldeten Stand; "Winken" und
"my-Position" im Mehr-Menue
Licht Kippschalter, Helligkeit, Farbwaehler des Browsers,
Effekt und Preset als Auswahl
Schalten ein Kippschalter statt dreier Knoepfe
Messwerte Wertegitter, die sechs wichtigsten sichtbar - beim
Wasserzaehler standen vorher MAC-Adresse und freier
Speicher vorn und der Verbrauch hinter "12 weitere"
Heizung nur noch der Schieberegler, daneben Ist-Temperatur und
Feuchte live aus dem MQTT-Strom
Ab zwei Geraeten einer Art ordnet eine Ueberschrift; darunter waere sie
nur Aufwand. Schieberegler schicken beim Loslassen, nicht beim Ziehen -
sonst bekaeme eine Jalousie bei jedem Pixel ein neues Ziel. Waehrend ein
Kommando unterwegs ist, sperrt sich die Karte sichtbar: ein "Zu" dauert
ueber eine Minute, und ohne Sperre tippt man in der Zeit nach.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+100
-6
@@ -208,13 +208,95 @@ function switchFloor(floor){
|
||||
// eine Falle.
|
||||
btn.hidden = !slider;
|
||||
|
||||
koerper.querySelectorAll("button[data-cmd]").forEach(k => {
|
||||
k.addEventListener("click", () => schalte(k));
|
||||
});
|
||||
raumBedienungAktivieren(koerper);
|
||||
raumMesswerteAktualisieren(teile[0], teile[1]);
|
||||
})
|
||||
.catch(fehler => { koerper.innerHTML = "Konnte den Raum nicht laden: " + fehler.message; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Bedienelemente des Raum-Modals mit ihren Kommandos verbinden.
|
||||
*
|
||||
* Welches Geraet welches Element bekommt, entscheidet der Server
|
||||
* (restricted/roomControls.php); hier haengen nur die Zuhoerer an den
|
||||
* data-Attributen, die er dabei setzt.
|
||||
*/
|
||||
function raumBedienungAktivieren(koerper) {
|
||||
koerper.querySelectorAll("button[data-cmd]").forEach(k => {
|
||||
k.addEventListener("click", () => schalte(k));
|
||||
});
|
||||
|
||||
// Schieberegler: waehrend des Ziehens nur die Beschriftung, geschickt
|
||||
// wird erst beim Loslassen. Sonst bekaeme eine Jalousie bei jedem Pixel
|
||||
// ein neues Ziel und kaeme aus dem Anfahren nicht mehr heraus.
|
||||
koerper.querySelectorAll(".raum-regler").forEach(regler => {
|
||||
const schieber = regler.querySelector("input[type=range]");
|
||||
const anzeige = regler.querySelector(".raum-regler-wert");
|
||||
const einheit = schieber.dataset.einheit || "";
|
||||
schieber.addEventListener("input", () => { anzeige.textContent = schieber.value + einheit; });
|
||||
schieber.addEventListener("change", () => {
|
||||
const params = {};
|
||||
params[regler.dataset.param] = schieber.value;
|
||||
raumKommando(Number(regler.dataset.cmd), params, regler);
|
||||
});
|
||||
});
|
||||
|
||||
// Kippschalter: An und Aus sind zwei getrennte Kommandos. Kennt das
|
||||
// Geraet nur "umschalten", tut es auch das - dann stimmt die Stellung
|
||||
// hinterher, weil wir sie selbst gesetzt haben.
|
||||
koerper.querySelectorAll(".raum-schalter").forEach(schalter => {
|
||||
const kasten = schalter.querySelector("input[type=checkbox]");
|
||||
const beschriftung = schalter.querySelector("label");
|
||||
kasten.addEventListener("change", () => {
|
||||
const ziel = kasten.checked ? schalter.dataset.ein : schalter.dataset.aus;
|
||||
const cmd = ziel || schalter.dataset.um;
|
||||
beschriftung.textContent = kasten.checked ? "An" : "Aus";
|
||||
if (!cmd) return;
|
||||
raumKommando(Number(cmd), {}, schalter);
|
||||
});
|
||||
});
|
||||
|
||||
// Farbe: der Browser bringt seinen Farbwaehler mit, das Geraet will drei
|
||||
// Zahlen 0-255. Zerlegt wird deshalb erst hier.
|
||||
koerper.querySelectorAll(".raum-farbe").forEach(feld => {
|
||||
const eingabe = feld.querySelector("input[type=color]");
|
||||
eingabe.addEventListener("change", () => {
|
||||
const hex = eingabe.value;
|
||||
const params = {};
|
||||
params[feld.dataset.red] = parseInt(hex.substr(1, 2), 16);
|
||||
params[feld.dataset.green] = parseInt(hex.substr(3, 2), 16);
|
||||
params[feld.dataset.blue] = parseInt(hex.substr(5, 2), 16);
|
||||
raumKommando(Number(feld.dataset.cmd), params, feld);
|
||||
});
|
||||
});
|
||||
|
||||
// Auswahllisten, die ohne zusaetzlichen Knopf schalten - Effekt, Preset.
|
||||
koerper.querySelectorAll("select.raum-sofort").forEach(auswahl => {
|
||||
auswahl.addEventListener("change", () => {
|
||||
const params = {};
|
||||
params[auswahl.dataset.param] = auswahl.value;
|
||||
raumKommando(Number(auswahl.dataset.cmd), params, auswahl);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Ist-Werte im Heizungsteil aus dem laufenden MQTT-Strom fuellen.
|
||||
*
|
||||
* 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];
|
||||
if (!werte) return;
|
||||
document.querySelectorAll("#roomView [data-mqtt]").forEach(feld => {
|
||||
const wert = werte[feld.dataset.mqtt];
|
||||
if (typeof wert !== "undefined") feld.textContent = wert;
|
||||
});
|
||||
const heizt = document.querySelector("#roomView [data-mqtt-heizung]");
|
||||
if (heizt) heizt.classList.toggle("d-none", String(werte["Heating"]) !== "true");
|
||||
}
|
||||
|
||||
/** Ein Kommando des angeklickten Knopfes ausfuehren. */
|
||||
function schalte(knopf) {
|
||||
const zeile = knopf.closest("[data-cmdrow]");
|
||||
@@ -222,10 +304,22 @@ function switchFloor(floor){
|
||||
if (zeile) {
|
||||
zeile.querySelectorAll("[data-param]").forEach(f => { params[f.dataset.param] = f.value; });
|
||||
}
|
||||
knopf.disabled = true;
|
||||
raumRequest("command", { command_id: Number(knopf.dataset.cmd), params: params })
|
||||
raumKommando(Number(knopf.dataset.cmd), params, knopf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Kommando schicken und die Karte so lange sperren.
|
||||
*
|
||||
* Ein "Zu" an einer Jalousie dauert ueber eine Minute (die Mechanik will
|
||||
* zweimal geschwenkt werden, siehe restricted/commands.php). Ohne sichtbare
|
||||
* Sperre tippt man in der Zeit dreimal nach.
|
||||
*/
|
||||
function raumKommando(cmdId, params, element) {
|
||||
const karte = element.closest(".raum-geraet") || element;
|
||||
karte.classList.add("raum-warte");
|
||||
raumRequest("command", { command_id: cmdId, params: params })
|
||||
.then(antwort => {
|
||||
knopf.disabled = false;
|
||||
karte.classList.remove("raum-warte");
|
||||
raumMeldung(antwort);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user