From cd133cec328b891986ca687598b2ec7723283885 Mon Sep 17 00:00:00 2001 From: Julian Vollmer Date: Mon, 18 May 2026 18:55:02 +0200 Subject: [PATCH] Add shutdown and reboot buttons to web UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - POST /system/shutdown and /system/reboot Flask endpoints (sudo shutdown) - index.html: new System card with Neustart + Ausschalten buttons (confirm dialog) - live.html: red ⏻ button in bottom bar, replaces page with message on shutdown Co-Authored-By: Claude Sonnet 4.6 --- app/main.py | 16 ++++++++++++++++ app/templates/index.html | 15 +++++++++++++++ app/templates/live.html | 8 ++++++++ 3 files changed, 39 insertions(+) diff --git a/app/main.py b/app/main.py index 6db1973..7b28561 100644 --- a/app/main.py +++ b/app/main.py @@ -300,6 +300,22 @@ def wifi_connect(): }) +# --------------------------------------------------------------------------- +# System +# --------------------------------------------------------------------------- + +@app.route("/system/shutdown", methods=["POST"]) +def system_shutdown(): + subprocess.Popen(["sudo", "shutdown", "-h", "now"]) + return jsonify({"success": True, "message": "Pi wird heruntergefahren…"}) + + +@app.route("/system/reboot", methods=["POST"]) +def system_reboot(): + subprocess.Popen(["sudo", "shutdown", "-r", "now"]) + return jsonify({"success": True, "message": "Pi wird neu gestartet…"}) + + # --------------------------------------------------------------------------- # Start # --------------------------------------------------------------------------- diff --git a/app/templates/index.html b/app/templates/index.html index 72cfeab..a70001d 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -237,6 +237,13 @@
{{ status.uptime }}
+
+ +
+ + +
+
@@ -295,6 +302,14 @@ if (data.success) setTimeout(() => location.reload(), 800); } + async function systemAction(action) { + const labels = { reboot: "Pi wirklich neu starten?", shutdown: "Pi wirklich ausschalten?" }; + if (!confirm(labels[action])) return; + const res = await fetch(`/system/${action}`, { method: "POST" }); + const data = await res.json(); + alert(data.message); + } + async function connectWifi() { if (!selectedSSID) return; const password = document.getElementById("wifi-password").value; diff --git a/app/templates/live.html b/app/templates/live.html index 1e2896a..035c0a6 100644 --- a/app/templates/live.html +++ b/app/templates/live.html @@ -165,6 +165,7 @@
⚙ Einstellungen + @@ -263,6 +264,13 @@ nextPlayTime = 0; } + // Shutdown + async function systemShutdown() { + if (!confirm("Pi ausschalten?")) return; + await fetch("/system/shutdown", { method: "POST" }); + document.body.innerHTML = '
Pi wird heruntergefahren…
'; + } + // Fullscreen function toggleFullscreen() { if (!document.fullscreenElement) {