218 lines
7.3 KiB
HTML
218 lines
7.3 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<title>CUNO Admin</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
</head>
|
|
|
|
<body class="admin-page">
|
|
<main>
|
|
<div class="admin_shell">
|
|
<section class="panel admin_panel">
|
|
<div class="panel_header">
|
|
<div class="pilot_brand">
|
|
<a class="pilot_logo_link" href="./index.html" aria-label="Zurück zur Steuerung">
|
|
<img class="pilot_logo" src="./Logo_Cuno.png" alt="CUNO Logo" />
|
|
</a>
|
|
<div>
|
|
<p class="eyebrow">Admin</p>
|
|
<h1>CUNO System</h1>
|
|
</div>
|
|
</div>
|
|
<p id="admin_status" class="status_badge">Lade...</p>
|
|
</div>
|
|
|
|
<p class="admin_copy">
|
|
Diese Seite bündelt die wichtigsten Systemfunktionen und Statuswerte des Raspberry Pi.
|
|
</p>
|
|
|
|
<div class="admin_content">
|
|
<div class="admin_section">
|
|
<div class="admin_section_header">
|
|
<p class="eyebrow">Aktionen und Status</p>
|
|
</div>
|
|
<div class="admin_action_row">
|
|
<div class="admin_actions">
|
|
<button class="button buttonWarm" onclick="runAdminAction('restart-camera')">Kameradienst neu starten</button>
|
|
<button class="button buttonDanger" onclick="runAdminAction('restart-container')">ExoMy-Container neu starten</button>
|
|
<button class="button buttonWarm" onclick="runAdminAction('reboot')">Raspberry Pi neu starten</button>
|
|
<button class="button buttonDanger" onclick="runAdminAction('shutdown')">Raspberry Pi herunterfahren</button>
|
|
</div>
|
|
|
|
<div class="service_compact">
|
|
<div class="service_compact_row">
|
|
<span>cam</span>
|
|
<strong id="service_camera" class="service_state">-</strong>
|
|
</div>
|
|
<div class="service_compact_row">
|
|
<span>api</span>
|
|
<strong id="service_admin_api" class="service_state">-</strong>
|
|
</div>
|
|
<div class="service_compact_row">
|
|
<span>exo</span>
|
|
<strong id="service_exomy" class="service_state">-</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin_section">
|
|
<div class="admin_section_header">
|
|
<p class="eyebrow">Wartung</p>
|
|
</div>
|
|
<div class="admin_quick_link_card">
|
|
<div>
|
|
<strong>Motorentest pro Rad</strong>
|
|
<p>Separate Testseite für Lenkung links, Lenkung rechts, Vorwärts und Rückwärts je ausgewähltem Rad.</p>
|
|
</div>
|
|
<a class="button buttonX admin_quick_link_button" href="./admin-motor-test.html">Motortest öffnen</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin_section">
|
|
<div class="admin_section_header">
|
|
<p class="eyebrow">Systemstatus</p>
|
|
</div>
|
|
<div class="info_grid">
|
|
<div class="info_card">
|
|
<span class="info_label">WLAN-Status</span>
|
|
<strong id="info_wifi">-</strong>
|
|
</div>
|
|
<div class="info_card">
|
|
<span class="info_label">IP-Adressen</span>
|
|
<strong id="info_ips">-</strong>
|
|
</div>
|
|
<div class="info_card">
|
|
<span class="info_label">CPU-Temperatur</span>
|
|
<strong id="info_temp">-</strong>
|
|
</div>
|
|
<div class="info_card">
|
|
<span class="info_label">Uptime</span>
|
|
<strong id="info_uptime">-</strong>
|
|
</div>
|
|
<div class="info_card">
|
|
<span class="info_label">Freier Speicherplatz</span>
|
|
<strong id="info_disk">-</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<a class="admin_back" href="./index.html">Zurück zur Steuerung</a>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
|
|
<script type="text/javascript">
|
|
var adminApiBase = window.location.protocol + '//' + window.location.hostname + ':8082';
|
|
|
|
function setAdminStatus(text) {
|
|
var status = document.getElementById('admin_status');
|
|
if (status) {
|
|
status.innerHTML = text;
|
|
}
|
|
}
|
|
|
|
function setText(id, value) {
|
|
var node = document.getElementById(id);
|
|
if (node) {
|
|
node.textContent = value || '-';
|
|
}
|
|
}
|
|
|
|
function setServiceState(id, value) {
|
|
var node = document.getElementById(id);
|
|
if (!node) {
|
|
return;
|
|
}
|
|
|
|
node.textContent = value || '-';
|
|
node.classList.remove('state_active', 'state_inactive', 'state_unknown');
|
|
|
|
if (value === 'active' || value === 'running') {
|
|
node.classList.add('state_active');
|
|
return;
|
|
}
|
|
|
|
if (value === 'inactive' || value === 'failed' || value === 'exited') {
|
|
node.classList.add('state_inactive');
|
|
return;
|
|
}
|
|
|
|
node.classList.add('state_unknown');
|
|
}
|
|
|
|
function renderStatus(data) {
|
|
setAdminStatus(data.status || 'Bereit');
|
|
|
|
setText('info_ips', data.system && data.system.ips);
|
|
setText('info_wifi', data.system && data.system.wifi);
|
|
setText('info_temp', data.system && data.system.cpu_temperature);
|
|
setText('info_uptime', data.system && data.system.uptime);
|
|
setText('info_disk', data.system && data.system.disk_free);
|
|
|
|
setServiceState('service_camera', data.services && data.services.camera);
|
|
setServiceState('service_admin_api', data.services && data.services.admin_api);
|
|
setServiceState('service_exomy', data.services && data.services.exomy);
|
|
}
|
|
|
|
async function fetchStatus() {
|
|
try {
|
|
var response = await fetch(adminApiBase + '/api/status');
|
|
if (!response.ok) {
|
|
throw new Error('status ' + response.status);
|
|
}
|
|
|
|
var data = await response.json();
|
|
renderStatus(data);
|
|
} catch (error) {
|
|
console.error(error);
|
|
setAdminStatus('API nicht erreichbar');
|
|
}
|
|
}
|
|
|
|
async function runAdminAction(action) {
|
|
var labels = {
|
|
'restart-camera': 'Kameradienst jetzt wirklich neu starten?',
|
|
'restart-container': 'ExoMy-Container jetzt wirklich neu starten?',
|
|
'reboot': 'Raspberry Pi jetzt wirklich neu starten?',
|
|
'shutdown': 'Raspberry Pi jetzt wirklich herunterfahren?'
|
|
};
|
|
|
|
if (!window.confirm(labels[action] || 'Befehl ausführen?')) {
|
|
return;
|
|
}
|
|
|
|
setAdminStatus('Sende Befehl...');
|
|
|
|
try {
|
|
var response = await fetch(adminApiBase + '/api/' + action, {
|
|
method: 'POST'
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('status ' + response.status);
|
|
}
|
|
|
|
var data = await response.json();
|
|
setAdminStatus(data.status || 'Befehl gesendet');
|
|
window.setTimeout(fetchStatus, 2000);
|
|
} catch (error) {
|
|
console.error(error);
|
|
setAdminStatus('Fehler');
|
|
alert('Der Admin-Befehl konnte nicht ausgeführt werden.');
|
|
}
|
|
}
|
|
|
|
window.addEventListener('load', function () {
|
|
fetchStatus();
|
|
window.setInterval(fetchStatus, 10000);
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|