Compare commits
	
		
			30 Commits
		
	
	
		
			v1.4.6
			...
			7fd01bd1b9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7fd01bd1b9 | |||
| fad84e12c8 | |||
| 696efc4d79 | |||
| 29868e7101 | |||
| 823db6157c | |||
| 458cc4eaf2 | |||
| 83d14b32d1 | |||
| 2bf7c9fb7d | |||
|  | ac8adca84d | ||
|  | c701149c64 | ||
| 07a919b6ba | |||
| 8618b90e33 | |||
| 57723b5354 | |||
| d2be752175 | |||
| 97a050ace8 | |||
| 367e692c74 | |||
| 926a21249b | |||
| 2635c19667 | |||
|  | 6cc4efca0a | ||
| 1484a6b0da | |||
| b5f0472af4 | |||
| 95c1bc823c | |||
| 491ba7f526 | |||
| 56d7d8596c | |||
| 1044e91a0a | |||
| e459b53472 | |||
| 024056cb7d | |||
| e040a736b0 | |||
| 72b6b349c6 | |||
|  | fe4d2d7479 | 
							
								
								
									
										50
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,55 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [1.4.10] - 2025-03-30 | ||||
| ### Added | ||||
| - add manual tare functionality for scale | ||||
| - add debounce handling for TTP223 touch sensor | ||||
| - add TTP223 touch sensor support and wiring configuration | ||||
|  | ||||
| ### Changed | ||||
| - update platformio.ini for version v1.4.10 | ||||
|  | ||||
| ### Fixed | ||||
| - update TTP223 pin configuration and adjust touch sensor logic | ||||
|  | ||||
|  | ||||
| ## [1.4.9] - 2025-03-29 | ||||
| ### Changed | ||||
| - update platformio.ini for version v1.4.9 | ||||
|  | ||||
| ### Fixed | ||||
| - enhance HTTP method handling in sendToApi function | ||||
|  | ||||
|  | ||||
| ## [1.4.8] - 2025-03-29 | ||||
| ### Changed | ||||
| - update platformio.ini for version v1.4.8 | ||||
| - Merge pull request #30 from janecker/main | ||||
| - Merge branch 'testing' into main | ||||
|  | ||||
| ### Fixed | ||||
| - improve HTTP client configuration and clear update documents after API calls | ||||
| - Fixes memory leak in HTTPClient by disabling connection reuse | ||||
| - update reload logic after removing and saving Bambu credentials for better cache handling | ||||
|  | ||||
|  | ||||
| ## [1.4.7] - 2025-03-27 | ||||
| ### Added | ||||
| - add forced cache refresh after removing and saving Bambu credentials | ||||
| - add functionality to remove Bambu credentials and update API handling | ||||
| - add rfid_bambu.html and update bambu connection handling | ||||
|  | ||||
| ### Changed | ||||
| - update platformio.ini for version v1.4.7 | ||||
| - Merge branch 'testing' | ||||
| - update remove button for Bambu credentials with red background | ||||
| - Merge pull request #28 from tugsi/main | ||||
|  | ||||
| ### Fixed | ||||
| - handle Bambu connection state by introducing bambuDisabled flag | ||||
| - Fix rfid.js-Failure with X1-Series, if you wanna send a Spool to AMS:  - Uncaught TypeError: Cannot read properties of undefined (reading 'replace')     at handleSpoolIn (rfid.js:493:67)     at HTMLButtonElement.onclick ((Index):1:1) handleSpoolIn	@	rfid.js:493 onclick	@	(Index):1 | ||||
|  | ||||
|  | ||||
| ## [1.4.6] - 2025-03-26 | ||||
| ### Changed | ||||
| - update platformio.ini for version v1.4.6 | ||||
|   | ||||
							
								
								
									
										31
									
								
								README.de.md
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								README.de.md
									
									
									
									
									
								
							| @@ -55,19 +55,22 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | ||||
