Emergency Stop

This commit is contained in:
chk
2026-06-12 19:02:31 +02:00
parent f02415c23f
commit a49e54367e
3 changed files with 102 additions and 6 deletions

View File

@@ -21,11 +21,13 @@ const loginBtn = document.getElementById("login-btn");
const loginSubmit = document.getElementById("login-submit");
const loginMsg = document.getElementById("login-msg");
const nav = document.getElementById("services");
const estopBtn = document.getElementById("emergency-stop");
const usernameInput = document.getElementById("username");
const passwordInput = document.getElementById("password");
let loggedIn = false;
let armedPollInterval = null;
// ===========================
// Login anzeigen
@@ -57,6 +59,8 @@ function switchToLogout() {
// ===========================
function performLocalLogout() {
loggedIn = false;
stopArmedPolling();
estopBtn.style.display = "none";
iframe.src = "";
iframe.style.display = "none";
nav.innerHTML = "";
@@ -64,6 +68,46 @@ function performLocalLogout() {
switchToLogin();
}
// ===========================
// Armed-Status prüfen
// ===========================
async function updateArmedStatus() {
try {
const r = await fetch('https://robotDriver.server.schooltech.ch/api/power-status');
if (r.ok) {
const data = await r.json();
estopBtn.style.display = data.armed ? "block" : "none";
} else {
estopBtn.style.display = "none";
}
} catch (e) {
estopBtn.style.display = "none";
}
}
function startArmedPolling() {
updateArmedStatus();
armedPollInterval = setInterval(updateArmedStatus, 5000);
}
function stopArmedPolling() {
if (armedPollInterval) {
clearInterval(armedPollInterval);
armedPollInterval = null;
}
}
// ===========================
// Emergency Stop
// ===========================
estopBtn.addEventListener("click", async () => {
try {
await fetch('https://robotDriver.server.schooltech.ch/api/emergency-stop', { method: 'POST' });
} catch (e) {
console.error('E-Stop request failed:', e);
}
});
// ===========================
// Login-Logik
// ===========================
@@ -84,6 +128,7 @@ async function doLogin() {
loginMsg.textContent = "";
setupServiceButtons();
switchToLogout();
startArmedPolling();
} else {
loginMsg.textContent = "Login fehlgeschlagen";
}
@@ -156,6 +201,7 @@ function openService(svc) {
loggedIn = true;
setupServiceButtons();
switchToLogout();
startArmedPolling();
} else {
switchToLogin();
}

View File

@@ -10,8 +10,31 @@
<header id="header">
<div class="logo">schooltech</div>
<nav id="services"></nav>
<div class="user">
<button id="login-btn">Login</button>
<div class="right-actions">
<div id="emergency-stop" title="Emergency Stop">
<svg width="78" height="78" viewBox="0 0 78 78" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="redGrad" cx="38%" cy="32%" r="62%">
<stop offset="0%" stop-color="#ff5555"/>
<stop offset="65%" stop-color="#cc0000"/>
<stop offset="100%" stop-color="#880000"/>
</radialGradient>
<!-- Textpfad: Radius 34, weit aussen im gelben Ring -->
<path id="estop-textarc" d="M 9,39 A 30,30 0 0,0 69,39"/>
</defs>
<!-- Gelber Aussenring (10% grösser: r=36 statt ~33) -->
<circle cx="39" cy="39" r="36" fill="#FFD700" stroke="#C8960A" stroke-width="1.5"/>
<!-- Roter Knopf -->
<circle cx="39" cy="39" r="21" fill="url(#redGrad)" stroke="#660000" stroke-width="2"/>
<!-- Gebogener Text, weiter aussen, mit Wortabstand -->
<text font-size="7.5" fill="#1a1000" font-weight="bold" font-family="system-ui,sans-serif" letter-spacing="0.3" word-spacing="5">
<textPath href="#estop-textarc" startOffset="50%" text-anchor="middle">EMERGENCY STOP</textPath>
</text>
</svg>
</div>
<div class="user">
<button id="login-btn">Login</button>
</div>
</div>
</header>

View File

@@ -17,17 +17,44 @@ header {
padding: 0 20px;
backdrop-filter: blur(6px);
background: rgba(0,0,0,0.35);
/* NEU hochwertiger Shadow */
box-shadow: 0 4px 12px rgba(0,0,0,0.35);
overflow: visible;
position: relative;
z-index: 100;
}
.logo {
font-weight: bold;
}
.right-actions {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
}
.user {
margin-left: auto; /* ⬅️ Login/Logout nach rechts */
display: flex;
align-items: center;
}
#emergency-stop {
display: none;
position: relative;
width: 78px;
height: 78px;
cursor: pointer;
flex-shrink: 0;
transition: transform 0.1s ease;
}
#emergency-stop:hover svg {
filter: brightness(1.12);
}
#emergency-stop:active {
transform: scale(0.93);
}
nav button {