Add shutdown and reboot buttons to web UI

- 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 <noreply@anthropic.com>
This commit is contained in:
Julian Vollmer 2026-05-18 18:55:02 +02:00
parent 6ff2c329b0
commit cd133cec32
3 changed files with 39 additions and 0 deletions

View File

@ -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
# ---------------------------------------------------------------------------

View File

@ -237,6 +237,13 @@
<label>Laufzeit</label>
<div class="value">{{ status.uptime }}</div>
</div>
<div class="card">
<label>System</label>
<div style="display:flex;gap:.4rem;margin-top:.3rem;flex-wrap:wrap;">
<button onclick="systemAction('reboot')" style="font-size:.75rem;padding:.3rem .7rem;">↺ Neustart</button>
<button onclick="systemAction('shutdown')" style="font-size:.75rem;padding:.3rem .7rem;background:#3d1a1a;border-color:#5a2a2a;color:#f44336;">⏻ Ausschalten</button>
</div>
</div>
</div>
<!-- WLAN-Verwaltung -->
@ -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;

View File

@ -165,6 +165,7 @@
<div id="clock"></div>
<button class="btn" id="audio-btn" onclick="toggleAudio()">🔇 Ton an</button>
<a class="btn" href="/">⚙ Einstellungen</a>
<button class="btn" onclick="systemShutdown()" style="background:rgba(244,67,54,0.25);"></button>
</div>
@ -263,6 +264,13 @@
nextPlayTime = 0;
}
// Shutdown
async function systemShutdown() {
if (!confirm("Pi ausschalten?")) return;
await fetch("/system/shutdown", { method: "POST" });
document.body.innerHTML = '<div style="color:#fff;font-family:sans-serif;display:flex;height:100vh;align-items:center;justify-content:center;font-size:1.2rem;">Pi wird heruntergefahren…</div>';
}
// Fullscreen
function toggleFullscreen() {
if (!document.fullscreenElement) {