Geraete den Raeumen zuordnen
Beim Anlegen einer Automatik denkt man in Raeumen ("im Bad soll ..."), nicht
in Geraetearten. Ein Raummodell gibt es schon - restricted/rooms.php, die
einzige Quelle fuer die Home-Ansicht -, nur fehlte die Zuordnung Geraet ->
Raum.
Die neue Spalte actors.room haelt sie als "Etage/Raum" (OG/Bad), dazu
"aussen" fuer Carport, Garage und Regensensor. Etage und Raum zusammen,
weil "Bad" allein auf drei Etagen vorkommt. Discovery fasst die Spalte nicht
an - der Upsert setzt nur type und name -, die Zuordnung ueberlebt also
jeden Suchlauf.
Zugeordnet wird ueber das Haus-Symbol in der Karte "Automatismen". Wo der
Raum aus dem MQTT-Topic hervorgeht ("Raumtemp/OG/Bad/Temp[degC]"), schlaegt
die Ansicht ihn vor und uebernimmt ihn auf Knopfdruck - das sind die
dreizehn Thermostate, ohne jedes Raten. Bei allen anderen wird bewusst nicht
geraten: "Bad Links" sagt nichts darueber, auf welcher der drei Etagen
dieses Bad liegt. Noch nicht zugeordnete Geraete stehen in der Tabelle oben.
Die Geraeteauswahl im Editor gruppiert danach nach Raum, in der Reihenfolge
aus rooms.php. Solange niemand zugeordnet hat, bleibt es bei der Gruppierung
nach Geraeteart - eine einzige Gruppe "Nicht zugeordnet" waere ein
Rueckschritt. Und weil auch nach der ersten Zuordnung noch viel ohne Raum
ist, wird dieser Rest weiter nach Geraeteart unterteilt ("Ohne Raum ·
Aussenjalousie (11)").
Anders als bei den Gerätearten behalten Raeume mit nur einem Geraet ihre
Ueberschrift: "OG · Bad" ist auch mit einem einzigen Thermostat genau die
Zeile, die man sucht - und mehr als eines haengt selten in einem Raum.
Die dreizehn Thermostate sind bereits zugeordnet, weil das ihre eigenen
Topics hergeben; alles andere steht auf "-" und will von Hand vergeben
werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+111
-1
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . "/mysql.php");
|
||||
require_once(__DIR__ . "/rooms.php");
|
||||
|
||||
// Geraete, die zu keinem Raum der Wohnung gehoeren - Carport, Garage,
|
||||
// Regensensor. Kein Raum in rooms.php, aber auch nicht "unzugeordnet".
|
||||
const RAUM_AUSSEN = "aussen";
|
||||
|
||||
/** Verbindung zur Geraete- und Automatik-Datenbank. */
|
||||
function meshDb()
|
||||
@@ -210,6 +215,109 @@ function anzeigeName($name)
|
||||
return trim(preg_replace('/\s+/', ' ', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waehlbare Raeume: die Raeume der Home-Ansicht plus "Aussen".
|
||||
*
|
||||
* Einzige Quelle bleibt restricted/rooms.php - ein neuer Raum ist dort eine
|
||||
* Zeile und taucht hier automatisch auf. Der Schluessel ist "Etage/Raum",
|
||||
* weil "Bad" allein auf drei Etagen vorkommt.
|
||||
*/
|
||||
function raumListe()
|
||||
{
|
||||
$liste = [];
|
||||
foreach ($GLOBALS["rooms"] as $raum) {
|
||||
$liste[] = [
|
||||
"key" => $raum["floor"] . "/" . $raum["mqtt"],
|
||||
"label" => $raum["floor"] . " · " . $raum["mqtt"],
|
||||
];
|
||||
}
|
||||
$liste[] = ["key" => RAUM_AUSSEN, "label" => "Außen"];
|
||||
return $liste;
|
||||
}
|
||||
|
||||
/** Anzeigename eines gespeicherten Raumschluessels. */
|
||||
function raumBeschriftung($key)
|
||||
{
|
||||
if (!$key) {
|
||||
return "Nicht zugeordnet";
|
||||
}
|
||||
foreach (raumListe() as $raum) {
|
||||
if ($raum["key"] === $key) {
|
||||
return $raum["label"];
|
||||
}
|
||||
}
|
||||
// Raum aus rooms.php entfernt - der Eintrag am Geraet bleibt stehen,
|
||||
// damit eine Umbenennung dort keine Zuordnung stillschweigend loescht.
|
||||
return $key . " (unbekannt)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Raumvorschlaege aus den MQTT-Topics.
|
||||
*
|
||||
* Die Thermostate tragen ihren Raum im Topic: "Raumtemp/OG/Bad/Temp[degC]".
|
||||
* Das ist keine Rateaufgabe, sondern dieselbe Schreibweise wie in rooms.php,
|
||||
* und deckt dreizehn Geraete ohne Zutun ab. Bei allen anderen wird bewusst
|
||||
* nicht geraten: "Bad Links" sagt nichts darueber, auf welcher der drei
|
||||
* Etagen dieses Bad liegt.
|
||||
*/
|
||||
function raumVorschlaege()
|
||||
{
|
||||
$bekannt = [];
|
||||
foreach (raumListe() as $raum) {
|
||||
$bekannt[strtolower($raum["key"])] = $raum["key"];
|
||||
}
|
||||
$res = meshDb()->query("SELECT actor_id, url FROM actor_states
|
||||
WHERE url LIKE 'Raumtemp/%/%/%'");
|
||||
$vorschlag = [];
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
$teile = explode("/", $row["url"]);
|
||||
if (count($teile) < 3) {
|
||||
continue;
|
||||
}
|
||||
$key = strtolower($teile[1] . "/" . $teile[2]);
|
||||
if (isset($bekannt[$key])) {
|
||||
$vorschlag[intval($row["actor_id"])] = $bekannt[$key];
|
||||
}
|
||||
}
|
||||
return $vorschlag;
|
||||
}
|
||||
|
||||
/** Raum je Geraet, wie gespeichert. */
|
||||
function geraeteRaeume()
|
||||
{
|
||||
$res = meshDb()->query("SELECT id, room FROM actors");
|
||||
$raeume = [];
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
$raeume[intval($row["id"])] = $row["room"];
|
||||
}
|
||||
return $raeume;
|
||||
}
|
||||
|
||||
/** Zuordnungen speichern. $zuordnung ist [actor_id => Raumschluessel|""]. */
|
||||
function saveRooms($zuordnung)
|
||||
{
|
||||
$db = meshDb();
|
||||
$erlaubt = array_column(raumListe(), "key");
|
||||
$stmt = $db->prepare("UPDATE actors SET room = ? WHERE id = ?");
|
||||
$anzahl = 0;
|
||||
foreach ($zuordnung as $actorId => $key) {
|
||||
$actorId = intval($actorId);
|
||||
$key = strval($key);
|
||||
if ($actorId <= 0) {
|
||||
continue;
|
||||
}
|
||||
if ($key !== "" && !in_array($key, $erlaubt, true)) {
|
||||
throw new InvalidArgumentException("Unbekannter Raum: " . $key);
|
||||
}
|
||||
$wert = $key === "" ? null : $key;
|
||||
$stmt->bind_param("si", $wert, $actorId);
|
||||
$stmt->execute();
|
||||
$anzahl++;
|
||||
}
|
||||
$stmt->close();
|
||||
return $anzahl;
|
||||
}
|
||||
|
||||
/**
|
||||
* id => Beschriftung fuer alle Geraete, geputzt und eindeutig.
|
||||
*
|
||||
@@ -256,7 +364,7 @@ function deviceCatalog()
|
||||
$devices = [];
|
||||
|
||||
$labels = geraeteBeschriftungen();
|
||||
$res = $db->query("SELECT id, name, type, url FROM actors");
|
||||
$res = $db->query("SELECT id, name, type, url, room FROM actors");
|
||||
$zeilen = [];
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
$zeilen[] = $row;
|
||||
@@ -271,6 +379,8 @@ function deviceCatalog()
|
||||
"label" => $labels[intval($row["id"])],
|
||||
"type" => $row["type"],
|
||||
"url" => $row["url"],
|
||||
"room" => $row["room"],
|
||||
"roomLabel" => raumBeschriftung($row["room"]),
|
||||
"states" => [],
|
||||
"commands" => [],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user