From f869bcc0c1b4c101272f0dc0a47a58f5fd6de742 Mon Sep 17 00:00:00 2001 From: tugsi Date: Sun, 23 Mar 2025 18:58:33 +0100 Subject: [PATCH] Origin Rfid.js --- html/rfid.js | 338 +++++++++++++++++++++------------------------------ 1 file changed, 141 insertions(+), 197 deletions(-) diff --git a/html/rfid.js b/html/rfid.js index 12b3d82..960c9a7 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -11,7 +11,7 @@ let reconnectTimer = null; // WebSocket Funktionen function startHeartbeat() { if (heartbeatTimer) clearInterval(heartbeatTimer); - + heartbeatTimer = setInterval(() => { // Prüfe ob zu lange keine Antwort kam if (Date.now() - lastHeartbeatResponse > HEARTBEAT_TIMEOUT) { @@ -29,7 +29,7 @@ function startHeartbeat() { updateConnectionStatus(); return; } - + try { // Sende Heartbeat socket.send(JSON.stringify({ type: 'heartbeat' })); @@ -53,94 +53,118 @@ function initWebSocket() { // Wenn eine existierende Verbindung besteht, diese erst schließen if (socket) { - try { - socket.onclose = null; // Remove onclose handler before closing - socket.onerror = null; // Remove error handler - socket.close(); - } catch (e) { - console.error('Error closing existing socket:', e); - } + socket.close(); socket = null; } try { socket = new WebSocket('ws://' + window.location.host + '/ws'); - - socket.onopen = function() { - console.log('WebSocket connection established'); + + socket.onopen = function () { isConnected = true; updateConnectionStatus(); startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung }; - - socket.onclose = function(event) { - console.log('WebSocket connection closed:', event.code, event.reason); + + socket.onclose = function () { isConnected = false; updateConnectionStatus(); - if (heartbeatTimer) { - clearInterval(heartbeatTimer); - heartbeatTimer = null; - } - + if (heartbeatTimer) clearInterval(heartbeatTimer); + // Nur neue Verbindung versuchen, wenn kein Timer läuft if (!reconnectTimer) { reconnectTimer = setTimeout(() => { - console.log('Attempting to reconnect...'); initWebSocket(); }, RECONNECT_INTERVAL); } }; - - socket.onerror = function(error) { - console.error('WebSocket error occurred:', error); + + socket.onerror = function (error) { isConnected = false; updateConnectionStatus(); - if (heartbeatTimer) { - clearInterval(heartbeatTimer); - heartbeatTimer = null; + if (heartbeatTimer) clearInterval(heartbeatTimer); + + // Bei Fehler Verbindung schließen und neu aufbauen + if (socket) { + socket.close(); + socket = null; } }; - - socket.onmessage = function(event) { - try { - lastHeartbeatResponse = Date.now(); - const data = JSON.parse(event.data); - - // Handle different message types - switch(data.type) { - case 'amsData': - displayAmsData(data.payload); - break; - case 'nfcTag': - updateNfcStatusIndicator(data.payload); - break; - case 'nfcData': - updateNfcData(data.payload); - break; - case 'writeNfcTag': - handleWriteNfcTagResponse(data.success); - break; - case 'heartbeat': - handleHeartbeatResponse(data); - break; - case 'setSpoolmanSettings': - handleSpoolmanSettingsResponse(data); - break; - default: - console.warn('Unknown message type:', data.type); + + socket.onmessage = function (event) { + lastHeartbeatResponse = Date.now(); // Aktualisiere Zeitstempel bei jeder Server-Antwort + + const data = JSON.parse(event.data); + if (data.type === 'amsData') { + displayAmsData(data.payload); + } else if (data.type === 'nfcTag') { + updateNfcStatusIndicator(data.payload); + } else if (data.type === 'nfcData') { + updateNfcData(data.payload); + } else if (data.type === 'writeNfcTag') { + handleWriteNfcTagResponse(data.success); + } else if (data.type === 'heartbeat') { + // Optional: Spezifische Behandlung von Heartbeat-Antworten + // Update status dots + const bambuDot = document.getElementById('bambuDot'); + const spoolmanDot = document.getElementById('spoolmanDot'); + const ramStatus = document.getElementById('ramStatus'); + + if (bambuDot) { + bambuDot.className = 'status-dot ' + (data.bambu_connected ? 'online' : 'offline'); + // Add click handler only when offline + if (!data.bambu_connected) { + bambuDot.style.cursor = 'pointer'; + bambuDot.onclick = function () { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ + type: 'reconnect', + payload: 'bambu' + })); + } + }; + } else { + bambuDot.style.cursor = 'default'; + bambuDot.onclick = null; + } + } + if (spoolmanDot) { + spoolmanDot.className = 'status-dot ' + (data.spoolman_connected ? 'online' : 'offline'); + // Add click handler only when offline + if (!data.spoolman_connected) { + spoolmanDot.style.cursor = 'pointer'; + spoolmanDot.onclick = function () { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ + type: 'reconnect', + payload: 'spoolman' + })); + } + }; + } else { + spoolmanDot.style.cursor = 'default'; + spoolmanDot.onclick = null; + } + } + if (ramStatus) { + ramStatus.textContent = `${data.freeHeap}k`; + } + } + else if (data.type === 'setSpoolmanSettings') { + if (data.payload == 'success') { + showNotification(`Spoolman Settings set successfully`, true); + } else { + showNotification(`Error setting Spoolman Settings`, false); } - } catch (error) { - console.error('Error processing WebSocket message:', error); } }; } catch (error) { - console.error('Error initializing WebSocket:', error); isConnected = false; updateConnectionStatus(); - + + // Nur neue Verbindung versuchen, wenn kein Timer läuft if (!reconnectTimer) { reconnectTimer = setTimeout(() => { - console.log('Attempting to reconnect after error...'); initWebSocket(); }, RECONNECT_INTERVAL); } @@ -165,26 +189,26 @@ function updateConnectionStatus() { } // Event Listeners -document.addEventListener("DOMContentLoaded", function() { +document.addEventListener("DOMContentLoaded", function () { initWebSocket(); - + // Event Listener für Checkbox - document.getElementById("onlyWithoutSmId").addEventListener("change", function() { + document.getElementById("onlyWithoutSmId").addEventListener("change", function () { const spoolsData = window.getSpoolData(); window.populateVendorDropdown(spoolsData); }); }); // Event Listener für Spoolman Events -document.addEventListener('spoolDataLoaded', function(event) { +document.addEventListener('spoolDataLoaded', function (event) { window.populateVendorDropdown(event.detail); }); -document.addEventListener('spoolmanError', function(event) { +document.addEventListener('spoolmanError', function (event) { showNotification(`Spoolman Error: ${event.detail.message}`, false); }); -document.addEventListener('filamentSelected', function(event) { +document.addEventListener('filamentSelected', function (event) { updateNfcInfo(); // Zeige Spool-Buttons wenn ein Filament ausgewählt wurde const selectedText = document.getElementById("selected-filament").textContent; @@ -194,13 +218,13 @@ document.addEventListener('filamentSelected', function(event) { // Hilfsfunktion für kontrastreiche Textfarbe function getContrastColor(hexcolor) { // Konvertiere Hex zu RGB - const r = parseInt(hexcolor.substr(0,2),16); - const g = parseInt(hexcolor.substr(2,2),16); - const b = parseInt(hexcolor.substr(4,2),16); - + const r = parseInt(hexcolor.substr(0, 2), 16); + const g = parseInt(hexcolor.substr(2, 2), 16); + const b = parseInt(hexcolor.substr(4, 2), 16); + // Berechne Helligkeit (YIQ Formel) - const yiq = ((r*299)+(g*587)+(b*114))/1000; - + const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; + // Return schwarz oder weiß basierend auf Helligkeit return (yiq >= 128) ? '#000000' : '#FFFFFF'; } @@ -218,7 +242,7 @@ function updateNfcInfo() { } // Finde die ausgewählte Spule in den Daten - const selectedSpool = spoolsData.find(spool => + const selectedSpool = spoolsData.find(spool => `${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText ); @@ -231,18 +255,18 @@ function updateNfcInfo() { function displayAmsData(amsData) { const amsDataContainer = document.getElementById('amsData'); - amsDataContainer.innerHTML = ''; + amsDataContainer.innerHTML = ''; amsData.forEach((ams) => { // Bestimme den Anzeigenamen für das AMS const amsDisplayName = ams.ams_id === 255 ? 'External Spool' : `AMS ${ams.ams_id}`; - + const trayHTML = ams.tray.map(tray => { // Prüfe ob überhaupt Daten vorhanden sind const relevantFields = ['tray_type', 'tray_sub_brands', 'tray_info_idx', 'setting_id', 'cali_idx']; - const hasAnyContent = relevantFields.some(field => - tray[field] !== null && - tray[field] !== undefined && + const hasAnyContent = relevantFields.some(field => + tray[field] !== null && + tray[field] !== undefined && tray[field] !== '' && tray[field] !== 'null' ); @@ -258,8 +282,8 @@ function displayAmsData(amsData) { cursor: pointer; display: none;"> Spool In `; - - // Nur für nicht-leere Trays den Button-HTML erstellen + + // Nur für nicht-leere Trays den Button-HTML erstellen const outButtonHtml = `