feat: API-Endpunkt zum Neustarten des Systems hinzugefügt und Versionsnummer auf 1.0.7 erhöht

This commit is contained in:
2026-05-09 02:26:39 +02:00
parent d1eabea3e3
commit eef04ca7d5
2 changed files with 59 additions and 2 deletions

59
app.py
View File

@@ -1095,6 +1095,15 @@ def r_update_check():
return jsonify(ok=True)
@app.route('/api/system/reboot', methods=['POST'])
def r_system_reboot():
threading.Thread(target=lambda: (
__import__('time').sleep(1),
subprocess.Popen(['reboot'])
), daemon=True).start()
return jsonify(ok=True)
@app.route('/api/update/install', methods=['POST'])
def r_update_install():
try:
@@ -1239,7 +1248,7 @@ body{background:var(--bg);color:var(--txt);font-family:-apple-system,BlinkMacSys
.tog input{accent-color:var(--acc);width:16px;height:16px;cursor:pointer;flex-shrink:0}
.tog span{line-height:1.35}
.flash{font-size:.78rem;min-height:1rem;padding:.2rem 0}
.flash.ok{color:var(--grn)}.flash.err{color:var(--red)}
.flash.ok{color:var(--grn)}.flash.err{color:var(--red)}.flash.warn{color:#f4a332}
/* ── Port Slots ── */
/* port-pair: immer echtes 1fr 1fr, unabhängig vom Explorer */
@@ -1609,6 +1618,19 @@ body{background:var(--bg);color:var(--txt);font-family:-apple-system,BlinkMacSys
</div>
</div>
<!-- ── System ── -->
<div class="card">
<div class="card-head">
<div class="card-icon" style="background:rgba(255,180,60,.1);color:#f4a332">⚙</div>
<span class="card-title">System</span>
</div>
<div class="card-body" style="display:flex;flex-direction:column;gap:.6rem">
<button class="btn" style="width:100%" onclick="checkUpdate()">🔍&nbsp;Nach Update suchen</button>
<div id="sys-update-flash" class="flash" style="display:none"></div>
<button class="btn" style="width:100%;background:rgba(220,60,60,.12);color:#e05555;border-color:rgba(220,60,60,.25)" onclick="rebootDevice()">↺&nbsp;Gerät neu starten</button>
</div>
</div>
<!-- ── Logs ── -->
<div class="card col2">
<div class="card-head">
@@ -2063,6 +2085,41 @@ async function installUpdate() {
}, 5000);
}
async function checkUpdate() {
const btn = event.currentTarget;
btn.disabled = true; btn.textContent = '↻ Prüfe…';
try {
await api('/update/check', 'POST');
await new Promise(r => setTimeout(r, 2000));
const u = await api('/update/status');
const fl = $('sys-update-flash');
if (u.available && u.latest) {
fl.className = 'flash warn'; fl.textContent = 'Update v' + u.latest + ' verfügbar über das Badge oben installieren.';
} else if (u.error) {
fl.className = 'flash err'; fl.textContent = 'Fehler: ' + u.error;
} else {
fl.className = 'flash ok'; fl.textContent = 'PiCopy ist aktuell.';
}
fl.style.display = 'block';
if (fl.className.includes('ok')) setTimeout(() => fl.style.display = 'none', 3500);
} catch(e) {
const fl = $('sys-update-flash');
fl.className = 'flash err'; fl.textContent = 'Verbindung fehlgeschlagen.'; fl.style.display = 'block';
} finally {
btn.disabled = false; btn.innerHTML = '🔍&nbsp;Nach Update suchen';
}
}
async function rebootDevice() {
if (!confirm('Gerät jetzt neu starten?\n\nDas Web-Interface ist für ca. 30 Sekunden nicht erreichbar.')) return;
try { await api('/system/reboot', 'POST'); } catch(e) {}
document.body.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100vh;font-family:sans-serif;color:#888;font-size:1rem">↻ Gerät startet neu bitte warten…</div>';
setTimeout(async function waitForRestart() {
try { await fetch('/api/update/status'); location.reload(); }
catch(e) { setTimeout(waitForRestart, 2000); }
}, 10000);
}
function flash(id,cls,msg){
const el=$(id); el.className='flash '+cls; el.textContent=msg; el.style.display='block';
if(cls==='ok') setTimeout(()=>el.style.display='none',3500);

View File

@@ -1 +1 @@
1.0.6
1.0.7