Was draussen haengt, stand als Pseudo-Raum "aussen" in automations.php:
"Geraete, die zu keinem Raum der Wohnung gehoeren - Carport, Garage,
Regensensor". Das waren inzwischen sechzehn Geraete in einem einzigen Topf,
der groesste ueberhaupt - in der Geraeteauswahl des Editors standen die fuenf
Carport-Wechselrichter, das Sonnensegel und das Garagentor unsortiert
nebeneinander.
Jetzt ist das Aussengelaende eine Etage wie OG, EG und UG, mit eigenen
Raeumen: Carport, Veranda, Pergola, Terrasse, Garage und Garten. Die Namen
stammen von den Geraeten selbst - die Hoymiles heissen seit jeher "Carport
1-6" und "Veranda OG2-4". Die achtzehn Geraete sind verteilt (die beiden
Ventilsteuerungen hatten noch gar keinen Raum und stehen jetzt im Garten,
zusammen mit dem Regensensor, der ihre Automatiken ausloest); "Ohne Raum"
faellt damit von acht auf sechs, und die sind es zu Recht.
AG ist eine Etage ohne Grundriss. Ihre Raeume haben kein x/y, es gibt ja
kein Bild, auf das eine Kachel zeigen koennte - ein Raum ohne Position war
schon immer vorgesehen. Das Menue und das SVG richten sich deshalb nach der
neuen floorsWithPlan(), die Zuordnung und die Automatiken nach $floors.
Bekommt der erste AG-Raum eine Kachel, erscheint die Etage von selbst auch
im Menue; es gibt keine zweite Liste, die man nachziehen muesste.
Die Etagen standen bisher an sechs Stellen noch einmal im Code. Jetzt gibt
es genau eine Liste, $floors in rooms.php, und alles andere leitet sich ab:
* automations.php prueft gegen $floors statt gegen eine eigene Whitelist
* ajax/AutoAction.php baut seine Etagen-Auswahl daraus
* home.php baut Reiter und Inhaltsbereiche in einer Schleife statt
dreimal fast dasselbe HTML
* header.php baut die Menuepunkte daraus
* switchTab() in homeMQTT.js liest die Reiter aus der Seite, statt OG, EG
und UG sechsmal aufzuzaehlen
* refreshAutomations() ebenso - eine feste Liste haette die vierte Etage
still ausgelassen, die Tabelle waere ohne Fehlermeldung leer geblieben
Dazu die ausgeschriebenen Namen in $floorLabels: das Kuerzel steht in URLs,
SVG-Ids und im MQTT-Baum, "Aussengelaende" nur als Titel am Menuepunkt und
am Reiter.
In der Datenbank ist das Enum um 'AG' erweitert; header.php laedt rooms.php
jetzt selbst, weil es vor home.php eingebunden wird.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
208 lines
10 KiB
PHP
208 lines
10 KiB
PHP
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<!--begin::Head-->
|
|
<?php
|
|
// Die Raumtabelle traegt die Etagen - das Menue baut daraus seine Punkte.
|
|
// Hier und nicht erst in home.php: der Kopf wird zuerst eingebunden.
|
|
require_once(__DIR__ . "/rooms.php");
|
|
|
|
// $_GET["action"] ist von index.php bereits auf eine gueltige Seite gesetzt.
|
|
if (!isset($_GET["floor"]))
|
|
$_GET["floor"] = "OG";
|
|
?>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>Smarthome control</title>
|
|
<!--begin::Accessibility Meta Tags-->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
|
<meta name="color-scheme" content="light dark" />
|
|
<meta name="theme-color" content="#007bff" media="(prefers-color-scheme: light)" />
|
|
<meta name="theme-color" content="#1a1a1a" media="(prefers-color-scheme: dark)" />
|
|
<link rel="icon" type="image/png" href="assets/img/favicon.png">
|
|
<!--end::Accessibility Meta Tags-->
|
|
|
|
<!--begin::Primary Meta Tags-->
|
|
<meta name="title" content="Smarthome control" />
|
|
<meta name="author" content="ColorlibHQ" />
|
|
<meta name="description" content="Smarthome control panel by m0." />
|
|
<meta name="keywords" content="smarthome dashboard, admin panel" />
|
|
<!--end::Primary Meta Tags-->
|
|
|
|
<!--begin::Accessibility Features-->
|
|
<!-- Skip links will be dynamically added by accessibility.js -->
|
|
<meta name="supported-color-schemes" content="light dark" />
|
|
<link rel="preload" href="./css/adminlte.min.css?v=2" as="style" />
|
|
<link rel="stylesheet" href="./css/solar.css?v=<?= filemtime("css/solar.css") ?>" />
|
|
<!--end::Accessibility Features-->
|
|
|
|
<!--begin::Fonts-->
|
|
<link rel="stylesheet" href="assets/fonts/font_poppins.css" media="print" onload="this.media='all'" />
|
|
<!--end::Fonts-->
|
|
|
|
<!--begin::Third Party Plugin(Bootstrap Icons)-->
|
|
<link rel="stylesheet" href="css/bootstrap-icons.min.css" />
|
|
<!--end::Third Party Plugin(Bootstrap Icons)-->
|
|
|
|
<!--begin::Required Plugin(AdminLTE)-->
|
|
<link rel="stylesheet" href="./css/adminlte.min.css?v=2" />
|
|
<!--end::Required Plugin(AdminLTE)-->
|
|
|
|
<!--begin::Karte (Leaflet) - nur auf Seiten mit Karte-->
|
|
<?php if ($page["leaflet"]): ?>
|
|
<link rel="stylesheet" href="css/leaflet.css" />
|
|
<?php endif; ?>
|
|
<!--end::Karte-->
|
|
|
|
|
|
</head>
|
|
<!--end::Head-->
|
|
<!--begin::Body-->
|
|
|
|
<body class="layout-fixed sidebar-expand-lg bg-body-tertiary" data-bs-theme="dark">
|
|
<!--begin::App Wrapper-->
|
|
<div class="app-wrapper">
|
|
<!--begin::Header-->
|
|
<nav class="app-header navbar navbar-expand bg-body">
|
|
<!--begin::Container-->
|
|
<div class="container-fluid">
|
|
<!--begin::Start Navbar Links-->
|
|
<ul class="navbar-nav">
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-lte-toggle="sidebar" href="#" role="button">
|
|
<i class="bi bi-list"></i>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<!--end::Start Navbar Links-->
|
|
|
|
<!--begin::End Navbar Links-->
|
|
<ul class="navbar-nav ms-auto">
|
|
<!--begin::Fullscreen Toggle-->
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="#" data-lte-toggle="fullscreen">
|
|
<i data-lte-icon="maximize" class="bi bi-arrows-fullscreen"></i>
|
|
<i data-lte-icon="minimize" class="bi bi-fullscreen-exit" style="display: none"></i>
|
|
</a>
|
|
</li>
|
|
<?php
|
|
if ($_SESSION["local"] == true)
|
|
echo "<li class='nav-item'><a class='nav-link' href='addUser.php'><i data-lte-icon='Add user' class='bi bi-person-add'></i></a></li>";
|
|
?>
|
|
<!--end::Fullscreen Toggle-->
|
|
</ul>
|
|
<!--end::End Navbar Links-->
|
|
</div>
|
|
<!--end::Container-->
|
|
</nav>
|
|
<!--end::Header-->
|
|
<!--begin::Sidebar-->
|
|
<aside class="app-sidebar bg-body-secondary shadow">
|
|
<!--begin::Sidebar Brand-->
|
|
<div class="sidebar-brand">
|
|
<!--begin::Brand Link-->
|
|
<a href="./index.php" class="brand-link">
|
|
<!--begin::Brand Image-->
|
|
<img src="./assets/img/AdminLTELogo.png" alt="Logo"
|
|
class="brand-image opacity-75 shadow" />
|
|
<!--end::Brand Image-->
|
|
<!--begin::Brand Text-->
|
|
<span class="brand-text fw-light">Smart controller</span>
|
|
<!--end::Brand Text-->
|
|
</a>
|
|
<!--end::Brand Link-->
|
|
</div>
|
|
<!--end::Sidebar Brand-->
|
|
<!--begin::Sidebar Wrapper-->
|
|
<div class="sidebar-wrapper">
|
|
<nav class="mt-2">
|
|
<!--begin::Sidebar Menu-->
|
|
<ul class="nav sidebar-menu flex-column" data-lte-toggle="treeview" role="navigation"
|
|
aria-label="Main navigation" data-accordion="false" id="navigation">
|
|
<li class="nav-item menu-open">
|
|
<a href="#" class="nav-link active">
|
|
<i class="nav-icon bi bi-speedometer"></i>
|
|
<p>
|
|
Dashboards
|
|
<i class="nav-arrow bi bi-chevron-right"></i>
|
|
</p>
|
|
</a>
|
|
<ul class="nav nav-treeview ps-4">
|
|
<li class="nav-item">
|
|
<a href="?action=solar" class="nav-link<?php if($_GET["action"]=="solar"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-brightness-alt-high"></i>
|
|
<p>Solar</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="?action=heat" class="nav-link <?php if($_GET["action"]=="heat"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-fire"></i>
|
|
<p>Heizung</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="?action=history" class="nav-link <?php if($_GET["action"]=="history"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-graph-up"></i>
|
|
<p>Historie</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="?action=weather" class="nav-link <?php if($_GET["action"]=="weather"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-cloud-sun"></i>
|
|
<p>Wetter</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="?action=skoda" class="nav-link <?php if($_GET["action"]=="skoda"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-ev-front"></i>
|
|
<p>Škoda</p>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-item menu-open">
|
|
<a href="#" class="nav-link active">
|
|
<i class="nav-icon bi bi-house"></i>
|
|
<p>
|
|
Home
|
|
<i class="nav-arrow bi bi-chevron-right"></i>
|
|
</p>
|
|
</a>
|
|
<!-- Nur Etagen mit Grundriss: ein Menuepunkt auf das
|
|
Aussengelaende fuehrte auf eine leere Zeichenflaeche.
|
|
Bekommt dessen erster Raum eine Kachel, steht es hier
|
|
von selbst. -->
|
|
<ul class="nav nav-treeview ps-4">
|
|
<?php foreach (floorsWithPlan() as $etage): ?>
|
|
<li class="nav-item">
|
|
<a href="?action=home&floor=<?= $etage ?>" title="<?= htmlspecialchars(floorLabel($etage)) ?>"
|
|
class="nav-link <?php if($_GET["action"]=="home" && $_GET["floor"] == $etage){echo " active";} ?>">
|
|
<p> <?= $etage ?></p>
|
|
</a>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</li>
|
|
<!-- Einstellungen stehen fuer sich: kein Dashboard,
|
|
sondern die Parameter dahinter. Genauso die
|
|
Protokolle - sie zeigen nicht das Haus, sondern
|
|
die Prozesse, die es steuern. -->
|
|
<li class="nav-item">
|
|
<a href="?action=settings" class="nav-link<?php if($_GET["action"]=="settings"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-gear"></i>
|
|
<p>Einstellungen</p>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="?action=logs" class="nav-link<?php if($_GET["action"]=="logs"){echo " active";} ?>">
|
|
<i class="nav-icon bi bi-journal-text"></i>
|
|
<p>Protokolle</p>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<!--end::Sidebar Menu-->
|
|
</nav>
|
|
</div>
|
|
<!--end::Sidebar Wrapper-->
|
|
</aside>
|
|
<!--end::Sidebar-->
|