Files
Smart-Dashboard/ajax/watering.php
T
adminandClaude Opus 5 97b5c78fda Bewaesserungsanzeige loest sich vom alten Regenskript
Die Anzeigen im Realtime-SVG und im Bewaesserungs-Modal lasen ihre
Vorschau aus Gartenwasser/AutoWatering/<zone>/RainStatus, das
auto_watering.py stuendlich veroeffentlicht hat. Solange das so blieb,
konnte das Skript nicht abgeschaltet werden, obwohl die Entscheidung
laengst in den Automatiken des Runners steht - und dessen Schwellen
haetten dann neben denen im Skript gestanden, ohne dass ein Unterschied
auffaellt.

Statt des Plans zeigen die Anzeigen jetzt, ob die Zone heute schon
gelaufen ist. Die Regenautomatik loest zum Sonnenaufgang aus; wer
spaeter auf das Dashboard schaut, will ohnehin wissen, was passiert ist,
nicht was vorgesehen war. Die Angabe kommt aus dem retained
WateringToday der Ventilsteuerung, das die Karte schon fuer "Heute"
auswertet - eine Bewaesserung von Hand zaehlt damit genauso, was hier
richtig ist.

Im SVG steht dafuer ein Haekchen statt der Stoppuhr, das Schild im
Modal sagt "heute bewaessert" statt "heute geplant", und die
Planungszeilen in der Automatik-Karte entfallen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 11:33:15 +02:00

137 lines
5.3 KiB
PHP

<?php
require_once("./phpMQTT.php");
require_once("../helper.php");
if ($_SERVER["REQUEST_METHOD"] === "POST") {
header("Content-Type: application/json; charset=utf-8");
if (!checkLogin()) {
http_response_code(401);
echo json_encode(["success" => false, "message" => "Nicht angemeldet."]);
exit;
}
$topic = $_POST["topic"] ?? "";
$payload = $_POST["payload"] ?? "";
$allowedTopics = [
"Gartenwasser/vorn/set",
"Gartenwasser/vorn/auto",
"Gartenwasser/hinten/set",
"Gartenwasser/hinten/auto"
];
if (!in_array($topic, $allowedTopics, true)) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Nicht erlaubtes MQTT-Topic."]);
exit;
}
if (str_ends_with($topic, "/set")) {
$command = json_decode($payload, true);
$validValve = is_array($command)
&& isset($command["valve"], $command["set"])
&& in_array((int) $command["valve"], [1, 6], true)
&& in_array($command["set"], ["open", "close"], true);
if ($validValve && $command["set"] === "open") {
$validValve = isset($command["timer"])
&& is_numeric($command["timer"])
&& (int) $command["timer"] >= 1
&& (int) $command["timer"] <= 120;
}
if (!$validValve) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Ungültiger Ventilbefehl."]);
exit;
}
$payload = json_encode($command, JSON_THROW_ON_ERROR);
} elseif (!in_array($payload, ["Hoch", "Vorn", "Trog", "Stop"], true)) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Ungültiger Automatikbefehl."]);
exit;
}
try {
$mqtt = new Bluerhinos\phpMQTT("localhost", 1883, "WateringWeb-" . bin2hex(random_bytes(4)));
if (!$mqtt->connect(true, null, "", "")) {
http_response_code(503);
echo json_encode(["success" => false, "message" => "MQTT-Broker nicht erreichbar."]);
exit;
}
$mqtt->publish($topic, $payload, 0, false);
$mqtt->close();
} catch (Throwable $error) {
http_response_code(503);
echo json_encode(["success" => false, "message" => "MQTT-Fehler: " . $error->getMessage()]);
exit;
}
echo json_encode(["success" => true, "topic" => $topic, "payload" => $payload]);
exit;
}
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 = [
["key" => "troughs", "label" => "Tröge", "minuten" => 5],
["key" => "raisedBeds", "label" => "Beete", "minuten" => 30],
["key" => "frontGarden", "label" => "Vorn", "minuten" => 30],
];
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>
</div>
</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 &bdquo;Heute&ldquo;.
</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>
<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>
</div>
</div>
</div>
HTML;
}
echo "\n</div>\n";