153 lines
5.1 KiB
HTML
153 lines
5.1 KiB
HTML
<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Serial Portal</title>
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
</head>
|
|
<body>
|
|
<main class="container">
|
|
<h1>WiFi Setup</h1>
|
|
<p>Fallback-AP: <strong>serial</strong> / Passwort: <strong>serialserial</strong></p>
|
|
|
|
<section class="card">
|
|
<h2>Netzwerkstatus</h2>
|
|
<div id="status">Lade Status...</div>
|
|
<div id="error" class="error"></div>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Mit WLAN verbinden</h2>
|
|
<button id="scanBtn">Scan</button>
|
|
<label for="ssidSelect">SSID</label>
|
|
<select id="ssidSelect">
|
|
<option value="">Bitte zuerst scannen</option>
|
|
</select>
|
|
|
|
<label for="pw">Passwort</label>
|
|
<input id="pw" type="password" autocomplete="off" placeholder="WLAN Passwort">
|
|
|
|
<button id="connectBtn">Verbinden</button>
|
|
<div id="connectMsg"></div>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Serial Monitor</h2>
|
|
<a href="/serial">Zur Live-Serial-Seite</a>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>System</h2>
|
|
<div class="button-row">
|
|
<button id="rebootBtn" class="btn-secondary">Reboot</button>
|
|
<button id="shutdownBtn" class="btn-danger">Shutdown</button>
|
|
</div>
|
|
<div id="systemMsg"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<script>
|
|
async function refreshStatus() {
|
|
try {
|
|
const resp = await fetch('/api/status');
|
|
const data = await resp.json();
|
|
document.getElementById('status').textContent =
|
|
`AP: ${data.ap_mode ? 'an' : 'aus'} | WLAN: ${data.wifi_connected ? 'verbunden' : 'getrennt'} | Internet: ${data.internet_available ? 'ok' : 'nein'} | Status: ${data.status_message}`;
|
|
document.getElementById('error').textContent = data.last_error || '';
|
|
} catch (e) {
|
|
document.getElementById('status').textContent = 'Status nicht erreichbar';
|
|
}
|
|
}
|
|
|
|
async function scan() {
|
|
const msg = document.getElementById('connectMsg');
|
|
msg.textContent = 'Scanne WLANs...';
|
|
try {
|
|
const resp = await fetch('/api/scan', {method: 'POST'});
|
|
const data = await resp.json();
|
|
const select = document.getElementById('ssidSelect');
|
|
select.innerHTML = '';
|
|
if (data.ssids && data.ssids.length) {
|
|
data.ssids.forEach(ssid => {
|
|
const opt = document.createElement('option');
|
|
opt.value = ssid;
|
|
opt.textContent = ssid;
|
|
select.appendChild(opt);
|
|
});
|
|
msg.textContent = `${data.ssids.length} Netzwerke gefunden.`;
|
|
} else {
|
|
const opt = document.createElement('option');
|
|
opt.value = '';
|
|
opt.textContent = 'Keine Netzwerke gefunden';
|
|
select.appendChild(opt);
|
|
msg.textContent = 'Keine Netzwerke gefunden.';
|
|
}
|
|
} catch (e) {
|
|
msg.textContent = 'Scan fehlgeschlagen.';
|
|
}
|
|
refreshStatus();
|
|
}
|
|
|
|
async function connectWifi() {
|
|
const ssid = document.getElementById('ssidSelect').value;
|
|
const password = document.getElementById('pw').value;
|
|
const msg = document.getElementById('connectMsg');
|
|
|
|
if (!ssid) {
|
|
msg.textContent = 'Bitte SSID waehlen.';
|
|
return;
|
|
}
|
|
|
|
msg.textContent = `Verbinde mit ${ssid}...`;
|
|
try {
|
|
const resp = await fetch('/api/connect', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ssid, password})
|
|
});
|
|
const data = await resp.json();
|
|
if (resp.ok && data.ok) {
|
|
msg.textContent = 'Verbindung erfolgreich. AP wird beendet.';
|
|
} else {
|
|
msg.textContent = `Fehler: ${data.message || 'Connect fehlgeschlagen'}`;
|
|
}
|
|
} catch (e) {
|
|
msg.textContent = 'Verbindungsversuch fehlgeschlagen.';
|
|
}
|
|
setTimeout(refreshStatus, 1000);
|
|
}
|
|
|
|
async function triggerSystemAction(action) {
|
|
const msg = document.getElementById('systemMsg');
|
|
const label = action === 'reboot' ? 'Reboot' : 'Shutdown';
|
|
const ok = window.confirm(`System wirklich ${label.toLowerCase()} ausfuehren?`);
|
|
if (!ok) {
|
|
return;
|
|
}
|
|
|
|
msg.textContent = `${label} wird gestartet...`;
|
|
try {
|
|
const resp = await fetch(`/api/system/${action}`, {method: 'POST'});
|
|
const data = await resp.json();
|
|
if (resp.ok && data.ok) {
|
|
msg.textContent = `${label} ausgeloest.`;
|
|
} else {
|
|
msg.textContent = `Fehler: ${data.message || 'Aktion fehlgeschlagen'}`;
|
|
}
|
|
} catch (e) {
|
|
msg.textContent = `${label} fehlgeschlagen.`;
|
|
}
|
|
}
|
|
|
|
document.getElementById('scanBtn').addEventListener('click', scan);
|
|
document.getElementById('connectBtn').addEventListener('click', connectWifi);
|
|
document.getElementById('rebootBtn').addEventListener('click', () => triggerSystemAction('reboot'));
|
|
document.getElementById('shutdownBtn').addEventListener('click', () => triggerSystemAction('shutdown'));
|
|
|
|
refreshStatus();
|
|
setInterval(refreshStatus, 15000);
|
|
</script>
|
|
</body>
|
|
</html>
|