diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16d2846 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.pio +.vscode +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +data \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/README.de.md b/README.de.md index eb81f18..a02af3e 100644 --- a/README.de.md +++ b/README.de.md @@ -1,8 +1,8 @@ # FilaMan - Filament Management System FilaMan ist ein Filament-Managementsystem für den 3D-Druck. Es verwendet ESP32-Hardware für Gewichtsmessungen und NFC-Tag-Management. -Benutzer können Filamentspulen verwalten, den Status des Automatic Material System (AMS) von Bablulab Druckern überwachen und Einstellungen über eine Weboberfläche vornehmen. -Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/Spoolman) Filamentverwaltung, zusätzlich mit [Bambulab](https://bambulab.com/en-us) 3D-Druckern und sowie dem [Openspool](https://github.com/spuder/OpenSpool) NFC-TAG Format. +Benutzer können Filamentspulen verwalten, den Status des Automatic Material System (AMS) von Bambu Lab Druckern überwachen und Einstellungen über eine Weboberfläche vornehmen. +Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/Spoolman) Filamentverwaltung, zusätzlich mit [Bambu Lab](https://bambulab.com/en-us) 3D-Druckern. ![Scale](./img/scale_trans.png) @@ -16,18 +16,17 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ### ESP32 Hardware-Funktionen - **Gewichtsmessung:** Verwendung einer Wägezelle mit HX711-Verstärker für präzise Gewichtsverfolgung. - **NFC-Tag Lesen/Schreiben:** PN532-Modul zum Lesen und Schreiben von Filamentdaten auf NFC-Tags. -- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, Bambu Lab, Spoolman). +- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, BambuLab, Spoolman). - **WLAN-Konnektivität:** WiFiManager für einfache Netzwerkkonfiguration. - **MQTT-Integration:** Verbindet sich mit Bambu Lab Drucker für AMS-Steuerung. -- **NFC-Tag NTAG213 NTAG215:** Verwendung von NTAG213, besser NTAG215 wegen ausreichendem Speicherplatz auf dem Tag +- **NFC-Tag NTAG213 NTAG215:** Verwendung von NTAG213 (144 Bytes - Kapazität), besser NTAG215 (540 Bytes - Kapazität) wegen ausreichendem Speicherplatz auf dem Tag ### Weboberflächen-Funktionen - **Echtzeit-Updates:** WebSocket-Verbindung für Live-Daten-Updates. - **NFC-Tag-Verwaltung:** - Filamentdaten auf NFC-Tags schreiben. - - Verwendet das NFC-Tag-Format von [Openspool](https://github.com/spuder/OpenSpool) - - Ermöglicht automatische Spulenerkennung im AMS -- **Bambulab AMS-Integration:** + - Ermöglicht automatische Spulenerkennung im AMS. +- **Bambu Lab AMS-Integration:** - Anzeige der aktuellen AMS-Fachbelegung. - Zuordnung von Filamenten zu AMS-Slots. - Unterstützung für externe Spulenhalter. @@ -36,7 +35,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Filtern und Auswählen von Filamenten. - Automatische Aktualisierung der Spulengewichte. - Verfolgung von NFC-Tag-Zuweisungen. - - Unterstützt das Spoolman Octoprint Plugin + - Unterstützt das Spoolman Octoprint Plugin. ### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee Buy Me A Coffee @@ -122,7 +121,7 @@ Du musst Spoolman auf DEBUG Modus setzten, da man bisher in Spoolman keine CORS ``` ## Schritt-für-Schritt Installation -### Einfache Installation +### Einfache Installation (Google Chrome oder Microsoft Edge) 1. **Gehe auf [FilaMan Installer](https://www.filaman.app/installer.html)** 2. **Stecke dein ESP an den Rechner und klicke Connect** @@ -185,4 +184,4 @@ Dieses Projekt ist unter der MIT-Lizenz lizenziert. Siehe [LICENSE](LICENSE) Dat Der Code kann getestet und die Anwendung kann vom [GitHub Repository](https://github.com/ManuelW77/Filaman) heruntergeladen werden. ### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee -Buy Me A Coffee \ No newline at end of file +Buy Me A Coffee diff --git a/README.md b/README.md index 0415795..9866cd8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ FilaMan is a filament management system for 3D printing. It uses ESP32 hardware for weight measurement and NFC tag management. Users can manage filament spools, monitor the status of the Automatic Material System (AMS) and make settings via a web interface. -The system integrates seamlessly with [Bambulab](https://bambulab.com/en-us) 3D printers and [Spoolman](https://github.com/Donkie/Spoolman) filament management as well as the [Openspool](https://github.com/spuder/OpenSpool) NFC-TAG format. +The system integrates seamlessly with [Bambu Lab](https://bambulab.com/en-us) 3D printers and [Spoolman](https://github.com/Donkie/Spoolman) filament management. ![Scale](./img/scale_trans.png) @@ -23,13 +23,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman). - **WiFi Connectivity:** WiFiManager for easy network configuration. - **MQTT Integration:** Connects to Bambu Lab printer for AMS control. -- **NFC-Tag NTAG213 NTAG215:** Use NTAG213, better NTAG215 because of enaught space on the Tag +- **NFC-Tag NTAG213 NTAG215:** Use NTAG213 (Capacity of 144 bytes), better NTAG215 (Capacity of 540 bytes) because of enaught space on the Tag. ### Web Interface Features - **Real-time Updates:** WebSocket connection for live data updates. - **NFC Tag Management:** - Write filament data to NFC tags. - - uses NFC-Tag Format of [Openspool](https://github.com/spuder/OpenSpool) - so you can use it with automatic Spool detection in AMS - **Bambulab AMS Integration:** - Display current AMS tray contents. @@ -40,7 +39,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Filter and select filaments. - Update spool weights automatically. - Track NFC tag assignments. - - Supports Spoolman Octoprint Plugin + - Supports Spoolman Octoprint Plugin. ### If you want to support my work, i would be happy to get a coffe Buy Me A Coffee @@ -128,7 +127,7 @@ You have to activate Spoolman in debug mode, because you are not able to set COR ## Step-by-Step Installation -### Easy Installation +### Easy Installation (Google Chrome or Microsoft Edge) 1. **Go to [FilaMan Installer](https://www.filaman.app/installer.html)** 2. **Plug you device in and push Connect button** @@ -191,4 +190,4 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file The code can be tested and the application can be downloaded from the [GitHub repository](https://github.com/ManuelW77/Filaman). ### If you want to support my work, i would be happy to get a coffe -Buy Me A Coffee \ No newline at end of file +Buy Me A Coffee diff --git a/html/rfid.js b/html/rfid.js index d0d2f07..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' })); @@ -59,18 +59,18 @@ function initWebSocket() { try { socket = new WebSocket('ws://' + window.location.host + '/ws'); - - socket.onopen = function() { + + socket.onopen = function () { isConnected = true; updateConnectionStatus(); startHeartbeat(); // Starte Heartbeat nach erfolgreicher Verbindung }; - - socket.onclose = function() { + + socket.onclose = function () { isConnected = false; updateConnectionStatus(); if (heartbeatTimer) clearInterval(heartbeatTimer); - + // Nur neue Verbindung versuchen, wenn kein Timer läuft if (!reconnectTimer) { reconnectTimer = setTimeout(() => { @@ -78,22 +78,22 @@ function initWebSocket() { }, RECONNECT_INTERVAL); } }; - - socket.onerror = function(error) { + + socket.onerror = function (error) { isConnected = false; updateConnectionStatus(); if (heartbeatTimer) clearInterval(heartbeatTimer); - + // Bei Fehler Verbindung schließen und neu aufbauen if (socket) { socket.close(); socket = null; } }; - - socket.onmessage = function(event) { + + 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); @@ -109,13 +109,13 @@ function initWebSocket() { 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() { + bambuDot.onclick = function () { if (socket && socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ type: 'reconnect', @@ -133,7 +133,7 @@ function initWebSocket() { // Add click handler only when offline if (!data.spoolman_connected) { spoolmanDot.style.cursor = 'pointer'; - spoolmanDot.onclick = function() { + spoolmanDot.onclick = function () { if (socket && socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ type: 'reconnect', @@ -161,7 +161,7 @@ function initWebSocket() { } catch (error) { isConnected = false; updateConnectionStatus(); - + // Nur neue Verbindung versuchen, wenn kein Timer läuft if (!reconnectTimer) { reconnectTimer = setTimeout(() => { @@ -189,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; @@ -218,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'; } @@ -242,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 ); @@ -255,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' ); @@ -282,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 = `