Heizstab- und Bewaesserungsfenster im neuen Look, Bewaesserungszeilen enger
Beide Fenster lesen den Zustand live aus MQTT und uebernehmen jede Wahl sofort (bedienfenster.js). submitFormAjax entfaellt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+100
-58
@@ -1,66 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* Heizstab im Pufferspeicher.
|
||||
*
|
||||
* GET das Bedienfenster (Werte und Logik: js/solar/bedienfenster.js)
|
||||
* POST setMode=0 Automatik: der SolarManager regelt nach Überschuss
|
||||
* POST setMode=1..60 feste Leistung in 100 W (60 = 6,0 kW)
|
||||
*
|
||||
* Seit September 2026 gilt jede Änderung sofort, ohne "Save changes". Die
|
||||
* Antwort ist leer, wenn der Befehl beim Heizstab ankam, sonst steht dort
|
||||
* eine Meldung für das Fenster.
|
||||
*/
|
||||
|
||||
require_once("../helper.php");
|
||||
|
||||
$hostname = "192.168.179.169";
|
||||
|
||||
if (checkLogin()) {
|
||||
$close = 0;
|
||||
$hostname = "192.168.179.169";
|
||||
|
||||
if (!checkLogin()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST["setMode"]) || isset($_GET["setMode"])) {
|
||||
/*
|
||||
* Der Wert kommt aus dem Formular (POST) oder von Hand aus der
|
||||
* Adresse (GET) - immer nur einer von beiden. Frueher wurden beide
|
||||
* addiert; der fehlende erzeugte eine PHP-Warnung, und die stand dann
|
||||
* als Meldung im Browser.
|
||||
*
|
||||
* 0 = Automatik (Ueberschuss), 1..60 = feste Leistung in 100 W. Der
|
||||
* Regler reicht bis 60; die alte Pruefung "< 60" liess genau 6,0 kW
|
||||
* still nicht durch.
|
||||
*/
|
||||
$stufe = intval($_POST["setMode"] ?? $_GET["setMode"] ?? 0);
|
||||
if ($stufe >= 1 && $stufe <= 60) {
|
||||
$pfad = "/set?mode=man&pwr=" . ($stufe * 100);
|
||||
} elseif ($stufe === 0) {
|
||||
$pfad = "/set?mode=eco&pwr=0";
|
||||
} else {
|
||||
$pfad = null;
|
||||
}
|
||||
if ($pfad !== null) {
|
||||
$remote = @fsockopen("tcp://" . $hostname, 80, $errno, $errstr, 5);
|
||||
if ($remote) {
|
||||
fwrite($remote, "GET " . $pfad . " HTTP/1.1\r\nHost: " . $hostname . "\r\nConnection: close\r\n\r\n");
|
||||
stream_set_timeout($remote, 5);
|
||||
fread($remote, 1024);
|
||||
fclose($remote);
|
||||
} else {
|
||||
// Ohne Verbindung eine verstaendliche Meldung statt eines PHP-Fehlers.
|
||||
// Bewusst Status 200: submitFormAjax() in common.js zeigt die
|
||||
// Antwort nur dann als Meldung an.
|
||||
echo "Der Heizstab ist nicht erreichbar.";
|
||||
}
|
||||
}
|
||||
$close = 1;
|
||||
if (isset($_POST["setMode"]) || isset($_GET["setMode"])) {
|
||||
// Der Wert kommt aus dem Fenster (POST) oder von Hand aus der Adresse
|
||||
// (GET) - immer nur einer von beiden.
|
||||
$stufe = intval($_POST["setMode"] ?? $_GET["setMode"] ?? 0);
|
||||
if ($stufe >= 1 && $stufe <= 60) {
|
||||
$pfad = "/set?mode=man&pwr=" . ($stufe * 100);
|
||||
} elseif ($stufe === 0) {
|
||||
$pfad = "/set?mode=eco&pwr=0";
|
||||
} else {
|
||||
echo "Unbekannte Leistungsstufe.";
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
$close = 1;
|
||||
}
|
||||
if (!$close) {
|
||||
echo <<<ENDE
|
||||
<!--begin::Form-->
|
||||
<form id="heater_form">
|
||||
<div class="col-sm-11">
|
||||
<div class="form-check">
|
||||
<label class="form-label" for="addedCharge">Leistung: </label>
|
||||
<div style="font-size: 15px;color: #297195;display: inline-block;" id="modal-slider-label">0</div>
|
||||
<input type="range" id="modal-slider" name="setMode" class="form-range range-color-track" min="0" max="60" />
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">Auto</span>
|
||||
<span class="max-amount f-16 font-weight-normal darkGray-color text-right mt-1">6.0 kW</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
ENDE;
|
||||
$remote = @fsockopen("tcp://" . $hostname, 80, $errno, $errstr, 5);
|
||||
if ($remote) {
|
||||
fwrite($remote, "GET " . $pfad . " HTTP/1.1\r\nHost: " . $hostname . "\r\nConnection: close\r\n\r\n");
|
||||
stream_set_timeout($remote, 5);
|
||||
fread($remote, 1024);
|
||||
fclose($remote);
|
||||
} else {
|
||||
echo "Der Heizstab ist nicht erreichbar.";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div class="lade heiz">
|
||||
<div class="lade-links">
|
||||
<div class="lade-status">
|
||||
<div class="heiz-tank" aria-hidden="true">
|
||||
<svg viewBox="0 0 80 120">
|
||||
<defs><clipPath id="heiz-innen"><rect x="14" y="8" width="52" height="100" rx="20"/></clipPath></defs>
|
||||
<g clip-path="url(#heiz-innen)">
|
||||
<rect x="0" y="0" width="80" height="42" data-heiz="t0"/>
|
||||
<rect x="0" y="42" width="80" height="34" data-heiz="t1"/>
|
||||
<rect x="0" y="76" width="80" height="44" data-heiz="t2"/>
|
||||
</g>
|
||||
<rect x="14" y="8" width="52" height="100" rx="20" class="heiz-huelle"/>
|
||||
<path d="M26 103l4-6 4 6 4-6 4 6 4-6 4 6 4-6" class="heiz-spirale" data-heiz="spirale"/>
|
||||
<path d="M26 108v7M54 108v7" class="heiz-huelle"/>
|
||||
<text x="40" y="30" data-heiz="tt0">–</text>
|
||||
<text x="40" y="63" data-heiz="tt1">–</text>
|
||||
<text x="40" y="90" data-heiz="tt2" class="klein">–</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="lade-text">
|
||||
<div class="lade-auto">Pufferspeicher <span data-heiz="pille" class="lade-pille"></span></div>
|
||||
<div class="lade-gross" data-heiz="leistung">–</div>
|
||||
<div class="lade-zeile" data-heiz="temps"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lade-erklaerung" data-heiz="erklaerung"></div>
|
||||
</div>
|
||||
|
||||
<div class="lade-rechts">
|
||||
<div class="lade-abschnitt">
|
||||
<h3 id="heiz-modus">Wie heizen?</h3>
|
||||
<div class="lade-modi zwei" role="radiogroup" aria-labelledby="heiz-modus">
|
||||
<button type="button" class="lade-modus" role="radio" aria-checked="false" data-heiz-modus="auto" style="--c:#f7c000">
|
||||
<span class="lade-sym"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg></span>
|
||||
<b>Automatik</b><span>heizt mit dem Überschuss der Anlage</span>
|
||||
</button>
|
||||
<button type="button" class="lade-modus" role="radio" aria-checked="false" data-heiz-modus="fest" style="--c:#e5624f">
|
||||
<span class="lade-sym"><svg viewBox="0 0 24 24"><path d="M12 3c3 4 5 6.5 5 10a5 5 0 0 1-10 0c0-2 1-3.5 2-4.5.3 1.5 1 2.5 2 3 0-3 .5-5.5 1-8.5z"/></svg></span>
|
||||
<b>Fest</b><span>eingestellte Leistung, auch aus dem Netz</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lade-planung" data-heiz="fest" hidden>
|
||||
<div>
|
||||
<div class="lade-plan-zeile">
|
||||
<label for="heiz-regler">Leistung</label>
|
||||
<output data-heiz="reglerAusgabe"></output>
|
||||
</div>
|
||||
<input type="range" id="heiz-regler" data-heiz="regler" min="1" max="60" step="1" value="30" class="heiz-regler">
|
||||
<div class="lade-marken"><span>0,1 kW</span><span>3 kW</span><span>6 kW</span></div>
|
||||
</div>
|
||||
<div class="lade-chips" role="group" aria-label="Schnellwahl">
|
||||
<button type="button" class="lade-chip" aria-pressed="false" data-heiz-stufe="10">1 kW</button>
|
||||
<button type="button" class="lade-chip" aria-pressed="false" data-heiz-stufe="20">2 kW</button>
|
||||
<button type="button" class="lade-chip" aria-pressed="false" data-heiz-stufe="30">3 kW</button>
|
||||
<button type="button" class="lade-chip" aria-pressed="false" data-heiz-stufe="60">6 kW</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lade-meldung" data-heiz="meldung" aria-live="polite">Änderungen gelten sofort</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+49
-51
@@ -73,64 +73,62 @@ if (!checkLogin()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Zonen des Modals. Die Reihenfolge bestimmt die Reihenfolge der Karten, die
|
||||
// Keys muessen zu wateringZones in js/solar/solarMQTT.js passen.
|
||||
// Zonen des Fensters. Die Reihenfolge bestimmt die Reihenfolge der Karten;
|
||||
// die Keys muessen zu wateringZones in js/solar/bewaesserungAnzeige.js passen,
|
||||
// "bild" zu ZONENBILDER in js/solar/energiefluss.js. "dauern" sind die
|
||||
// Schnellwahlen in Minuten, die erste ist die Vorgabe.
|
||||
$zonen = [
|
||||
["key" => "troughs", "label" => "Tröge", "minuten" => 5],
|
||||
["key" => "raisedBeds", "label" => "Beete", "minuten" => 30],
|
||||
["key" => "frontGarden", "label" => "Vorn", "minuten" => 30],
|
||||
["key" => "troughs", "label" => "Tröge", "bild" => "kuebel", "dauern" => [5, 10, 15, 30]],
|
||||
["key" => "raisedBeds", "label" => "Beete", "bild" => "hochbeet", "dauern" => [30, 15, 45, 60]],
|
||||
["key" => "frontGarden", "label" => "Vorn", "bild" => "garten", "dauern" => [30, 15, 45, 60]],
|
||||
];
|
||||
|
||||
echo <<<HTML
|
||||
<div class="p-3">
|
||||
<div id="watering-feedback" class="alert d-none mb-3" role="status"></div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div class="fw-semibold mb-3">Automatik</div>
|
||||
<div class="d-grid gap-2 mb-3">
|
||||
<button type="button" class="btn btn-outline-primary" data-watering-auto-toggle data-watering-auto="Trog,Hoch" data-watering-topics="Gartenwasser/vorn,Gartenwasser/hinten" data-watering-label="Tröge und Hochbeete">Tröge und Hochbeete</button>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm flex-fill" data-watering-auto-toggle data-watering-auto="Trog" data-watering-topic="Gartenwasser/vorn" data-watering-label="Tröge">Tröge</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm flex-fill" data-watering-auto-toggle data-watering-auto="Hoch" data-watering-topic="Gartenwasser/hinten" data-watering-label="Hochbeete">Hochbeete</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm flex-fill" data-watering-auto-toggle data-watering-auto="Vorn" data-watering-topic="Gartenwasser/vorn" data-watering-label="Garten vorn">Garten vorn</button>
|
||||
// Die Abläufe der Ventilsteuerung (Topic .../auto). Mehrere Einträge in
|
||||
// "modi" starten bzw. stoppen gemeinsam.
|
||||
$ablaeufe = [
|
||||
["label" => "Tröge + Beete", "modi" => ["Gartenwasser/vorn" => "Trog", "Gartenwasser/hinten" => "Hoch"]],
|
||||
["label" => "Tröge", "modi" => ["Gartenwasser/vorn" => "Trog"]],
|
||||
["label" => "Beete", "modi" => ["Gartenwasser/hinten" => "Hoch"]],
|
||||
["label" => "Vorn", "modi" => ["Gartenwasser/vorn" => "Vorn"]],
|
||||
];
|
||||
?>
|
||||
<div class="lade wasser">
|
||||
<div class="wasser-zonen">
|
||||
<?php foreach ($zonen as $zone):
|
||||
$dauern = $zone["dauern"];
|
||||
sort($dauern); ?>
|
||||
<div class="wasser-zone" data-zone="<?= $zone["key"] ?>" data-dauer="<?= $zone["dauern"][0] ?>">
|
||||
<div class="wasser-kopf">
|
||||
<span class="wasser-bild" data-bild="<?= $zone["bild"] ?>" aria-hidden="true"></span>
|
||||
<div class="wasser-titel">
|
||||
<b><?= htmlspecialchars($zone["label"]) ?></b>
|
||||
<span data-w="zustand">–</span>
|
||||
</div>
|
||||
<span class="lade-pille" data-w="pille"></span>
|
||||
</div>
|
||||
<div class="small text-muted">
|
||||
Startet die Ventilfolge von Hand. Die Regenautomatik läuft davon
|
||||
unabhängig zum Sonnenaufgang; ob eine Zone dabei schon versorgt
|
||||
wurde, steht unten bei „Heute“.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
foreach ($zonen as $zone) {
|
||||
$key = $zone["key"];
|
||||
$label = $zone["label"];
|
||||
$minuten = $zone["minuten"];
|
||||
echo <<<HTML
|
||||
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="fw-semibold">$label</span>
|
||||
<span class="badge bg-secondary" data-watering-state="$key">unbekannt</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mb-2">
|
||||
<div class="input-group input-group-sm" style="max-width: 7.5rem;">
|
||||
<input class="form-control" type="number" min="1" max="120" value="$minuten" data-watering-timer="$key" aria-label="Dauer in Minuten für $label">
|
||||
<span class="input-group-text">Min.</span>
|
||||
<div class="wasser-fuss">
|
||||
<div class="lade-chips" role="group" aria-label="Dauer für <?= htmlspecialchars($zone["label"]) ?>">
|
||||
<?php foreach ($dauern as $min): ?>
|
||||
<button type="button" class="lade-chip" aria-pressed="false" data-min="<?= $min ?>"><?= $min ?> min</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success px-4 ms-auto" data-watering-toggle data-watering-zone="$key">Ein</button>
|
||||
</div>
|
||||
<div class="small text-muted">
|
||||
Zuletzt <span data-watering-last="$key">--</span> · <span data-watering-duration="$key">--</span><br>
|
||||
Heute <span data-watering-today="$key">--</span> · Vortag <span data-watering-prevday="$key">--</span>
|
||||
<button type="button" class="lade-start wasser-knopf" data-w="knopf"><span class="lade-punkt"></span><span data-w="knopfText">Gießen</span></button>
|
||||
</div>
|
||||
<div class="wasser-info" data-w="info"></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
echo "\n</div>\n";
|
||||
<div class="lade-abschnitt">
|
||||
<h3>Abläufe</h3>
|
||||
<div class="lade-chips wasser-ablaeufe">
|
||||
<?php foreach ($ablaeufe as $ablauf): ?>
|
||||
<button type="button" class="lade-chip" aria-pressed="false"
|
||||
data-ablauf="<?= htmlspecialchars(json_encode($ablauf["modi"], JSON_UNESCAPED_SLASHES)) ?>"><?= htmlspecialchars($ablauf["label"]) ?></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="lade-erklaerung">Ein Ablauf gießt die Zonen nacheinander – antippen startet, nochmal antippen stoppt. Die Regenautomatik läuft davon unabhängig zum Sonnenaufgang.</div>
|
||||
</div>
|
||||
|
||||
<div class="lade-meldung" data-w="meldung" aria-live="polite">Befehle gehen sofort an die Ventilsteuerung</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user