E-Stop Log
This commit is contained in:
@@ -10399,3 +10399,13 @@
|
||||
2026-06-12T16:12:57.932Z ::ffff:127.0.0.1: M114
|
||||
2026-06-12T16:12:58.165Z ::ffff:127.0.0.1: G1 X1 Y2 Z3
|
||||
2026-06-12T16:12:58.438Z ::ffff:127.0.0.1: G1 X1
|
||||
2026-06-12T16:34:08.466Z ::ffff:127.0.0.1: M114
|
||||
2026-06-12T16:34:08.468Z ::ffff:127.0.0.1: M114
|
||||
2026-06-12T16:34:08.483Z ::ffff:127.0.0.1: G1 X1 Y2 Z3
|
||||
2026-06-12T16:34:08.701Z ::ffff:127.0.0.1: G1 X1 Y2 Z3
|
||||
2026-06-12T16:34:08.935Z ::ffff:127.0.0.1: G1 X1
|
||||
2026-06-12T16:46:45.327Z ::ffff:127.0.0.1: M114
|
||||
2026-06-12T16:46:45.356Z ::ffff:127.0.0.1: G1 X1 Y2 Z3
|
||||
2026-06-12T16:46:46.488Z ::ffff:127.0.0.1: M114
|
||||
2026-06-12T16:46:46.701Z ::ffff:127.0.0.1: G1 X1 Y2 Z3
|
||||
2026-06-12T16:46:46.923Z ::ffff:127.0.0.1: G1 X1
|
||||
|
||||
@@ -14634,3 +14634,7 @@
|
||||
2026-06-12T16:00:23.226Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:12:57.687Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:12:57.751Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:34:08.216Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:34:08.427Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:46:45.306Z ::ffff:127.0.0.1 : Ping
|
||||
2026-06-12T16:46:46.265Z ::ffff:127.0.0.1 : Ping
|
||||
|
||||
@@ -175,7 +175,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// ── Emergency Stop Panel ─────────────────────────────────────────────
|
||||
|
||||
// SVG-Button: Farbe + Text + Click-Handler je nach armed-Zustand wechseln.
|
||||
// SVG-Button: Farbe + Text je nach armed-Zustand.
|
||||
// armed=true → rot "EMERGENCY STOP" → POST /api/emergency-stop
|
||||
// armed=false → grün "START ROBOT" → POST /api/power-on
|
||||
let _lastArmed = null;
|
||||
@@ -184,7 +184,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (armed === _lastArmed) return;
|
||||
_lastArmed = armed;
|
||||
|
||||
const stops = document.querySelectorAll('#estopGrad stop');
|
||||
const stops = document.querySelectorAll('#estopGrad stop');
|
||||
const textPath = document.querySelector('#emergency-stop textPath');
|
||||
const btnInner = document.querySelector('#emergency-stop circle:last-of-type');
|
||||
const label = document.getElementById('armed-status');
|
||||
@@ -198,7 +198,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (textPath) textPath.textContent = 'EMERGENCY STOP';
|
||||
if (label) { label.textContent = '● Bestromt'; label.className = 'estop-armed-label armed'; }
|
||||
} else {
|
||||
// Grün: Strom AUS → Klick = Strom einschalten (Start Robot)
|
||||
// Grün: Strom AUS → Klick = Strom einschalten
|
||||
if (stops[0]) stops[0].setAttribute('stop-color', '#88ff99');
|
||||
if (stops[1]) stops[1].setAttribute('stop-color', '#00aa44');
|
||||
if (stops[2]) stops[2].setAttribute('stop-color', '#005522');
|
||||
@@ -206,24 +206,59 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (textPath) textPath.textContent = 'START ROBOT';
|
||||
if (label) { label.textContent = '○ Kein Strom'; label.className = 'estop-armed-label disarmed'; }
|
||||
}
|
||||
}
|
||||
|
||||
const div = document.getElementById('emergency-stop');
|
||||
if (div) {
|
||||
div.onclick = armed
|
||||
? () => fetch('/api/emergency-stop', { method: 'POST' })
|
||||
: () => fetch('/api/power-on', { method: 'POST' });
|
||||
// ── Click-Handler (einmalig registriert, liest _lastArmed dynamisch) ─────────
|
||||
//
|
||||
// Zeigt Lade-/Erfolgs-/Fehlerstatus unter dem Button.
|
||||
// Schreibt console.warn ⚠️ für den Browser-Dev-Tools-Log.
|
||||
async function handleEstopClick() {
|
||||
const armed = _lastArmed;
|
||||
const url = armed ? '/api/emergency-stop' : '/api/power-on';
|
||||
const action = armed ? 'EmergencyStop' : 'PowerOn';
|
||||
const statusEl = document.getElementById('estop-action-status');
|
||||
|
||||
if (statusEl) { statusEl.textContent = '⏳ …'; statusEl.className = 'estop-status'; }
|
||||
console.warn(`⚠️ [${action}] wird ausgeführt …`);
|
||||
|
||||
try {
|
||||
const res = await fetch(url, { method: 'POST' });
|
||||
const data = await res.json();
|
||||
const ok = data.ok || (data.results || []).every(r => r.ok || r.skipped);
|
||||
if (ok) {
|
||||
if (statusEl) { statusEl.textContent = `✅ ${action} OK`; statusEl.className = 'estop-status ok'; }
|
||||
console.warn(`⚠️ [${action}] OK`);
|
||||
} else {
|
||||
const failed = (data.results || [])
|
||||
.filter(r => !r.ok && !r.skipped)
|
||||
.map(r => `${r.name}(${r.error || '?'})`)
|
||||
.join(', ');
|
||||
if (statusEl) { statusEl.textContent = `⚠️ Teilfehler: ${failed}`; statusEl.className = 'estop-status err'; }
|
||||
console.warn(`⚠️ [${action}] Teilfehler — ${failed}`);
|
||||
}
|
||||
} catch (err) {
|
||||
if (statusEl) { statusEl.textContent = `❌ Netzwerkfehler`; statusEl.className = 'estop-status err'; }
|
||||
console.error(`❌ [${action}] Netzwerkfehler: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// onclick einmalig setzen — bleibt dauerhaft, Handler liest _lastArmed dynamisch.
|
||||
const estopDiv = document.getElementById('emergency-stop');
|
||||
if (estopDiv) estopDiv.onclick = handleEstopClick;
|
||||
|
||||
async function pollPowerStatus() {
|
||||
try {
|
||||
const res = await fetch('/api/power-status');
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
if (data.ok) updateEmergencyStopButton(data.armed);
|
||||
// Immer aktualisieren (auch bei ok:false → disarmed als sicherer Fallback)
|
||||
updateEmergencyStopButton(data.ok ? data.armed : false);
|
||||
} catch { /* Netzwerkfehler → Button bleibt im letzten Zustand */ }
|
||||
}
|
||||
|
||||
// Sofort sicheren Startzustand (grün "START ROBOT") setzen, damit der onclick
|
||||
// sofort aktiv ist — noch bevor der erste Poll antwortet.
|
||||
updateEmergencyStopButton(false);
|
||||
pollPowerStatus();
|
||||
setInterval(pollPowerStatus, 2000);
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div id="armed-status" class="estop-armed-label"></div>
|
||||
<div id="estop-action-status" class="estop-status"></div>
|
||||
</div>
|
||||
|
||||
<button id="btn-alarm-unlock" class="btn btn-unlock">
|
||||
|
||||
@@ -99,12 +99,12 @@ module.exports = class ShellyEmergencyStop extends SenderInterface {
|
||||
const result = await this._httpGet(this._offUrl);
|
||||
this.state = result.ok ? 'stopped' : 'error';
|
||||
this.error = result.ok ? null : `HTTP ${result.status}`;
|
||||
console.log(`[Shelly] power OFF → ${result.ok ? 'OK' : `HTTP ${result.status}`}`);
|
||||
console.warn(`⚠️ [Shelly] power OFF → ${result.ok ? 'OK' : `HTTP ${result.status}`}`);
|
||||
return result;
|
||||
} catch (err) {
|
||||
this.state = 'error';
|
||||
this.error = err.message;
|
||||
console.error(`[Shelly] power OFF failed: ${err.message}`);
|
||||
console.error(`❌ [Shelly] power OFF failed: ${err.message}`);
|
||||
return { ok: false, error: err.message };
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ module.exports = class ShellyEmergencyStop extends SenderInterface {
|
||||
const result = await this._httpGet(this._onUrl);
|
||||
this.state = result.ok ? 'ready' : 'error';
|
||||
this.error = result.ok ? null : `HTTP ${result.status}`;
|
||||
console.log(`[Shelly] power ON → ${result.ok ? 'OK' : `HTTP ${result.status}`}`);
|
||||
console.warn(`⚠️ [Shelly] power ON → ${result.ok ? 'OK' : `HTTP ${result.status}`}`);
|
||||
return result;
|
||||
} catch (err) {
|
||||
this.state = 'error';
|
||||
|
||||
@@ -314,6 +314,7 @@ module.exports = class TelnetSenderGRBL extends SenderInterface {
|
||||
if (!this.tSocket) return { ok: false, error: 'not connected' };
|
||||
try {
|
||||
this.tSocket.write('!');
|
||||
console.warn(`⚠️ [EmergencyStop] Feed Hold '!' → ${this.urlGRBLstr}`);
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
return { ok: false, error: err.message };
|
||||
|
||||
@@ -120,8 +120,12 @@ function createInfoServer(httpsOptions, sharedState, robot, GCode, senders, opti
|
||||
? r.value
|
||||
: { name: senders[i].name, ok: false, error: r.reason?.message }
|
||||
);
|
||||
console.log(`[EmergencyStop] triggered at ${new Date().toISOString()}`);
|
||||
res.json({ ok: results.every(r => r.ok || r.skipped), at: new Date().toISOString(), results });
|
||||
const ok = results.every(r => r.ok || r.skipped);
|
||||
const summary = results
|
||||
.map(r => `${r.name}:${r.skipped ? 'skip' : r.ok ? 'ok' : `FAIL(${r.error})`}`)
|
||||
.join(', ');
|
||||
console.warn(`⚠️ [EmergencyStop] ${new Date().toISOString()} — [${summary}]`);
|
||||
res.json({ ok, at: new Date().toISOString(), results });
|
||||
});
|
||||
|
||||
app.post('/api/power-on', async (req, res) => {
|
||||
@@ -134,7 +138,10 @@ function createInfoServer(httpsOptions, sharedState, robot, GCode, senders, opti
|
||||
const results = settled.map(r =>
|
||||
r.status === 'fulfilled' ? r.value : { ok: false, error: r.reason?.message }
|
||||
);
|
||||
res.json({ ok: results.length > 0 && results.every(r => r.ok), at: new Date().toISOString(), results });
|
||||
const ok = results.length > 0 && results.every(r => r.ok);
|
||||
const summary = results.map(r => `${r.name}:${r.ok ? 'ok' : `FAIL(${r.error})`}`).join(', ');
|
||||
console.warn(`⚠️ [PowerOn] ${new Date().toISOString()} — [${summary || 'keine Shelly konfiguriert'}]`);
|
||||
res.json({ ok, at: new Date().toISOString(), results });
|
||||
});
|
||||
|
||||
app.post('/api/alarm-unlock', async (req, res) => {
|
||||
@@ -148,7 +155,12 @@ function createInfoServer(httpsOptions, sharedState, robot, GCode, senders, opti
|
||||
? r.value
|
||||
: { name: senders[i].name, ok: false, error: r.reason?.message }
|
||||
);
|
||||
res.json({ ok: results.every(r => r.ok || r.skipped), at: new Date().toISOString(), results });
|
||||
const ok = results.every(r => r.ok || r.skipped);
|
||||
const summary = results
|
||||
.map(r => `${r.name}:${r.skipped ? 'skip' : r.ok ? 'ok' : `FAIL(${r.error})`}`)
|
||||
.join(', ');
|
||||
console.warn(`⚠️ [AlarmUnlock] ${new Date().toISOString()} — [${summary}]`);
|
||||
res.json({ ok, at: new Date().toISOString(), results });
|
||||
});
|
||||
|
||||
// ── 404 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user