| ## Hardware-Anforderungen | ||||
|  | ||||
| ### Komponenten | ||||
| - **ESP32 Entwicklungsboard:** Jede ESP32-Variante. | ||||
| [Amazon Link](https://amzn.eu/d/aXThslf) | ||||
| - **HX711 5kg Wägezellen-Verstärker:** Für Gewichtsmessung. | ||||
| [Amazon Link](https://amzn.eu/d/06A0DLb) | ||||
| - **OLED 0.96 Zoll I2C weiß/gelb Display:** 128x64 SSD1306. | ||||
| [Amazon Link](https://amzn.eu/d/0AuBp2c) | ||||
| - **PN532 NFC NXP RFID-Modul V3:** Für NFC-Tag-Operationen. | ||||
| [Amazon Link](https://amzn.eu/d/jfIuQXb) | ||||
| - **NFC Tags NTAG213 NTA215:** RFID Tag | ||||
| [Amazon Link](https://amzn.eu/d/9Z6mXc1) | ||||
| - **ESP32 Development Board:** Any ESP32 variant. | ||||
| [Amazon Link](https://amzn.to/3FHea6D) | ||||
| - **HX711 5kg Load Cell Amplifier:** For weight measurement. | ||||
| [Amazon Link](https://amzn.to/4ja1KTe) | ||||
| - **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. | ||||
| [Amazon Link](https://amzn.to/445aaa9) | ||||
| - **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. | ||||
| [Amazon Link](https://amzn.to/4iO6CO4) | ||||
| - **NFC Tags NTAG213 NTAG215:** RFID Tag | ||||
| [Amazon Link](https://amzn.to/3E071xO) | ||||
| - **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch | ||||
| [Amazon Link](https://amzn.to/4hTChMK) | ||||
|  | ||||
| ### Pin-Konfiguration | ||||
| | Komponente        | ESP32 Pin | | ||||
|  | ||||
| ### Pin Konfiguration | ||||
| | Component          | ESP32 Pin | | ||||
| |-------------------|-----------| | ||||
| | HX711 DOUT        | 16        | | ||||
| | HX711 SCK         | 17        | | ||||
| @@ -77,8 +80,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | ||||
| | PN532 RESET       | 33        | | ||||
| | PN532 SDA         | 21        | | ||||
| | PN532 SCL         | 22        | | ||||
| | TTP223 I/O        | 25        | | ||||
|  | ||||
| **Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** | ||||
| **!! Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** | ||||
| **Nutze den 3V Pin vom ESP für den Touch Sensor** | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @@ -60,15 +60,17 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | ||||
|  | ||||
| ### Components | ||||
| - **ESP32 Development Board:** Any ESP32 variant. | ||||
| [Amazon Link](https://amzn.eu/d/aXThslf) | ||||
| [Amazon Link](https://amzn.to/3FHea6D) | ||||
| - **HX711 5kg Load Cell Amplifier:** For weight measurement. | ||||
| [Amazon Link](https://amzn.eu/d/06A0DLb) | ||||
| [Amazon Link](https://amzn.to/4ja1KTe) | ||||
| - **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. | ||||
| [Amazon Link](https://amzn.eu/d/0AuBp2c) | ||||
| [Amazon Link](https://amzn.to/445aaa9) | ||||
| - **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. | ||||
| [Amazon Link](https://amzn.eu/d/jfIuQXb) | ||||
| [Amazon Link](https://amzn.to/4iO6CO4) | ||||
| - **NFC Tags NTAG213 NTAG215:** RFID Tag | ||||
| [Amazon Link](https://amzn.eu/d/9Z6mXc1) | ||||
| [Amazon Link](https://amzn.to/3E071xO) | ||||
| - **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch | ||||
| [Amazon Link](https://amzn.to/4hTChMK) | ||||
|  | ||||
|  | ||||
| ### Pin Configuration | ||||
| @@ -82,8 +84,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | ||||
| | PN532 RESET       | 33        | | ||||
| | PN532 SDA         | 21        | | ||||
| | PN532 SCL         | 22        | | ||||
| | TTP223 I/O        | 25        | | ||||
|  | ||||
| **Make sure that the DIP switches on the PN532 are set to I2C** | ||||
| **!! Make sure that the DIP switches on the PN532 are set to I2C** | ||||
| **Use the 3V pin from the ESP for the touch sensor** | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -141,15 +141,6 @@ | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <!-- Rechte Spalte --> | ||||
|         <div class="column"> | ||||
|             <div class="feature-box"> | ||||
|                 <h2>Bambu AMS</h2> | ||||
|                 <div id="amsDataContainer"> | ||||
|                     <div class="amsData" id="amsData">Wait for AMS-Data...</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
|   | ||||
							
								
								
									
										12
									
								
								html/rfid.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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' })); | ||||
| @@ -83,7 +83,7 @@ function initWebSocket() { | ||||
|             isConnected = false; | ||||
|             updateConnectionStatus(); | ||||
|             if (heartbeatTimer) clearInterval(heartbeatTimer); | ||||
|              | ||||
|  | ||||
|             // Bei Fehler Verbindung schließen und neu aufbauen | ||||
|             if (socket) { | ||||
|                 socket.close(); | ||||
| @@ -109,7 +109,7 @@ 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 | ||||
| @@ -208,7 +208,7 @@ 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; | ||||
| @@ -686,4 +686,4 @@ function showNotification(message, isSuccess) { | ||||
|             notification.remove(); | ||||
|         }, 300); | ||||
|     }, 3000); | ||||
| } | ||||
| } | ||||
							
								
								
									
										160
									
								
								html/rfid_bambu.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								html/rfid_bambu.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| <!-- head --><!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>FilaMan - Filament Management Tool</title> | ||||
|     <link rel="icon" type="image/png" href="/favicon.ico"> | ||||
|     <link rel="stylesheet" href="style.css"> | ||||
|     <script> | ||||
|         fetch('/api/version') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 const versionSpan = document.querySelector('.version'); | ||||
|                 if (versionSpan) { | ||||
|                     versionSpan.textContent = 'v' + data.version; | ||||
|                 } | ||||
|             }) | ||||
|             .catch(error => console.error('Error fetching version:', error)); | ||||
|     </script> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="navbar"> | ||||
|         <div style="display: flex; align-items: center; gap: 2rem;"> | ||||
|             <img src="/logo.png" alt="FilaMan Logo" class="logo"> | ||||
|             <div class="logo-text"> | ||||
|                 <h1>FilaMan<span class="version"></span></h1> | ||||
|                 <h4>Filament Management Tool</h4> | ||||
|             </div> | ||||
|         </div> | ||||
|         <nav style="display: flex; gap: 1rem;"> | ||||
|             <a href="/">Start</a> | ||||
|             <a href="/waage">Scale</a> | ||||
|             <a href="/spoolman">Spoolman/Bambu</a> | ||||
|             <a href="/about">About</a> | ||||
|             <a href="/upgrade">Upgrade</a> | ||||
|         </nav> | ||||
|         <div class="status-container"> | ||||
|             <div class="status-item"> | ||||
|                 <span class="status-dot" id="bambuDot"></span>B | ||||
|             </div> | ||||
|             <div class="status-item"> | ||||
|                 <span class="status-dot" id="spoolmanDot"></span>S | ||||
|             </div> | ||||
|             <div class="ram-status" id="ramStatus"></div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
| <!-- head --> | ||||
|  | ||||
| <div class="connection-status hidden"> | ||||
|     <div class="spinner"></div> | ||||
|     <span>Connection lost. Trying to reconnect...</span> | ||||
| </div> | ||||
| <div class="content"> | ||||
|     <div class="three-column-layout"> | ||||
|         <!-- Linke Spalte --> | ||||
|         <div class="column"> | ||||
|             <div class="feature-box"> | ||||
|                 <div class="statistics-header"> | ||||
|                     <h2>Statistics</h2> | ||||
|                     <button id="refreshSpoolman" class="refresh-button"> | ||||
|                         <span>Refresh Spoolman</span> | ||||
|                     </button> | ||||
|                 </div> | ||||
|                 <div class="statistics-column"> | ||||
|                     <h3>Spools</h3> | ||||
|                         <div class="spool-stat" style="display: flex; justify-content: center; align-items: center;"> | ||||
|                             <span class="stat-label">total:</span> | ||||
|                             <span class="stat-value" id="totalSpools"></span> | ||||
|                             <div style="width: auto;"></div> | ||||
|                             <span class="stat-label">without Tag:</span> | ||||
|                             <span class="stat-value" id="spoolsWithoutTag"></span> | ||||
|                         </div> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="statistics-grid"> | ||||
|                     <div class="statistics-column"> | ||||
|                         <h3>Overview</h3> | ||||
|                         <ul class="statistics-list"> | ||||
|                             <li> | ||||
|                                 <span class="stat-label">Manufacturer:</span> | ||||
|                                 <span class="stat-value" id="totalVendors"></span> | ||||
|                             </li> | ||||
|                             <li> | ||||
|                                 <span class="stat-label">Weight:</span> | ||||
|                                 <span class="stat-value"><span id="totalWeight"></span></span> | ||||
|                             </li> | ||||
|                             <li> | ||||
|                                 <span class="stat-label">Length:</span> | ||||
|                                 <span class="stat-value"><span id="totalLength"></span></span> | ||||
|                             </li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                     <div class="statistics-column"> | ||||
|                         <h3>Materials</h3> | ||||
|                         <ul class="statistics-list" id="materialsList"> | ||||
|                             <!-- Wird dynamisch befüllt --> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="feature-box"> | ||||
|                 <div class="nfc-header"> | ||||
|                     <h2>NFC-Tag</h2> | ||||
|                     <span id="nfcStatusIndicator" class="status-circle"></span> | ||||
|                 </div> | ||||
|                 <div class="nfc-status-display"></div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <!-- Mittlere Spalte --> | ||||
|         <div class="column"> | ||||
|             <div class="feature-box"> | ||||
|                 <h2>Spoolman Spools</h2> | ||||
|                 <label for="vendorSelect">Manufacturer:</label> | ||||
|                 <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|                     <select id="vendorSelect" class="styled-select"> | ||||
|                         <option value="">Please choose...</option> | ||||
|                     </select> | ||||
|                     <label style="margin-left: 10px;"> | ||||
|                         <input type="checkbox" id="onlyWithoutSmId" checked onchange="updateFilamentDropdown()"> | ||||
|                         Only Spools without SM ID | ||||
|                     </label> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <div id="filamentSection" class="feature-box hidden"> | ||||
|                 <label>Spool / Filament:</label> | ||||
|                 <div class="custom-dropdown"> | ||||
|                     <div class="dropdown-button" onclick="toggleFilamentDropdown()"> | ||||
|                         <div class="selected-color" id="selected-color"></div> | ||||
|                         <span id="selected-filament">Please choose...</span> | ||||
|                         <span class="dropdown-arrow">▼</span> | ||||
|                     </div> | ||||
|                     <div class="dropdown-content" id="filament-dropdown-content"> | ||||
|                         <!-- Optionen werden dynamisch hinzugefügt --> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <p id="nfcInfo" class="nfc-status"></p> | ||||
|                 <button id="writeNfcButton" class="btn btn-primary hidden" onclick="writeNfcTag()">Write Tag</button> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <!-- Rechte Spalte --> | ||||
|         <div class="column"> | ||||
|             <div class="feature-box"> | ||||
|                 <h2>Bambu AMS</h2> | ||||
|                 <div id="amsDataContainer"> | ||||
|                     <div class="amsData" id="amsData">Wait for AMS-Data...</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <script src="spoolman.js"></script> | ||||
| <script src="rfid.js"></script> | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
| @@ -57,6 +57,31 @@ | ||||
|             toggleOctoFields(); | ||||
|         }; | ||||
|  | ||||
|         function removeBambuCredentials() { | ||||
|             fetch('/api/bambu?remove=true') | ||||
|                 .then(response => response.json()) | ||||
|                 .then(data => { | ||||
|                     if (data.success) { | ||||
|                         document.getElementById('bambuIp').value = ''; | ||||
|                         document.getElementById('bambuSerial').value = ''; | ||||
|                         document.getElementById('bambuCode').value = ''; | ||||
|                         document.getElementById('autoSend').checked = false; | ||||
|                         document.getElementById('autoSendTime').value = ''; | ||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!'; | ||||
|                         // Reload with forced cache refresh after short delay | ||||
|                         setTimeout(() => { | ||||
|                             window.location.reload(true); | ||||
|                             window.location.href = '/'; | ||||
|                         }, 1500); | ||||
|                     } else { | ||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.'; | ||||
|                     } | ||||
|                 }) | ||||
|                 .catch(error => { | ||||
|                     document.getElementById('bambuStatusMessage').innerText = 'Error while removing: ' + error.message; | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         function checkSpoolmanInstance() { | ||||
|             const url = document.getElementById('spoolmanUrl').value; | ||||
|             const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked; | ||||
| @@ -89,6 +114,11 @@ | ||||
|                 .then(data => { | ||||
|                     if (data.healthy) { | ||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!'; | ||||
|                         // Reload with forced cache refresh after short delay | ||||
|                         setTimeout(() => { | ||||
|                             window.location.reload(true); | ||||
|                             window.location.href = '/'; | ||||
|                         }, 1500); | ||||
|                     } else { | ||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.'; | ||||
|                     } | ||||
| @@ -162,6 +192,7 @@ | ||||
|                     </div> | ||||
|  | ||||
|                     <button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button> | ||||
|                     <button style="margin: 0; background-color: red;" onclick="removeBambuCredentials()">Remove Credentials</button> | ||||
|                     <p id="bambuStatusMessage"></p> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| ; https://docs.platformio.org/page/projectconf.html | ||||
|  | ||||
| [common] | ||||
| version = "1.4.6" | ||||
| version = "1.4.10" | ||||
| to_old_version = "1.4.0" | ||||
|  | ||||
| ## | ||||
|   | ||||
							
								
								
									
										22
									
								
								src/api.cpp
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/api.cpp
									
									
									
									
									
								
							| @@ -3,7 +3,8 @@ | ||||
| #include <ArduinoJson.h> | ||||
| #include "commonFS.h" | ||||
|  | ||||
| bool spoolman_connected = false; | ||||
| volatile spoolmanApiStateType spoolmanApiState = API_INIT; | ||||
| //bool spoolman_connected = false; | ||||
| String spoolmanUrl = ""; | ||||
| bool octoEnabled = false; | ||||
| String octoUrl = ""; | ||||
| @@ -85,6 +86,7 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) { | ||||
| } | ||||
|  | ||||
| void sendToApi(void *parameter) { | ||||
|     spoolmanApiState = API_TRANSMITTING; | ||||
|     SendToApiParams* params = (SendToApiParams*)parameter; | ||||
|  | ||||
|     // Extrahiere die Werte | ||||
| @@ -94,13 +96,16 @@ void sendToApi(void *parameter) { | ||||
|     String octoToken = params->octoToken;     | ||||
|  | ||||
|     HTTPClient http; | ||||
|     http.setReuse(false); | ||||
|  | ||||
|     http.begin(spoolsUrl); | ||||
|     http.addHeader("Content-Type", "application/json"); | ||||
|     if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); | ||||
|  | ||||
|     int httpCode = http.PUT(updatePayload); | ||||
|     int httpCode; | ||||
|     if (httpType == "PATCH") httpCode = http.PATCH(updatePayload); | ||||
|     if (httpType == "POST") httpCode = http.POST(updatePayload); | ||||
|     else if (httpType == "POST") httpCode = http.POST(updatePayload); | ||||
|     else httpCode = http.PUT(updatePayload); | ||||
|  | ||||
|     if (httpCode == HTTP_CODE_OK) { | ||||
|         Serial.println("Spoolman erfolgreich aktualisiert"); | ||||
| @@ -111,10 +116,12 @@ void sendToApi(void *parameter) { | ||||
|     } | ||||
|  | ||||
|     http.end(); | ||||
|     vTaskDelay(50 / portTICK_PERIOD_MS); | ||||
|  | ||||
|     // Speicher freigeben | ||||
|     delete params; | ||||
|     vTaskDelete(NULL); | ||||
|     spoolmanApiState = API_IDLE; | ||||
| } | ||||
|  | ||||
| bool updateSpoolTagId(String uidString, const char* payload) { | ||||
| @@ -165,6 +172,8 @@ bool updateSpoolTagId(String uidString, const char* payload) { | ||||
|         NULL                      // Task-Handle (nicht benötigt) | ||||
|     ); | ||||
|  | ||||
|     updateDoc.clear(); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| @@ -201,6 +210,8 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { | ||||
|         NULL                      // Task-Handle (nicht benötigt) | ||||
|     ); | ||||
|  | ||||
|     updateDoc.clear(); | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| @@ -238,6 +249,8 @@ bool updateSpoolOcto(int spoolId) { | ||||
|         NULL                      // Task-Handle (nicht benötigt) | ||||
|     ); | ||||
|  | ||||
|     updateDoc.clear(); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| @@ -469,7 +482,8 @@ bool checkSpoolmanInstance(const String& url) { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 spoolman_connected = true; | ||||
|                 spoolmanApiState = API_IDLE; | ||||
|                 oledShowTopRow(); | ||||
|                 return strcmp(status, "healthy") == 0; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -6,7 +6,13 @@ | ||||
| #include "website.h" | ||||
| #include "display.h" | ||||
| #include <ArduinoJson.h> | ||||
| typedef enum { | ||||
|     API_INIT, | ||||
|     API_IDLE, | ||||
|     API_TRANSMITTING | ||||
| } spoolmanApiStateType; | ||||
|  | ||||
| extern volatile spoolmanApiStateType spoolmanApiState; | ||||
| extern bool spoolman_connected; | ||||
| extern String spoolmanUrl; | ||||
| extern bool octoEnabled; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ const char* bambu_serialnr = nullptr; | ||||
| String g_bambu_ip = ""; | ||||
| String g_bambu_accesscode = ""; | ||||
| String g_bambu_serialnr = ""; | ||||
| bool bambuDisabled = false; | ||||
|  | ||||
| bool bambu_connected = false; | ||||
| bool autoSendToBambu = false; | ||||
| @@ -37,6 +38,32 @@ int ams_count = 0; | ||||
| String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | ||||
| AMSData ams_data[MAX_AMS];  // Definition des Arrays; | ||||
|  | ||||
| bool removeBambuCredentials() { | ||||
|     if (BambuMqttTask) { | ||||
|         vTaskDelete(BambuMqttTask); | ||||
|     } | ||||
|      | ||||
|     if (!removeJsonValue("/bambu_credentials.json")) { | ||||
|         Serial.println("Fehler beim Löschen der Bambu-Credentials."); | ||||
|         return false; | ||||
|     } | ||||
|     // Löschen der globalen Variablen | ||||
|     g_bambu_ip = ""; | ||||
|     g_bambu_accesscode = ""; | ||||
|     g_bambu_serialnr = ""; | ||||
|     bambu_ip = nullptr; | ||||
|     bambu_accesscode = nullptr; | ||||
|     bambu_serialnr = nullptr; | ||||
|     autoSendToBambu = false; | ||||
|     autoSetToBambuSpoolId = 0; | ||||
|     ams_count = 0; | ||||
|     amsJsonData = ""; | ||||
|  | ||||
|     bambuDisabled = true; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) { | ||||
|     if (BambuMqttTask) { | ||||
|         vTaskDelete(BambuMqttTask); | ||||
| @@ -606,14 +633,13 @@ bool setupMqtt() { | ||||
|     bool success = loadBambuCredentials(); | ||||
|  | ||||
|     if (!success) { | ||||
|         Serial.println("Failed to load Bambu credentials"); | ||||
|         oledShowMessage("Bambu Credentials Missing"); | ||||
|         vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|         bambuDisabled = true; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "")  | ||||
|     { | ||||
|         bambuDisabled = false; | ||||
|         sslClient.setCACert(root_ca); | ||||
|         sslClient.setInsecure(); | ||||
|         client.setServer(bambu_ip, 8883); | ||||
| @@ -654,10 +680,7 @@ bool setupMqtt() { | ||||
|     }  | ||||
|     else  | ||||
|     { | ||||
|         Serial.println("Fehler: Keine MQTT-Daten vorhanden"); | ||||
|         oledShowMessage("Bambu Credentials Missing"); | ||||
|         oledShowTopRow(); | ||||
|         vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|         bambuDisabled = true; | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
|   | ||||
| @@ -30,7 +30,9 @@ extern int ams_count; | ||||
| extern AMSData ams_data[MAX_AMS]; | ||||
| extern bool autoSendToBambu; | ||||
| extern int autoSetToBambuSpoolId; | ||||
| extern bool bambuDisabled; | ||||
|  | ||||
| bool removeBambuCredentials(); | ||||
| bool loadBambuCredentials(); | ||||
| bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime); | ||||
| bool setupMqtt(); | ||||
|   | ||||
| @@ -1,6 +1,20 @@ | ||||
| #include "commonFS.h" | ||||
| #include <LittleFS.h> | ||||
|  | ||||
| bool removeJsonValue(const char* filename) { | ||||
|     File file = LittleFS.open(filename, "r"); | ||||
|     if (!file) { | ||||
|         return true; | ||||
|     } | ||||
|     file.close(); | ||||
|     if (!LittleFS.remove(filename)) { | ||||
|         Serial.print("Fehler beim Löschen der Datei: "); | ||||
|         Serial.println(filename); | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool saveJsonValue(const char* filename, const JsonDocument& doc) { | ||||
|     File file = LittleFS.open(filename, "w"); | ||||
|     if (!file) { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include <ArduinoJson.h> | ||||
| #include <LittleFS.h> | ||||
|  | ||||
| bool removeJsonValue(const char* filename); | ||||
| bool saveJsonValue(const char* filename, const JsonDocument& doc); | ||||
| bool loadJsonValue(const char* filename, JsonDocument& doc); | ||||
| void initializeFileSystem(); | ||||
|   | ||||
| @@ -19,6 +19,12 @@ const uint16_t SCALE_LEVEL_WEIGHT = 500; | ||||
| uint16_t defaultScaleCalibrationValue = 430; | ||||
| // ***** HX711 | ||||
|  | ||||
| // ***** TTP223 (Touch Sensor) | ||||
| // TTP223 circuit wiring | ||||
| const uint8_t TTP223_PIN = 25; | ||||
| // ***** TTP223 | ||||
|  | ||||
|  | ||||
| // ***** Display | ||||
| // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) | ||||
| // On an ESP32:   21(SDA),  22(SCL) | ||||
|   | ||||
| @@ -11,6 +11,8 @@ extern const uint8_t LOADCELL_SCK_PIN; | ||||
| extern const uint8_t calVal_eepromAdress; | ||||
| extern const uint16_t SCALE_LEVEL_WEIGHT; | ||||
|  | ||||
| extern const uint8_t TTP223_PIN; | ||||
|  | ||||
| extern const int8_t OLED_RESET; | ||||
| extern const uint8_t SCREEN_ADDRESS; | ||||
| extern const uint8_t SCREEN_WIDTH; | ||||
|   | ||||
| @@ -177,7 +177,7 @@ void oledShowTopRow() { | ||||
|         display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE); | ||||
|     } | ||||
|  | ||||
|     if (spoolman_connected == 1) { | ||||
|     if (spoolmanApiState != API_INIT) { | ||||
|         display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); | ||||
|     } else { | ||||
|         display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE); | ||||
|   | ||||
							
								
								
									
										49
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								src/main.cpp
									
									
									
									
									
								
							| @@ -39,7 +39,6 @@ void setup() { | ||||
|   setupWebserver(server); | ||||
|  | ||||
|   // Spoolman API | ||||
|   // api.cpp | ||||
|   initSpoolman(); | ||||
|  | ||||
|   // Bambu MQTT | ||||
| @@ -48,6 +47,7 @@ void setup() { | ||||
|   // NFC Reader | ||||
|   startNfc(); | ||||
|  | ||||
|   // Scale | ||||
|   start_scale(); | ||||
|  | ||||
|   // WDT initialisieren mit 10 Sekunden Timeout | ||||
| @@ -56,6 +56,9 @@ void setup() { | ||||
|  | ||||
|   // Aktuellen Task (loopTask) zum Watchdog hinzufügen | ||||
|   esp_task_wdt_add(NULL); | ||||
|  | ||||
|   // Touch Sensor | ||||
|   pinMode(TTP223_PIN, INPUT_PULLUP); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -84,13 +87,25 @@ uint8_t autoAmsCounter = 0; | ||||
| uint8_t weightSend = 0; | ||||
| int16_t lastWeight = 0; | ||||
|  | ||||
| // WIFI check variables | ||||
| unsigned long lastWifiCheckTime = 0; | ||||
| const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms) | ||||
|  | ||||
| // Button debounce variables | ||||
| unsigned long lastButtonPress = 0; | ||||
| const unsigned long debounceDelay = 500; // 500 ms debounce delay | ||||
|  | ||||
| // ##### PROGRAM START ##### | ||||
| void loop() { | ||||
|   unsigned long currentMillis = millis(); | ||||
|  | ||||
|   // Überprüfe den Status des Touch Sensors | ||||
|   if (digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay)  | ||||
|   { | ||||
|     lastButtonPress = currentMillis; | ||||
|     scaleTareRequest = true; | ||||
|   } | ||||
|  | ||||
|   // Überprüfe regelmäßig die WLAN-Verbindung | ||||
|   if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval))  | ||||
|   { | ||||
| @@ -100,14 +115,14 @@ void loop() { | ||||
|   // Wenn Bambu auto set Spool aktiv | ||||
|   if (autoSendToBambu && autoSetToBambuSpoolId > 0)  | ||||
|   { | ||||
|     if (!bambu_connected)  | ||||
|     if (!bambuDisabled && !bambu_connected)  | ||||
|     { | ||||
|       bambu_restart(); | ||||
|     } | ||||
|  | ||||
|     if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval))  | ||||
|     { | ||||
|       if (hasReadRfidTag == 0) | ||||
|       if (nfcReaderState == NFC_IDLE) | ||||
|       { | ||||
|         lastAutoSetBambuAmsTime = currentMillis; | ||||
|         oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); | ||||
| @@ -141,7 +156,7 @@ void loop() { | ||||
|   // Ausgabe der Waage auf Display | ||||
|   if(pauseMainTask == 0) | ||||
|   { | ||||
|     if (mainTaskWasPaused || (weight != lastWeight && hasReadRfidTag == 0 && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) | ||||
|     if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) | ||||
|     { | ||||
|       (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); | ||||
|     } | ||||
| @@ -154,29 +169,10 @@ void loop() { | ||||
|  | ||||
|  | ||||
|   // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird | ||||
|   if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag < 3) | ||||
|   if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING) | ||||
|   { | ||||
|     lastWeightReadTime = currentMillis; | ||||
|  | ||||
|     // Prüfen ob die Waage korrekt genullt ist | ||||
|     if ((weight > 0 && weight < 5) || weight < -1) | ||||
|     { | ||||
|       if(scaleTareCounter < 5) | ||||
|       { | ||||
|         scaleTareCounter++; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         scaleTareRequest = true; | ||||
|         scaleTareCounter = 0; | ||||
|       } | ||||
|        | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       scaleTareCounter = 0; | ||||
|     } | ||||
|  | ||||
|     // Prüfen ob das Gewicht gleich bleibt und dann senden | ||||
|     if (weight == lastWeight && weight > 5) | ||||
|     { | ||||
| @@ -190,7 +186,8 @@ void loop() { | ||||
|   } | ||||
|  | ||||
|   // reset weight counter after writing tag | ||||
|   if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag > 1) | ||||
|   // TBD: what exactly is the logic behind this? | ||||
|   if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS) | ||||
|   { | ||||
|     weigthCouterToApi = 0; | ||||
|   } | ||||
| @@ -198,7 +195,7 @@ void loop() { | ||||
|   lastWeight = weight; | ||||
|  | ||||
|   // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden | ||||
|   if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && hasReadRfidTag == 1) { | ||||
|   if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS) { | ||||
|     oledShowIcon("loading"); | ||||
|     if (updateSpoolWeight(spoolId, weight))  | ||||
|     { | ||||
|   | ||||
							
								
								
									
										28
									
								
								src/nfc.cpp
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/nfc.cpp
									
									
									
									
									
								
							| @@ -18,7 +18,7 @@ String spoolId = ""; | ||||
| String nfcJsonData = ""; | ||||
| volatile bool pauseBambuMqttTask = false; | ||||
|  | ||||
| volatile uint8_t hasReadRfidTag = 0; | ||||
| volatile nfcReaderStateType nfcReaderState = NFC_IDLE; | ||||
| // 0 = nicht gelesen | ||||
| // 1 = erfolgreich gelesen | ||||
| // 2 = fehler beim Lesen | ||||
| @@ -242,7 +242,7 @@ void writeJsonToTag(void *parameter) { | ||||
|   Serial.println("Erstelle NDEF-Message..."); | ||||
|   Serial.println(payload); | ||||
|  | ||||
|   hasReadRfidTag = 3; | ||||
|   nfcReaderState = NFC_WRITING; | ||||
|   vTaskSuspend(RfidReaderTask); | ||||
|   vTaskDelay(50 / portTICK_PERIOD_MS); | ||||
|  | ||||
| @@ -288,7 +288,7 @@ void writeJsonToTag(void *parameter) { | ||||
|         //oledShowMessage("NFC-Tag written"); | ||||
|         oledShowIcon("success"); | ||||
|         vTaskDelay(1000 / portTICK_PERIOD_MS); | ||||
|         hasReadRfidTag = 5; | ||||
|         nfcReaderState = NFC_WRITE_SUCCESS; | ||||
|         // aktualisieren der Website wenn sich der Status ändert | ||||
|         sendNfcData(nullptr); | ||||
|         pauseBambuMqttTask = false; | ||||
| @@ -310,7 +310,7 @@ void writeJsonToTag(void *parameter) { | ||||
|         Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag"); | ||||
|         oledShowIcon("failed"); | ||||
|         vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|         hasReadRfidTag = 4; | ||||
|         nfcReaderState = NFC_WRITE_ERROR; | ||||
|     } | ||||
|   } | ||||
|   else | ||||
| @@ -318,7 +318,7 @@ void writeJsonToTag(void *parameter) { | ||||
|     Serial.println("Fehler: Kein Tag zu schreiben gefunden."); | ||||
|     oledShowMessage("No NFC-Tag found"); | ||||
|     vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|     hasReadRfidTag = 0; | ||||
|     nfcReaderState = NFC_IDLE; | ||||
|   } | ||||
|    | ||||
|   sendWriteResult(nullptr, success); | ||||
| @@ -334,7 +334,7 @@ void startWriteJsonToTag(const char* payload) { | ||||
|   char* payloadCopy = strdup(payload); | ||||
|    | ||||
|   // Task nicht mehrfach starten | ||||
|   if (hasReadRfidTag != 3) { | ||||
|   if (nfcReaderState != NFC_WRITING) { | ||||
|     // Erstelle die Task | ||||
|     xTaskCreate( | ||||
|         writeJsonToTag,        // Task-Funktion | ||||
| @@ -351,7 +351,7 @@ void scanRfidTask(void * parameter) { | ||||
|   Serial.println("RFID Task gestartet"); | ||||
|   for(;;) { | ||||
|     // Wenn geschrieben wird Schleife aussetzen | ||||
|     if (hasReadRfidTag != 3) | ||||
|     if (nfcReaderState != NFC_WRITING) | ||||
|     { | ||||
|       yield(); | ||||
|  | ||||
| @@ -363,12 +363,12 @@ void scanRfidTask(void * parameter) { | ||||
|  | ||||
|       foundNfcTag(nullptr, success); | ||||
|        | ||||
|       if (success && hasReadRfidTag != 1) | ||||
|       if (success && nfcReaderState != NFC_READ_SUCCESS) | ||||
|       { | ||||
|         // Display some basic information about the card | ||||
|         Serial.println("Found an ISO14443A card"); | ||||
|  | ||||
|         hasReadRfidTag = 6; | ||||
|         nfcReaderState = NFC_READING; | ||||
|  | ||||
|         oledShowIcon("transfer"); | ||||
|         vTaskDelay(500 / portTICK_PERIOD_MS); | ||||
| @@ -406,11 +406,11 @@ void scanRfidTask(void * parameter) { | ||||
|             { | ||||
|               oledShowMessage("NFC-Tag unknown"); | ||||
|               vTaskDelay(2000 / portTICK_PERIOD_MS); | ||||
|               hasReadRfidTag = 2; | ||||
|               nfcReaderState = NFC_READ_ERROR; | ||||
|             } | ||||
|             else  | ||||
|             { | ||||
|               hasReadRfidTag = 1; | ||||
|               nfcReaderState = NFC_READ_SUCCESS; | ||||
|             } | ||||
|  | ||||
|             free(data); | ||||
| @@ -418,7 +418,7 @@ void scanRfidTask(void * parameter) { | ||||
|           else | ||||
|           { | ||||
|             oledShowMessage("NFC-Tag read error"); | ||||
|             hasReadRfidTag = 2; | ||||
|             nfcReaderState = NFC_READ_ERROR; | ||||
|           } | ||||
|         } | ||||
|         else | ||||
| @@ -427,9 +427,9 @@ void scanRfidTask(void * parameter) { | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (!success && hasReadRfidTag > 0) | ||||
|       if (!success && nfcReaderState != NFC_IDLE) | ||||
|       { | ||||
|         hasReadRfidTag = 0; | ||||
|         nfcReaderState = NFC_IDLE; | ||||
|         //uidString = ""; | ||||
|         nfcJsonData = ""; | ||||
|         Serial.println("Tag entfernt"); | ||||
|   | ||||
							
								
								
									
										14
									
								
								src/nfc.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/nfc.h
									
									
									
									
									
								
							| @@ -3,6 +3,16 @@ | ||||
|  | ||||
| #include <Arduino.h> | ||||
|  | ||||
| typedef enum{ | ||||
|     NFC_IDLE, | ||||
|     NFC_READING, | ||||
|     NFC_READ_SUCCESS, | ||||
|     NFC_READ_ERROR, | ||||
|     NFC_WRITING, | ||||
|     NFC_WRITE_SUCCESS, | ||||
|     NFC_WRITE_ERROR | ||||
| } nfcReaderStateType; | ||||
|  | ||||
| void startNfc(); | ||||
| void scanRfidTask(void * parameter); | ||||
| void startWriteJsonToTag(const char* payload); | ||||
| @@ -10,7 +20,9 @@ void startWriteJsonToTag(const char* payload); | ||||
| extern TaskHandle_t RfidReaderTask; | ||||
| extern String nfcJsonData; | ||||
| extern String spoolId; | ||||
| extern volatile uint8_t hasReadRfidTag; | ||||
| extern volatile nfcReaderStateType nfcReaderState; | ||||
| extern volatile bool pauseBambuMqttTask; | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -38,11 +38,15 @@ void scale_loop(void * parameter) { | ||||
|   for(;;) { | ||||
|     if (scale.is_ready())  | ||||
|     { | ||||
|       // Waage nochmal Taren, wenn zu lange Abweichung | ||||
|       // Waage manuell Taren | ||||
|       if (scaleTareRequest == true)  | ||||
|       { | ||||
|         Serial.println("Re-Tare scale"); | ||||
|         oledShowMessage("TARE Scale"); | ||||
|         vTaskDelay(pdMS_TO_TICKS(1000)); | ||||
|         scale.tare(); | ||||
|         vTaskDelay(pdMS_TO_TICKS(1000)); | ||||
|         oledShowWeight(0); | ||||
|         scaleTareRequest = false; | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -22,14 +22,14 @@ AsyncWebServer server(webserverPort); | ||||
| AsyncWebSocket ws("/ws"); | ||||
|  | ||||
| uint8_t lastSuccess = 0; | ||||
| uint8_t lastHasReadRfidTag = 0; | ||||
| nfcReaderStateType lastnfcReaderState = NFC_IDLE; | ||||
|  | ||||
|  | ||||
| void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { | ||||
|     if (type == WS_EVT_CONNECT) { | ||||
|         Serial.println("Neuer Client verbunden!"); | ||||
|         // Sende die AMS-Daten an den neuen Client | ||||
|         sendAmsData(client); | ||||
|         if (!bambuDisabled) sendAmsData(client); | ||||
|         sendNfcData(client); | ||||
|         foundNfcTag(client, 0); | ||||
|         sendWriteResult(client, 3); | ||||
| @@ -44,13 +44,15 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp | ||||
|         JsonDocument doc; | ||||
|         deserializeJson(doc, message); | ||||
|  | ||||
|         bool spoolmanConnected = (spoolmanApiState != API_INIT); | ||||
|  | ||||
|         if (doc["type"] == "heartbeat") { | ||||
|             // Sende Heartbeat-Antwort | ||||
|             ws.text(client->id(), "{" | ||||
|                 "\"type\":\"heartbeat\"," | ||||
|                 "\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + "," | ||||
|                 "\"bambu_connected\":" + String(bambu_connected) + "," | ||||
|                 "\"spoolman_connected\":" + String(spoolman_connected) + "" | ||||
|                 "\"spoolman_connected\":" + String(spoolmanConnected) + "" | ||||
|                 "}"); | ||||
|         } | ||||
|  | ||||
| @@ -139,34 +141,31 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) { | ||||
| } | ||||
|  | ||||
| void sendNfcData(AsyncWebSocketClient *client) { | ||||
|     if (lastHasReadRfidTag == hasReadRfidTag) return; | ||||
|     if (hasReadRfidTag == 0) { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}"); | ||||
|     if (lastnfcReaderState == nfcReaderState) return; | ||||
|     // TBD: Why is there no status for reading the tag? | ||||
|     switch(nfcReaderState){ | ||||
|         case NFC_IDLE: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}"); | ||||
|             break; | ||||
|         case NFC_READ_SUCCESS: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}"); | ||||
|             break; | ||||
|         case NFC_READ_ERROR: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}"); | ||||
|             break; | ||||
|         case NFC_WRITING: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}"); | ||||
|             break; | ||||
|         case NFC_WRITE_SUCCESS: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}"); | ||||
|             break; | ||||
|         case NFC_WRITE_ERROR: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}"); | ||||
|             break; | ||||
|         case DEFAULT: | ||||
|             ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}"); | ||||
|     } | ||||
|     else if (hasReadRfidTag == 1) { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}"); | ||||
|     } | ||||
|     else if (hasReadRfidTag == 2) | ||||
|     { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}"); | ||||
|     } | ||||
|     else if (hasReadRfidTag == 3) | ||||
|     { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}"); | ||||
|     } | ||||
|     else if (hasReadRfidTag == 4) | ||||
|     { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}"); | ||||
|     } | ||||
|     else if (hasReadRfidTag == 5) | ||||
|     { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}"); | ||||
|     } | ||||
|     else  | ||||
|     { | ||||
|         ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}"); | ||||
|     } | ||||
|     lastHasReadRfidTag = hasReadRfidTag; | ||||
|     lastnfcReaderState = nfcReaderState; | ||||
| } | ||||
|  | ||||
| void sendAmsData(AsyncWebSocketClient *client) { | ||||
| @@ -213,7 +212,10 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|     // Route für RFID | ||||
|     server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|         Serial.println("Anfrage für /rfid erhalten"); | ||||
|         AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html"); | ||||
|          | ||||
|         String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz"; | ||||
|         AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html"); | ||||
|          | ||||
|         response->addHeader("Content-Encoding", "gzip"); | ||||
|         response->addHeader("Cache-Control", CACHE_CONTROL); | ||||
|         request->send(response); | ||||
| @@ -310,6 +312,15 @@ void setupWebserver(AsyncWebServer &server) { | ||||
|  | ||||
|     // Route für das Überprüfen der Bambu-Instanz | ||||
|     server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request){ | ||||
|         if (request->hasParam("remove")) { | ||||
|             if (removeBambuCredentials()) { | ||||
|                 request->send(200, "application/json", "{\"success\": true}"); | ||||
|             } else { | ||||
|                 request->send(500, "application/json", "{\"success\": false, \"error\": \"Fehler beim Löschen der Bambu-Credentials\"}"); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) { | ||||
|             request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}"); | ||||
|             return; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user