Compare commits
	
		
			28 Commits
		
	
	
		
			v1.3.97
			...
			8a558c3121
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8a558c3121 | |||
| 5afb60df32 | |||
| 3394e6eb01 | |||
| 3818c2c059 | |||
| 0afc543b5f | |||
| adee46e3fc | |||
| 1db74867e6 | |||
| 0f24a63d32 | |||
| 3640809502 | |||
| 289d5357be | |||
| 315530d1ea | |||
| f36773a4c4 | |||
| b35163936f | |||
| 7a2c9d6d17 | |||
| eb2a8dc128 | |||
| bec2c91331 | |||
| c6e727de06 | |||
| 3253e7d407 | |||
| bce2ad2ed8 | |||
| 
						 | 
					0eff29ef4a | ||
| 492bf6cdb8 | |||
| b0317f4001 | |||
| 58ff6458b0 | |||
| d9c40f5124 | |||
| 68bc31e29a | |||
| 9b23ac5fd2 | |||
| d31bff14c3 | |||
| 150f92484a | 
							
								
								
									
										10
									
								
								.github/workflows/gitea-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/gitea-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -41,16 +41,16 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2)
 | 
					        VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Build firmware and SPIFFS
 | 
					        # Build firmware and LittleFS
 | 
				
			||||||
        echo "Building firmware and SPIFFS..."
 | 
					        echo "Building firmware and LittleFS..."
 | 
				
			||||||
        pio run -e esp32dev
 | 
					        pio run -e esp32dev
 | 
				
			||||||
        pio run -t buildfs
 | 
					        pio run -t buildfs
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Copy firmware binary
 | 
					        # Copy firmware binary
 | 
				
			||||||
        cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/upgrade_filaman_firmware_v${VERSION}.bin
 | 
					        cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/upgrade_filaman_firmware_v${VERSION}.bin
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Create SPIFFS binary - direct copy without header
 | 
					        # Create LittleFS binary - direct copy without header
 | 
				
			||||||
        cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/upgrade_filaman_website_v${VERSION}.bin
 | 
					        cp .pio/build/esp32dev/littlefs.bin .pio/build/esp32dev/upgrade_filaman_website_v${VERSION}.bin
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Create full binary
 | 
					        # Create full binary
 | 
				
			||||||
        (cd .pio/build/esp32dev && 
 | 
					        (cd .pio/build/esp32dev && 
 | 
				
			||||||
@@ -63,7 +63,7 @@ jobs:
 | 
				
			|||||||
          0x1000 bootloader.bin \
 | 
					          0x1000 bootloader.bin \
 | 
				
			||||||
          0x8000 partitions.bin \
 | 
					          0x8000 partitions.bin \
 | 
				
			||||||
          0x10000 firmware.bin \
 | 
					          0x10000 firmware.bin \
 | 
				
			||||||
          0x3D0000 spiffs.bin)
 | 
					          0x3D0000 littlefs.bin)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Verify file sizes
 | 
					        # Verify file sizes
 | 
				
			||||||
        echo "File sizes:"
 | 
					        echo "File sizes:"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								.github/workflows/github-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/github-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -39,16 +39,16 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2)
 | 
					        VERSION=$(grep '^version = ' platformio.ini | cut -d'"' -f2)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Always build firmware and SPIFFS
 | 
					        # Always build firmware and LittleFS
 | 
				
			||||||
        echo "Building firmware and SPIFFS..."
 | 
					        echo "Building firmware and LittleFS..."
 | 
				
			||||||
        pio run -e esp32dev
 | 
					        pio run -e esp32dev
 | 
				
			||||||
        pio run -t buildfs
 | 
					        pio run -t buildfs
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Copy firmware binary
 | 
					        # Copy firmware binary
 | 
				
			||||||
        cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/upgrade_filaman_firmware_v${VERSION}.bin
 | 
					        cp .pio/build/esp32dev/firmware.bin .pio/build/esp32dev/upgrade_filaman_firmware_v${VERSION}.bin
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Create SPIFFS binary - direct copy without header
 | 
					        # Create LittleFS binary - direct copy without header
 | 
				
			||||||
        cp .pio/build/esp32dev/spiffs.bin .pio/build/esp32dev/upgrade_filaman_website_v${VERSION}.bin
 | 
					        cp .pio/build/esp32dev/littlefs.bin .pio/build/esp32dev/upgrade_filaman_website_v${VERSION}.bin
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Create full binary (always)
 | 
					        # Create full binary (always)
 | 
				
			||||||
        (cd .pio/build/esp32dev && 
 | 
					        (cd .pio/build/esp32dev && 
 | 
				
			||||||
@@ -61,7 +61,7 @@ jobs:
 | 
				
			|||||||
          0x1000 bootloader.bin \
 | 
					          0x1000 bootloader.bin \
 | 
				
			||||||
          0x8000 partitions.bin \
 | 
					          0x8000 partitions.bin \
 | 
				
			||||||
          0x10000 firmware.bin \
 | 
					          0x10000 firmware.bin \
 | 
				
			||||||
          0x3D0000 spiffs.bin)
 | 
					          0x3D0000 littlefs.bin)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Verify file sizes
 | 
					        # Verify file sizes
 | 
				
			||||||
        echo "File sizes:"
 | 
					        echo "File sizes:"
 | 
				
			||||||
@@ -131,7 +131,7 @@ jobs:
 | 
				
			|||||||
          FILES_TO_UPLOAD="$FILES_TO_UPLOAD upgrade_filaman_firmware_v${VERSION}.bin"
 | 
					          FILES_TO_UPLOAD="$FILES_TO_UPLOAD upgrade_filaman_firmware_v${VERSION}.bin"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # Add SPIFFS and full binary only if they exist
 | 
					        # Add LittleFS and full binary only if they exist
 | 
				
			||||||
        if [ -f "upgrade_filaman_website_v${VERSION}.bin" ]; then
 | 
					        if [ -f "upgrade_filaman_website_v${VERSION}.bin" ]; then
 | 
				
			||||||
          FILES_TO_UPLOAD="$FILES_TO_UPLOAD upgrade_filaman_website_v${VERSION}.bin"
 | 
					          FILES_TO_UPLOAD="$FILES_TO_UPLOAD upgrade_filaman_website_v${VERSION}.bin"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -1,54 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
    "files.associations": {
 | 
					 | 
				
			||||||
        "algorithm": "cpp",
 | 
					 | 
				
			||||||
        "vector": "cpp",
 | 
					 | 
				
			||||||
        "cmath": "cpp",
 | 
					 | 
				
			||||||
        "array": "cpp",
 | 
					 | 
				
			||||||
        "atomic": "cpp",
 | 
					 | 
				
			||||||
        "*.tcc": "cpp",
 | 
					 | 
				
			||||||
        "bitset": "cpp",
 | 
					 | 
				
			||||||
        "cctype": "cpp",
 | 
					 | 
				
			||||||
        "clocale": "cpp",
 | 
					 | 
				
			||||||
        "cstdarg": "cpp",
 | 
					 | 
				
			||||||
        "cstddef": "cpp",
 | 
					 | 
				
			||||||
        "cstdint": "cpp",
 | 
					 | 
				
			||||||
        "cstdio": "cpp",
 | 
					 | 
				
			||||||
        "cstdlib": "cpp",
 | 
					 | 
				
			||||||
        "cstring": "cpp",
 | 
					 | 
				
			||||||
        "ctime": "cpp",
 | 
					 | 
				
			||||||
        "cwchar": "cpp",
 | 
					 | 
				
			||||||
        "cwctype": "cpp",
 | 
					 | 
				
			||||||
        "deque": "cpp",
 | 
					 | 
				
			||||||
        "unordered_map": "cpp",
 | 
					 | 
				
			||||||
        "unordered_set": "cpp",
 | 
					 | 
				
			||||||
        "exception": "cpp",
 | 
					 | 
				
			||||||
        "functional": "cpp",
 | 
					 | 
				
			||||||
        "iterator": "cpp",
 | 
					 | 
				
			||||||
        "map": "cpp",
 | 
					 | 
				
			||||||
        "memory": "cpp",
 | 
					 | 
				
			||||||
        "memory_resource": "cpp",
 | 
					 | 
				
			||||||
        "numeric": "cpp",
 | 
					 | 
				
			||||||
        "optional": "cpp",
 | 
					 | 
				
			||||||
        "random": "cpp",
 | 
					 | 
				
			||||||
        "regex": "cpp",
 | 
					 | 
				
			||||||
        "string": "cpp",
 | 
					 | 
				
			||||||
        "string_view": "cpp",
 | 
					 | 
				
			||||||
        "system_error": "cpp",
 | 
					 | 
				
			||||||
        "tuple": "cpp",
 | 
					 | 
				
			||||||
        "type_traits": "cpp",
 | 
					 | 
				
			||||||
        "utility": "cpp",
 | 
					 | 
				
			||||||
        "fstream": "cpp",
 | 
					 | 
				
			||||||
        "initializer_list": "cpp",
 | 
					 | 
				
			||||||
        "iomanip": "cpp",
 | 
					 | 
				
			||||||
        "iosfwd": "cpp",
 | 
					 | 
				
			||||||
        "istream": "cpp",
 | 
					 | 
				
			||||||
        "limits": "cpp",
 | 
					 | 
				
			||||||
        "new": "cpp",
 | 
					 | 
				
			||||||
        "ostream": "cpp",
 | 
					 | 
				
			||||||
        "sstream": "cpp",
 | 
					 | 
				
			||||||
        "stdexcept": "cpp",
 | 
					 | 
				
			||||||
        "streambuf": "cpp",
 | 
					 | 
				
			||||||
        "cinttypes": "cpp",
 | 
					 | 
				
			||||||
        "typeinfo": "cpp"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										30
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,5 +1,35 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.4.0] - 2025-03-01
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- add support for Spoolman Octoprint Plugin in README files
 | 
				
			||||||
 | 
					- add OctoPrint integration with configurable fields and update functionality
 | 
				
			||||||
 | 
					- add version comparison function and check for outdated versions before updates
 | 
				
			||||||
 | 
					- remove unused version and protocol fields from JSON output; add error message for insufficient memory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- update NFC tag references to include NTAG213 and clarify storage capacity
 | 
				
			||||||
 | 
					- bump version to 1.4.0
 | 
				
			||||||
 | 
					- remove unused version and protocol fields from NFC data packet
 | 
				
			||||||
 | 
					- sort vendors alphabetically in the dropdown list
 | 
				
			||||||
 | 
					- Merge pull request #10 from janecker/nfc-improvements
 | 
				
			||||||
 | 
					- Improves NFC Tag handling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.3.99] - 2025-02-28
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- update platformio.ini for version v1.3.99
 | 
				
			||||||
 | 
					- update workflows to build firmware with LittleFS instead of SPIFFS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.3.98] - 2025-02-28
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- update platformio.ini for version v1.3.98
 | 
				
			||||||
 | 
					- migrate from SPIFFS to LittleFS for file handling
 | 
				
			||||||
 | 
					- remove unused VSCode settings file
 | 
				
			||||||
 | 
					- remove commented-out spoolman and filaman data from api.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [1.3.97] - 2025-02-28
 | 
					## [1.3.97] - 2025-02-28
 | 
				
			||||||
### Added
 | 
					### Added
 | 
				
			||||||
- füge Bestätigungsmeldung für Spool-Einstellung hinzu
 | 
					- füge Bestätigungsmeldung für Spool-Einstellung hinzu
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ Das System integriert sich nahtlos mit der [Spoolman](https://github.com/Donkie/
 | 
				
			|||||||
Weitere Bilder finden Sie im [img Ordner](/img/)
 | 
					Weitere Bilder finden Sie im [img Ordner](/img/)
 | 
				
			||||||
oder auf meiner Website: [FilaMan Website](https://www.filaman.app)  
 | 
					oder auf meiner Website: [FilaMan Website](https://www.filaman.app)  
 | 
				
			||||||
Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)  
 | 
					Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)  
 | 
				
			||||||
 | 
					Discord Server: [https://discord.gg/vMAx2gf5](https://discord.gg/vMAx2gf5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Es gibt jetzt auch ein Wiki, dort sind nochmal alle Funktionen beschrieben: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
 | 
					### Es gibt jetzt auch ein Wiki, dort sind nochmal alle Funktionen beschrieben: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -18,7 +19,7 @@ Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaO
 | 
				
			|||||||
- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, Bambu Lab, Spoolman).
 | 
					- **OLED-Display:** Zeigt aktuelles Gewicht, Verbindungsstatus (WiFi, Bambu Lab, Spoolman).
 | 
				
			||||||
- **WLAN-Konnektivität:** WiFiManager für einfache Netzwerkkonfiguration.
 | 
					- **WLAN-Konnektivität:** WiFiManager für einfache Netzwerkkonfiguration.
 | 
				
			||||||
- **MQTT-Integration:** Verbindet sich mit Bambu Lab Drucker für AMS-Steuerung.
 | 
					- **MQTT-Integration:** Verbindet sich mit Bambu Lab Drucker für AMS-Steuerung.
 | 
				
			||||||
- **NFC-Tag NTAG215:** Verwendung von NTAG215 wegen ausreichendem Speicherplatz auf dem Tag
 | 
					- **NFC-Tag NTAG213 NTAG215:** Verwendung von NTAG213, besser NTAG215 wegen ausreichendem Speicherplatz auf dem Tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Weboberflächen-Funktionen
 | 
					### Weboberflächen-Funktionen
 | 
				
			||||||
- **Echtzeit-Updates:** WebSocket-Verbindung für Live-Daten-Updates.
 | 
					- **Echtzeit-Updates:** WebSocket-Verbindung für Live-Daten-Updates.
 | 
				
			||||||
@@ -35,6 +36,7 @@ Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaO
 | 
				
			|||||||
  - Filtern und Auswählen von Filamenten.
 | 
					  - Filtern und Auswählen von Filamenten.
 | 
				
			||||||
  - Automatische Aktualisierung der Spulengewichte.
 | 
					  - Automatische Aktualisierung der Spulengewichte.
 | 
				
			||||||
  - Verfolgung von NFC-Tag-Zuweisungen.
 | 
					  - Verfolgung von NFC-Tag-Zuweisungen.
 | 
				
			||||||
 | 
					  - Unterstützt das Spoolman Octoprint Plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee
 | 
					### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee
 | 
				
			||||||
<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
 | 
					<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
 | 
				
			||||||
@@ -61,7 +63,7 @@ Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaO
 | 
				
			|||||||
[Amazon Link](https://amzn.eu/d/0AuBp2c)
 | 
					[Amazon Link](https://amzn.eu/d/0AuBp2c)
 | 
				
			||||||
- **PN532 NFC NXP RFID-Modul V3:** Für NFC-Tag-Operationen.
 | 
					- **PN532 NFC NXP RFID-Modul V3:** Für NFC-Tag-Operationen.
 | 
				
			||||||
[Amazon Link](https://amzn.eu/d/jfIuQXb)
 | 
					[Amazon Link](https://amzn.eu/d/jfIuQXb)
 | 
				
			||||||
- **NFC Tags Ntag215:** RFID Tag
 | 
					- **NFC Tags NTAG213 NTA215:** RFID Tag
 | 
				
			||||||
[Amazon Link](https://amzn.eu/d/9Z6mXc1)
 | 
					[Amazon Link](https://amzn.eu/d/9Z6mXc1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Pin-Konfiguration
 | 
					### Pin-Konfiguration
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,12 +6,14 @@ FilaMan is a filament management system for 3D printing. It uses ESP32 hardware
 | 
				
			|||||||
Users can manage filament spools, monitor the status of the Automatic Material System (AMS) and make settings via a web interface. 
 | 
					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 [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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
More Images can be found in the [img Folder](/img/)  
 | 
					More Images can be found in the [img Folder](/img/)  
 | 
				
			||||||
or my website:[FilaMan Website](https://www.filaman.app)  
 | 
					or my website: [FilaMan Website](https://www.filaman.app)  
 | 
				
			||||||
german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)  
 | 
					german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU)  
 | 
				
			||||||
 | 
					Discord Server: [https://discord.gg/vMAx2gf5](https://discord.gg/vMAx2gf5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Now more detailed informations about the usage: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
 | 
					### Now more detailed informations about the usage: [Wiki](https://github.com/ManuelW77/Filaman/wiki)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,7 +23,7 @@ german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62z
 | 
				
			|||||||
- **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman).
 | 
					- **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman).
 | 
				
			||||||
- **WiFi Connectivity:** WiFiManager for easy network configuration.
 | 
					- **WiFi Connectivity:** WiFiManager for easy network configuration.
 | 
				
			||||||
- **MQTT Integration:** Connects to Bambu Lab printer for AMS control.
 | 
					- **MQTT Integration:** Connects to Bambu Lab printer for AMS control.
 | 
				
			||||||
- **NFC-Tag NTAG215:** Use NTAG215 because of enaught space on the Tag
 | 
					- **NFC-Tag NTAG213 NTAG215:** Use NTAG213, better NTAG215 because of enaught space on the Tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Web Interface Features
 | 
					### Web Interface Features
 | 
				
			||||||
- **Real-time Updates:** WebSocket connection for live data updates.
 | 
					- **Real-time Updates:** WebSocket connection for live data updates.
 | 
				
			||||||
@@ -38,6 +40,7 @@ german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62z
 | 
				
			|||||||
  - Filter and select filaments.
 | 
					  - Filter and select filaments.
 | 
				
			||||||
  - Update spool weights automatically.
 | 
					  - Update spool weights automatically.
 | 
				
			||||||
  - Track NFC tag assignments.
 | 
					  - Track NFC tag assignments.
 | 
				
			||||||
 | 
					  - Supports Spoolman Octoprint Plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### If you want to support my work, i would be happy to get a coffe
 | 
					### If you want to support my work, i would be happy to get a coffe
 | 
				
			||||||
<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
 | 
					<a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 108px !important;" ></a>
 | 
				
			||||||
@@ -64,7 +67,7 @@ german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62z
 | 
				
			|||||||
[Amazon Link](https://amzn.eu/d/0AuBp2c)
 | 
					[Amazon Link](https://amzn.eu/d/0AuBp2c)
 | 
				
			||||||
- **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations.
 | 
					- **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations.
 | 
				
			||||||
[Amazon Link](https://amzn.eu/d/jfIuQXb)
 | 
					[Amazon Link](https://amzn.eu/d/jfIuQXb)
 | 
				
			||||||
- **NFC Tags Ntag215:** RFID Tag
 | 
					- **NFC Tags NTAG213 NTAG215:** RFID Tag
 | 
				
			||||||
[Amazon Link](https://amzn.eu/d/9Z6mXc1)
 | 
					[Amazon Link](https://amzn.eu/d/9Z6mXc1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15297
									
								
								_3D Print Files/FilaMan-Waage.step
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15297
									
								
								_3D Print Files/FilaMan-Waage.step
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								_3D Print Files/Filaman-Waage.f3z
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								_3D Print Files/Filaman-Waage.f3z
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -640,8 +640,6 @@ function writeNfcTag() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Erstelle das NFC-Datenpaket mit korrekten Datentypen
 | 
					    // Erstelle das NFC-Datenpaket mit korrekten Datentypen
 | 
				
			||||||
    const nfcData = {
 | 
					    const nfcData = {
 | 
				
			||||||
        version: "2.0",
 | 
					 | 
				
			||||||
        protocol: "openspool",
 | 
					 | 
				
			||||||
        color_hex: selectedSpool.filament.color_hex || "FFFFFF",
 | 
					        color_hex: selectedSpool.filament.color_hex || "FFFFFF",
 | 
				
			||||||
        type: selectedSpool.filament.material,
 | 
					        type: selectedSpool.filament.material,
 | 
				
			||||||
        min_temp: minTemp,
 | 
					        min_temp: minTemp,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,11 +52,18 @@
 | 
				
			|||||||
            if (spoolmanUrl && spoolmanUrl.trim() !== "") {
 | 
					            if (spoolmanUrl && spoolmanUrl.trim() !== "") {
 | 
				
			||||||
                document.getElementById('spoolmanUrl').value = spoolmanUrl;
 | 
					                document.getElementById('spoolmanUrl').value = spoolmanUrl;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Initialize OctoPrint fields visibility
 | 
				
			||||||
 | 
					            toggleOctoFields();
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function checkSpoolmanInstance() {
 | 
					        function checkSpoolmanInstance() {
 | 
				
			||||||
            const url = document.getElementById('spoolmanUrl').value;
 | 
					            const url = document.getElementById('spoolmanUrl').value;
 | 
				
			||||||
            fetch(`/api/checkSpoolman?url=${encodeURIComponent(url)}`)
 | 
					            const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
 | 
				
			||||||
 | 
					            const spoolmanOctoUrl = document.getElementById('spoolmanOctoUrl').value;
 | 
				
			||||||
 | 
					            const spoolmanOctoToken = document.getElementById('spoolmanOctoToken').value;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            fetch(`/api/checkSpoolman?url=${encodeURIComponent(url)}&octoEnabled=${spoolmanOctoEnabled}&octoUrl=${spoolmanOctoUrl}&octoToken=${spoolmanOctoToken}`)
 | 
				
			||||||
                .then(response => response.json())
 | 
					                .then(response => response.json())
 | 
				
			||||||
                .then(data => {
 | 
					                .then(data => {
 | 
				
			||||||
                    if (data.healthy) {
 | 
					                    if (data.healthy) {
 | 
				
			||||||
@@ -90,6 +97,15 @@
 | 
				
			|||||||
                    document.getElementById('bambuStatusMessage').innerText = 'Error while saving: ' + error.message;
 | 
					                    document.getElementById('bambuStatusMessage').innerText = 'Error while saving: ' + error.message;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Controls visibility of OctoPrint configuration fields based on checkbox state
 | 
				
			||||||
 | 
					         * Called on page load and when checkbox changes
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        function toggleOctoFields() {
 | 
				
			||||||
 | 
					            const octoEnabled = document.getElementById('spoolmanOctoEnabled').checked;
 | 
				
			||||||
 | 
					            document.getElementById('octoFields').style.display = octoEnabled ? 'block' : 'none';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
        var spoolmanUrl = "{{spoolmanUrl}}";
 | 
					        var spoolmanUrl = "{{spoolmanUrl}}";
 | 
				
			||||||
@@ -102,6 +118,17 @@
 | 
				
			|||||||
            <div class="card-body">
 | 
					            <div class="card-body">
 | 
				
			||||||
                <h5 class="card-title">Set URL/IP to your Spoolman-Instanz</h5>
 | 
					                <h5 class="card-title">Set URL/IP to your Spoolman-Instanz</h5>
 | 
				
			||||||
                <input type="text" id="spoolmanUrl" placeholder="http://ip-or-url-of-your-spoolman-instanz:port">
 | 
					                <input type="text" id="spoolmanUrl" placeholder="http://ip-or-url-of-your-spoolman-instanz:port">
 | 
				
			||||||
 | 
					                <h5 class="card-title">If you want to enable sending Spool to Spoolman Octoprint Plugin:</h5>
 | 
				
			||||||
 | 
					                <p>
 | 
				
			||||||
 | 
					                    <input type="checkbox" id="spoolmanOctoEnabled" {{spoolmanOctoEnabled}} onchange="toggleOctoFields()"> Send to Octo-Plugin
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					                <div id="octoFields" style="display: none;">
 | 
				
			||||||
 | 
					                    <p>
 | 
				
			||||||
 | 
					                        <input type="text" id="spoolmanOctoUrl" placeholder="http://ip-or-url-of-your-octoprint-instanz:port" value="{{spoolmanOctoUrl}}">
 | 
				
			||||||
 | 
					                        <input type="text" id="spoolmanOctoToken" placeholder="Your Octoprint Token" value="{{spoolmanOctoToken}}">
 | 
				
			||||||
 | 
					                    </p>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                <button onclick="checkSpoolmanInstance()">Save Spoolman URL</button>
 | 
					                <button onclick="checkSpoolmanInstance()">Save Spoolman URL</button>
 | 
				
			||||||
                <p id="statusMessage"></p>
 | 
					                <p id="statusMessage"></p>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@@ -127,11 +154,11 @@
 | 
				
			|||||||
                    <p>If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.</p>
 | 
					                    <p>If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.</p>
 | 
				
			||||||
                    <div class="input-group" style="display: flex; margin-bottom: 0;">
 | 
					                    <div class="input-group" style="display: flex; margin-bottom: 0;">
 | 
				
			||||||
                        <label for="autoSend" style="width: 250px; margin-right: 5px;">Auto Send to Bambu:</label>
 | 
					                        <label for="autoSend" style="width: 250px; margin-right: 5px;">Auto Send to Bambu:</label>
 | 
				
			||||||
                        <label for="autoSendTime" style="width: 250px; margin-right: 5px;">Wait time in Seconds:</label>
 | 
					                        <label for="autoSendTime" style="width: 250px; margin-right: 5px;">Wait for Spool in Sec:</label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div class="input-group" style="display: flex;">
 | 
					                    <div class="input-group" style="display: flex;">
 | 
				
			||||||
                        <input type="checkbox" id="autoSend" {{autoSendToBambu}} style="width: 190px; margin-right: 10px;">
 | 
					                        <input type="checkbox" id="autoSend" {{autoSendToBambu}} style="width: 190px; margin-right: 10px;">
 | 
				
			||||||
                        <input type="text" id="autoSendTime" placeholder="Time to wait for new Spool" value="{{autoSendTime}}" style="width: 100px;">
 | 
					                        <input type="number" min="60" id="autoSendTime" placeholder="Time to wait" value="{{autoSendTime}}" style="width: 100px;">
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
 | 
					                    <button style="margin: 0;" onclick="saveBambuCredentials()">Save Bambu Credentials</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@ function populateVendorDropdown(data, selectedSmId = null) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Nach der Schleife: Formatierung der Gesamtlänge
 | 
					    // Nach der Schleife: Formatierung der Gesamtlänge
 | 
				
			||||||
    console.log("Total Lenght: ", totalLength);
 | 
					    console.log("Total Length: ", totalLength);
 | 
				
			||||||
    const formattedLength = totalLength > 1000 
 | 
					    const formattedLength = totalLength > 1000 
 | 
				
			||||||
        ? (totalLength / 1000).toFixed(2) + " km" 
 | 
					        ? (totalLength / 1000).toFixed(2) + " km" 
 | 
				
			||||||
        : totalLength.toFixed(2) + " m";
 | 
					        : totalLength.toFixed(2) + " m";
 | 
				
			||||||
@@ -97,13 +97,15 @@ function populateVendorDropdown(data, selectedSmId = null) {
 | 
				
			|||||||
        ? (weightInKg / 1000).toFixed(2) + " t" 
 | 
					        ? (weightInKg / 1000).toFixed(2) + " t" 
 | 
				
			||||||
        : weightInKg.toFixed(2) + " kg";
 | 
					        : weightInKg.toFixed(2) + " kg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dropdown mit gefilterten Herstellern befüllen
 | 
					    // Dropdown mit gefilterten Herstellern befüllen - alphabetisch sortiert
 | 
				
			||||||
    Object.entries(filteredVendors).forEach(([id, name]) => {
 | 
					    Object.entries(filteredVendors)
 | 
				
			||||||
        const option = document.createElement("option");
 | 
					        .sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) // Sort vendors alphabetically by name
 | 
				
			||||||
        option.value = id;
 | 
					        .forEach(([id, name]) => {
 | 
				
			||||||
        option.textContent = name;
 | 
					            const option = document.createElement("option");
 | 
				
			||||||
        vendorSelect.appendChild(option);
 | 
					            option.value = id;
 | 
				
			||||||
    });
 | 
					            option.textContent = name;
 | 
				
			||||||
 | 
					            vendorSelect.appendChild(option);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    document.getElementById("totalSpools").textContent = totalSpools;
 | 
					    document.getElementById("totalSpools").textContent = totalSpools;
 | 
				
			||||||
    document.getElementById("spoolsWithoutTag").textContent = spoolsWithoutTag;
 | 
					    document.getElementById("spoolsWithoutTag").textContent = spoolsWithoutTag;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -188,14 +188,18 @@ label {
 | 
				
			|||||||
    font-weight: bold; 
 | 
					    font-weight: bold; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
input[type="text"], input[type="submit"] { 
 | 
					input[type="text"], input[type="submit"], input[type="number"] { 
 | 
				
			||||||
    padding: 10px; 
 | 
					    padding: 10px; 
 | 
				
			||||||
    border: 1px solid #ccc; 
 | 
					    border: 1px solid #ccc; 
 | 
				
			||||||
    border-radius: 5px; 
 | 
					    border-radius: 5px; 
 | 
				
			||||||
    font-size: 16px; 
 | 
					    font-size: 16px; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
input[type="text"]:focus { 
 | 
					input[type="number"] { 
 | 
				
			||||||
 | 
					    width: 108px !important; 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input[type="text"]:focus, input[type="number"]:focus { 
 | 
				
			||||||
    border-color: #007bff; 
 | 
					    border-color: #007bff; 
 | 
				
			||||||
    outline: none; 
 | 
					    outline: none; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								img/7-enable.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								img/7-enable.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 52 KiB  | 
@@ -9,7 +9,9 @@
 | 
				
			|||||||
; https://docs.platformio.org/page/projectconf.html
 | 
					; https://docs.platformio.org/page/projectconf.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[common]
 | 
					[common]
 | 
				
			||||||
version = "1.3.97"
 | 
					version = "1.4.0"
 | 
				
			||||||
 | 
					to_old_version = "1.4.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
[env:esp32dev]
 | 
					[env:esp32dev]
 | 
				
			||||||
platform = espressif32
 | 
					platform = espressif32
 | 
				
			||||||
@@ -33,7 +35,8 @@ lib_deps =
 | 
				
			|||||||
    digitaldragon/SSLClient @ ^1.3.2
 | 
					    digitaldragon/SSLClient @ ^1.3.2
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
; Enable SPIFFS upload
 | 
					; Enable SPIFFS upload
 | 
				
			||||||
board_build.filesystem = spiffs
 | 
					#board_build.filesystem = spiffs
 | 
				
			||||||
 | 
					board_build.filesystem = littlefs
 | 
				
			||||||
; Update partition settings
 | 
					; Update partition settings
 | 
				
			||||||
board_build.partitions = partitions.csv
 | 
					board_build.partitions = partitions.csv
 | 
				
			||||||
board_upload.flash_size = 4MB
 | 
					board_upload.flash_size = 4MB
 | 
				
			||||||
@@ -44,13 +47,14 @@ build_flags =
 | 
				
			|||||||
    -Os
 | 
					    -Os
 | 
				
			||||||
    -ffunction-sections
 | 
					    -ffunction-sections
 | 
				
			||||||
    -fdata-sections
 | 
					    -fdata-sections
 | 
				
			||||||
    -DNDEBUG
 | 
					    #-DNDEBUG
 | 
				
			||||||
    -mtext-section-literals
 | 
					    -mtext-section-literals
 | 
				
			||||||
    -DVERSION=\"${common.version}\"
 | 
					    -DVERSION=\"${common.version}\"
 | 
				
			||||||
 | 
					    -DTOOLDVERSION=\"${common.to_old_version}\"
 | 
				
			||||||
    -DASYNCWEBSERVER_REGEX
 | 
					    -DASYNCWEBSERVER_REGEX
 | 
				
			||||||
    -DCORE_DEBUG_LEVEL=3
 | 
					    #-DCORE_DEBUG_LEVEL=3
 | 
				
			||||||
    -DCONFIG_ARDUHAL_LOG_COLORS=1
 | 
					    -DCONFIG_ARDUHAL_LOG_COLORS=1
 | 
				
			||||||
    -DOTA_DEBUG=1
 | 
					    #-DOTA_DEBUG=1
 | 
				
			||||||
    -DCONFIG_OPTIMIZATION_LEVEL_DEBUG=1
 | 
					    -DCONFIG_OPTIMIZATION_LEVEL_DEBUG=1
 | 
				
			||||||
    -DBOOT_APP_PARTITION_OTA_0=1
 | 
					    -DBOOT_APP_PARTITION_OTA_0=1
 | 
				
			||||||
    -DCONFIG_LWIP_TCP_MSL=60000
 | 
					    -DCONFIG_LWIP_TCP_MSL=60000
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										90
									
								
								src/api.cpp
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								src/api.cpp
									
									
									
									
									
								
							@@ -5,38 +5,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool spoolman_connected = false;
 | 
					bool spoolman_connected = false;
 | 
				
			||||||
String spoolmanUrl = "";
 | 
					String spoolmanUrl = "";
 | 
				
			||||||
 | 
					bool octoEnabled = false;
 | 
				
			||||||
 | 
					String octoUrl = "";
 | 
				
			||||||
 | 
					String octoToken = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SendToApiParams {
 | 
					struct SendToApiParams {
 | 
				
			||||||
    String httpType;
 | 
					    String httpType;
 | 
				
			||||||
    String spoolsUrl;
 | 
					    String spoolsUrl;
 | 
				
			||||||
    String updatePayload;
 | 
					    String updatePayload;
 | 
				
			||||||
 | 
					    String octoToken;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
    // Spoolman Data
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        "version":"1.0",
 | 
					 | 
				
			||||||
        "protocol":"openspool",
 | 
					 | 
				
			||||||
        "color_hex":"AF7933",
 | 
					 | 
				
			||||||
        "type":"ABS",
 | 
					 | 
				
			||||||
        "min_temp":175,
 | 
					 | 
				
			||||||
        "max_temp":275,
 | 
					 | 
				
			||||||
        "brand":"Overture"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // FilaMan Data
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        "version":"1.0",
 | 
					 | 
				
			||||||
        "protocol":"openspool",
 | 
					 | 
				
			||||||
        "color_hex":"AF7933",
 | 
					 | 
				
			||||||
        "type":"ABS",
 | 
					 | 
				
			||||||
        "min_temp":175,
 | 
					 | 
				
			||||||
        "max_temp":275,
 | 
					 | 
				
			||||||
        "brand":"Overture",
 | 
					 | 
				
			||||||
        "sm_id": 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
JsonDocument fetchSingleSpoolInfo(int spoolId) {
 | 
					JsonDocument fetchSingleSpoolInfo(int spoolId) {
 | 
				
			||||||
    HTTPClient http;
 | 
					    HTTPClient http;
 | 
				
			||||||
    String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId;
 | 
					    String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId;
 | 
				
			||||||
@@ -112,14 +91,16 @@ void sendToApi(void *parameter) {
 | 
				
			|||||||
    String httpType = params->httpType;
 | 
					    String httpType = params->httpType;
 | 
				
			||||||
    String spoolsUrl = params->spoolsUrl;
 | 
					    String spoolsUrl = params->spoolsUrl;
 | 
				
			||||||
    String updatePayload = params->updatePayload;
 | 
					    String updatePayload = params->updatePayload;
 | 
				
			||||||
    
 | 
					    String octoToken = params->octoToken;    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HTTPClient http;
 | 
					    HTTPClient http;
 | 
				
			||||||
    http.begin(spoolsUrl);
 | 
					    http.begin(spoolsUrl);
 | 
				
			||||||
    http.addHeader("Content-Type", "application/json");
 | 
					    http.addHeader("Content-Type", "application/json");
 | 
				
			||||||
 | 
					    if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int httpCode = http.PUT(updatePayload);
 | 
					    int httpCode = http.PUT(updatePayload);
 | 
				
			||||||
    if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
 | 
					    if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
 | 
				
			||||||
 | 
					    if (httpType == "POST") httpCode = http.POST(updatePayload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (httpCode == HTTP_CODE_OK) {
 | 
					    if (httpCode == HTTP_CODE_OK) {
 | 
				
			||||||
        Serial.println("Spoolman erfolgreich aktualisiert");
 | 
					        Serial.println("Spoolman erfolgreich aktualisiert");
 | 
				
			||||||
@@ -223,6 +204,43 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
 | 
				
			|||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool updateSpoolOcto(int spoolId) {
 | 
				
			||||||
 | 
					    String spoolsUrl = octoUrl + "/plugin/Spoolman/selectSpool";
 | 
				
			||||||
 | 
					    Serial.print("Update Spule in Octoprint mit URL: ");
 | 
				
			||||||
 | 
					    Serial.println(spoolsUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JsonDocument updateDoc;
 | 
				
			||||||
 | 
					    updateDoc["spool_id"] = spoolId;
 | 
				
			||||||
 | 
					    updateDoc["tool"] = "tool0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    String updatePayload;
 | 
				
			||||||
 | 
					    serializeJson(updateDoc, updatePayload);
 | 
				
			||||||
 | 
					    Serial.print("Update Payload: ");
 | 
				
			||||||
 | 
					    Serial.println(updatePayload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SendToApiParams* params = new SendToApiParams();
 | 
				
			||||||
 | 
					    if (params == nullptr) {
 | 
				
			||||||
 | 
					        Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren.");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    params->httpType = "POST";
 | 
				
			||||||
 | 
					    params->spoolsUrl = spoolsUrl;
 | 
				
			||||||
 | 
					    params->updatePayload = updatePayload;
 | 
				
			||||||
 | 
					    params->octoToken = octoToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Erstelle die Task
 | 
				
			||||||
 | 
					    BaseType_t result = xTaskCreate(
 | 
				
			||||||
 | 
					        sendToApi,                // Task-Funktion
 | 
				
			||||||
 | 
					        "SendToApiTask",          // Task-Name
 | 
				
			||||||
 | 
					        4096,                     // Stackgröße in Bytes
 | 
				
			||||||
 | 
					        (void*)params,            // Parameter
 | 
				
			||||||
 | 
					        0,                        // Priorität
 | 
				
			||||||
 | 
					        NULL                      // Task-Handle (nicht benötigt)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool updateSpoolBambuData(String payload) {
 | 
					bool updateSpoolBambuData(String payload) {
 | 
				
			||||||
    JsonDocument doc;
 | 
					    JsonDocument doc;
 | 
				
			||||||
    DeserializationError error = deserializeJson(doc, payload);
 | 
					    DeserializationError error = deserializeJson(doc, payload);
 | 
				
			||||||
@@ -460,17 +478,24 @@ bool checkSpoolmanInstance(const String& url) {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool saveSpoolmanUrl(const String& url) {
 | 
					bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk) {
 | 
				
			||||||
    if (!checkSpoolmanInstance(url)) return false;
 | 
					    if (!checkSpoolmanInstance(url)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    JsonDocument doc;
 | 
					    JsonDocument doc;
 | 
				
			||||||
    doc["url"] = url;
 | 
					    doc["url"] = url;
 | 
				
			||||||
    Serial.print("Speichere URL in Datei: ");
 | 
					    doc["octoEnabled"] = octoOn;
 | 
				
			||||||
    Serial.println(url);
 | 
					    doc["octoUrl"] = octoWh;
 | 
				
			||||||
 | 
					    doc["octoToken"] = octoTk;
 | 
				
			||||||
 | 
					    Serial.print("Speichere Spoolman Data in Datei: ");
 | 
				
			||||||
 | 
					    Serial.println(doc.as<String>());
 | 
				
			||||||
    if (!saveJsonValue("/spoolman_url.json", doc)) {
 | 
					    if (!saveJsonValue("/spoolman_url.json", doc)) {
 | 
				
			||||||
        Serial.println("Fehler beim Speichern der Spoolman-URL.");
 | 
					        Serial.println("Fehler beim Speichern der Spoolman-URL.");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    spoolmanUrl = url;
 | 
					    spoolmanUrl = url;
 | 
				
			||||||
 | 
					    octoEnabled = octoOn;
 | 
				
			||||||
 | 
					    octoUrl = octoWh;
 | 
				
			||||||
 | 
					    octoToken = octoTk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -478,6 +503,13 @@ bool saveSpoolmanUrl(const String& url) {
 | 
				
			|||||||
String loadSpoolmanUrl() {
 | 
					String loadSpoolmanUrl() {
 | 
				
			||||||
    JsonDocument doc;
 | 
					    JsonDocument doc;
 | 
				
			||||||
    if (loadJsonValue("/spoolman_url.json", doc) && doc["url"].is<String>()) {
 | 
					    if (loadJsonValue("/spoolman_url.json", doc) && doc["url"].is<String>()) {
 | 
				
			||||||
 | 
					        octoEnabled = (doc["octoEnabled"].is<bool>()) ? doc["octoEnabled"].as<bool>() : false;
 | 
				
			||||||
 | 
					        if (octoEnabled && doc["octoToken"].is<String>() && doc["octoUrl"].is<String>())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            octoUrl = doc["octoUrl"].as<String>();
 | 
				
			||||||
 | 
					            octoToken = doc["octoToken"].as<String>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return doc["url"].as<String>();
 | 
					        return doc["url"].as<String>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Serial.println("Keine gültige Spoolman-URL gefunden.");
 | 
					    Serial.println("Keine gültige Spoolman-URL gefunden.");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,9 +9,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
extern bool spoolman_connected;
 | 
					extern bool spoolman_connected;
 | 
				
			||||||
extern String spoolmanUrl;
 | 
					extern String spoolmanUrl;
 | 
				
			||||||
 | 
					extern bool octoEnabled;
 | 
				
			||||||
 | 
					extern String octoUrl;
 | 
				
			||||||
 | 
					extern String octoToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool checkSpoolmanInstance(const String& url);
 | 
					bool checkSpoolmanInstance(const String& url);
 | 
				
			||||||
bool saveSpoolmanUrl(const String& url);
 | 
					bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk);
 | 
				
			||||||
String loadSpoolmanUrl(); // Neue Funktion zum Laden der URL
 | 
					String loadSpoolmanUrl(); // Neue Funktion zum Laden der URL
 | 
				
			||||||
bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafelder
 | 
					bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafelder
 | 
				
			||||||
JsonDocument fetchSingleSpoolInfo(int spoolId); // API-Funktion für die Webseite
 | 
					JsonDocument fetchSingleSpoolInfo(int spoolId); // API-Funktion für die Webseite
 | 
				
			||||||
@@ -19,5 +22,6 @@ bool updateSpoolTagId(String uidString, const char* payload); // Neue Funktion z
 | 
				
			|||||||
uint8_t updateSpoolWeight(String spoolId, uint16_t weight); // Neue Funktion zum Aktualisieren des Gewichts
 | 
					uint8_t updateSpoolWeight(String spoolId, uint16_t weight); // Neue Funktion zum Aktualisieren des Gewichts
 | 
				
			||||||
bool initSpoolman(); // Neue Funktion zum Initialisieren von Spoolman
 | 
					bool initSpoolman(); // Neue Funktion zum Initialisieren von Spoolman
 | 
				
			||||||
bool updateSpoolBambuData(String payload); // Neue Funktion zum Aktualisieren der Bambu-Daten
 | 
					bool updateSpoolBambuData(String payload); // Neue Funktion zum Aktualisieren der Bambu-Daten
 | 
				
			||||||
 | 
					bool updateSpoolOcto(int spoolId); // Neue Funktion zum Aktualisieren der Octo-Daten
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -341,7 +341,7 @@ void updateAmsWsData(JsonDocument& doc, JsonArray& amsArray, int& ams_count, Jso
 | 
				
			|||||||
            ams_data[i].trays[j].tray_color = trayObj["tray_color"].as<String>();
 | 
					            ams_data[i].trays[j].tray_color = trayObj["tray_color"].as<String>();
 | 
				
			||||||
            ams_data[i].trays[j].nozzle_temp_min = trayObj["nozzle_temp_min"].as<int>();
 | 
					            ams_data[i].trays[j].nozzle_temp_min = trayObj["nozzle_temp_min"].as<int>();
 | 
				
			||||||
            ams_data[i].trays[j].nozzle_temp_max = trayObj["nozzle_temp_max"].as<int>();
 | 
					            ams_data[i].trays[j].nozzle_temp_max = trayObj["nozzle_temp_max"].as<int>();
 | 
				
			||||||
            //ams_data[i].trays[j].setting_id = trayObj["setting_id"].as<String>();
 | 
					            if (trayObj["tray_type"].as<String>() == "") ams_data[i].trays[j].setting_id = "";
 | 
				
			||||||
            ams_data[i].trays[j].cali_idx = trayObj["cali_idx"].as<String>();
 | 
					            ams_data[i].trays[j].cali_idx = trayObj["cali_idx"].as<String>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -425,16 +425,8 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Wenn bambu auto set spool aktiv und eine spule erkannt und mqtt meldung das neue spule im ams
 | 
					 | 
				
			||||||
    if (autoSendToBambu && autoSetToBambuSpoolId > 0 && 
 | 
					 | 
				
			||||||
        doc["print"]["command"].as<String>() == "push_status" && doc["print"]["ams"]["tray_pre"].as<uint8_t>()
 | 
					 | 
				
			||||||
        && !doc["print"]["ams"]["ams"].as<JsonArray>())
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        autoSetSpool(autoSetToBambuSpoolId, doc["print"]["ams"]["tray_pre"].as<uint8_t>());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Prüfen, ob "print->upgrade_state" und "print.ams.ams" existieren
 | 
					    // Prüfen, ob "print->upgrade_state" und "print.ams.ams" existieren
 | 
				
			||||||
    if (doc["print"]["upgrade_state"].is<JsonObject>()) 
 | 
					    if (doc["print"]["upgrade_state"].is<JsonObject>() || (doc["print"]["command"].is<String>() && doc["print"]["command"] == "push_status")) 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Prüfen ob AMS-Daten vorhanden sind
 | 
					        // Prüfen ob AMS-Daten vorhanden sind
 | 
				
			||||||
        if (!doc["print"]["ams"].is<JsonObject>() || !doc["print"]["ams"]["ams"].is<JsonArray>()) 
 | 
					        if (!doc["print"]["ams"].is<JsonObject>() || !doc["print"]["ams"]["ams"].is<JsonArray>()) 
 | 
				
			||||||
@@ -479,6 +471,12 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
 | 
				
			|||||||
                    (trayObj["setting_id"].as<String>() != "" && trayObj["setting_id"].as<String>() != ams_data[storedIndex].trays[j].setting_id) ||
 | 
					                    (trayObj["setting_id"].as<String>() != "" && trayObj["setting_id"].as<String>() != ams_data[storedIndex].trays[j].setting_id) ||
 | 
				
			||||||
                    trayObj["cali_idx"].as<String>() != ams_data[storedIndex].trays[j].cali_idx) {
 | 
					                    trayObj["cali_idx"].as<String>() != ams_data[storedIndex].trays[j].cali_idx) {
 | 
				
			||||||
                    hasChanges = true;
 | 
					                    hasChanges = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        autoSetSpool(autoSetToBambuSpoolId, ams_data[storedIndex].trays[j].id);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -497,6 +495,11 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
 | 
				
			|||||||
                        (vtTray["setting_id"].as<String>() != "" && vtTray["setting_id"].as<String>() != ams_data[i].trays[0].setting_id) ||
 | 
					                        (vtTray["setting_id"].as<String>() != "" && vtTray["setting_id"].as<String>() != ams_data[i].trays[0].setting_id) ||
 | 
				
			||||||
                        (vtTray["tray_type"].as<String>() != "" && vtTray["cali_idx"].as<String>() != ams_data[i].trays[0].cali_idx)) {
 | 
					                        (vtTray["tray_type"].as<String>() != "" && vtTray["cali_idx"].as<String>() != ams_data[i].trays[0].cali_idx)) {
 | 
				
			||||||
                        hasChanges = true;
 | 
					                        hasChanges = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            autoSetSpool(autoSetToBambuSpoolId, 254);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -600,7 +603,6 @@ void mqtt_loop(void * parameter) {
 | 
				
			|||||||
bool setupMqtt() {
 | 
					bool setupMqtt() {
 | 
				
			||||||
    // Wenn Bambu Daten vorhanden
 | 
					    // Wenn Bambu Daten vorhanden
 | 
				
			||||||
    bool success = loadBambuCredentials();
 | 
					    bool success = loadBambuCredentials();
 | 
				
			||||||
    vTaskDelay(100 / portTICK_PERIOD_MS);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!success) {
 | 
					    if (!success) {
 | 
				
			||||||
        Serial.println("Failed to load Bambu credentials");
 | 
					        Serial.println("Failed to load Bambu credentials");
 | 
				
			||||||
@@ -664,6 +666,7 @@ bool setupMqtt() {
 | 
				
			|||||||
void bambu_restart() {
 | 
					void bambu_restart() {
 | 
				
			||||||
    if (BambuMqttTask) {
 | 
					    if (BambuMqttTask) {
 | 
				
			||||||
        vTaskDelete(BambuMqttTask);
 | 
					        vTaskDelete(BambuMqttTask);
 | 
				
			||||||
 | 
					        delay(10);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    setupMqtt();
 | 
					    setupMqtt();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
#include "commonFS.h"
 | 
					#include "commonFS.h"
 | 
				
			||||||
#include <SPIFFS.h>
 | 
					#include <LittleFS.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool saveJsonValue(const char* filename, const JsonDocument& doc) {
 | 
					bool saveJsonValue(const char* filename, const JsonDocument& doc) {
 | 
				
			||||||
    File file = SPIFFS.open(filename, "w");
 | 
					    File file = LittleFS.open(filename, "w");
 | 
				
			||||||
    if (!file) {
 | 
					    if (!file) {
 | 
				
			||||||
        Serial.print("Fehler beim Öffnen der Datei zum Schreiben: ");
 | 
					        Serial.print("Fehler beim Öffnen der Datei zum Schreiben: ");
 | 
				
			||||||
        Serial.println(filename);
 | 
					        Serial.println(filename);
 | 
				
			||||||
@@ -20,7 +20,7 @@ bool saveJsonValue(const char* filename, const JsonDocument& doc) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool loadJsonValue(const char* filename, JsonDocument& doc) {
 | 
					bool loadJsonValue(const char* filename, JsonDocument& doc) {
 | 
				
			||||||
    File file = SPIFFS.open(filename, "r");
 | 
					    File file = LittleFS.open(filename, "r");
 | 
				
			||||||
    if (!file) {
 | 
					    if (!file) {
 | 
				
			||||||
        Serial.print("Fehler beim Öffnen der Datei zum Lesen: ");
 | 
					        Serial.print("Fehler beim Öffnen der Datei zum Lesen: ");
 | 
				
			||||||
        Serial.println(filename);
 | 
					        Serial.println(filename);
 | 
				
			||||||
@@ -36,12 +36,12 @@ bool loadJsonValue(const char* filename, JsonDocument& doc) {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void initializeSPIFFS() {
 | 
					void initializeFileSystem() {
 | 
				
			||||||
    if (!SPIFFS.begin(true, "/spiffs", 10, "spiffs")) {
 | 
					    if (!LittleFS.begin(true)) {
 | 
				
			||||||
        Serial.println("SPIFFS Mount Failed");
 | 
					        Serial.println("LittleFS Mount Failed");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Serial.printf("SPIFFS Total: %u bytes\n", SPIFFS.totalBytes());
 | 
					    Serial.printf("LittleFS Total: %u bytes\n", LittleFS.totalBytes());
 | 
				
			||||||
    Serial.printf("SPIFFS Used: %u bytes\n", SPIFFS.usedBytes());
 | 
					    Serial.printf("LittleFS Used: %u bytes\n", LittleFS.usedBytes());
 | 
				
			||||||
    Serial.printf("SPIFFS Free: %u bytes\n", SPIFFS.totalBytes() - SPIFFS.usedBytes());
 | 
					    Serial.printf("LittleFS Free: %u bytes\n", LittleFS.totalBytes() - LittleFS.usedBytes());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2,11 +2,11 @@
 | 
				
			|||||||
#define COMMONFS_H
 | 
					#define COMMONFS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <Arduino.h>
 | 
					#include <Arduino.h>
 | 
				
			||||||
#include <SPIFFS.h>
 | 
					 | 
				
			||||||
#include <ArduinoJson.h>
 | 
					#include <ArduinoJson.h>
 | 
				
			||||||
 | 
					#include <LittleFS.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool saveJsonValue(const char* filename, const JsonDocument& doc);
 | 
					bool saveJsonValue(const char* filename, const JsonDocument& doc);
 | 
				
			||||||
bool loadJsonValue(const char* filename, JsonDocument& doc);
 | 
					bool loadJsonValue(const char* filename, JsonDocument& doc);
 | 
				
			||||||
void initializeSPIFFS();
 | 
					void initializeFileSystem();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										66
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -24,7 +24,7 @@ void setup() {
 | 
				
			|||||||
  Serial.printf("%08X\n", (uint32_t)chipid); //print Low 4bytes.
 | 
					  Serial.printf("%08X\n", (uint32_t)chipid); //print Low 4bytes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize SPIFFS
 | 
					  // Initialize SPIFFS
 | 
				
			||||||
  initializeSPIFFS();
 | 
					  initializeFileSystem();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Start Display
 | 
					  // Start Display
 | 
				
			||||||
  setupDisplay();
 | 
					  setupDisplay();
 | 
				
			||||||
@@ -74,6 +74,21 @@ void setup() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Safe interval check that handles millis() overflow
 | 
				
			||||||
 | 
					 * @param currentTime Current millis() value
 | 
				
			||||||
 | 
					 * @param lastTime Last recorded time
 | 
				
			||||||
 | 
					 * @param interval Desired interval in milliseconds
 | 
				
			||||||
 | 
					 * @return True if interval has elapsed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool intervalElapsed(unsigned long currentTime, unsigned long &lastTime, unsigned long interval) {
 | 
				
			||||||
 | 
					  if (currentTime - lastTime >= interval || currentTime < lastTime) {
 | 
				
			||||||
 | 
					    lastTime = currentTime;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned long lastWeightReadTime = 0;
 | 
					unsigned long lastWeightReadTime = 0;
 | 
				
			||||||
const unsigned long weightReadInterval = 1000; // 1 second
 | 
					const unsigned long weightReadInterval = 1000; // 1 second
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -81,9 +96,6 @@ unsigned long lastAutoSetBambuAmsTime = 0;
 | 
				
			|||||||
const unsigned long autoSetBambuAmsInterval = 1000; // 1 second
 | 
					const unsigned long autoSetBambuAmsInterval = 1000; // 1 second
 | 
				
			||||||
uint8_t autoAmsCounter = 0;
 | 
					uint8_t autoAmsCounter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned long lastAmsSendTime = 0;
 | 
					 | 
				
			||||||
const unsigned long amsSendInterval = 60000; // 1 minute
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint8_t weightSend = 0;
 | 
					uint8_t weightSend = 0;
 | 
				
			||||||
int16_t lastWeight = 0;
 | 
					int16_t lastWeight = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,41 +107,34 @@ void loop() {
 | 
				
			|||||||
  unsigned long currentMillis = millis();
 | 
					  unsigned long currentMillis = millis();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Überprüfe regelmäßig die WLAN-Verbindung
 | 
					  // Überprüfe regelmäßig die WLAN-Verbindung
 | 
				
			||||||
  if (millis() - lastWifiCheckTime > wifiCheckInterval) {
 | 
					  if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) {
 | 
				
			||||||
    checkWiFiConnection();
 | 
					    checkWiFiConnection();
 | 
				
			||||||
    lastWifiCheckTime = millis();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Send AMS Data min every Minute
 | 
					 | 
				
			||||||
  if (currentMillis - lastAmsSendTime >= amsSendInterval) 
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    lastAmsSendTime = currentMillis;
 | 
					 | 
				
			||||||
    //sendAmsData(nullptr);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Wenn Bambu auto set Spool aktiv
 | 
					  // Wenn Bambu auto set Spool aktiv
 | 
				
			||||||
  if (autoSendToBambu && autoSetToBambuSpoolId > 0 && currentMillis - lastAutoSetBambuAmsTime >= autoSetBambuAmsInterval) 
 | 
					  if (autoSendToBambu && autoSetToBambuSpoolId > 0) {
 | 
				
			||||||
  {
 | 
					    if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval)) 
 | 
				
			||||||
    if (hasReadRfidTag == 0)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      lastAutoSetBambuAmsTime = currentMillis;
 | 
					      if (hasReadRfidTag == 0)
 | 
				
			||||||
      oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
 | 
					      {
 | 
				
			||||||
      autoAmsCounter++;
 | 
					        lastAutoSetBambuAmsTime = currentMillis;
 | 
				
			||||||
 | 
					        oledShowMessage("Auto Set         " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s");
 | 
				
			||||||
      if (autoAmsCounter >= autoSetBambuAmsCounter) 
 | 
					        autoAmsCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (autoAmsCounter >= autoSetBambuAmsCounter) 
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          autoSetToBambuSpoolId = 0;
 | 
				
			||||||
 | 
					          autoAmsCounter = 0;
 | 
				
			||||||
 | 
					          oledShowWeight(weight);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        autoSetToBambuSpoolId = 0;
 | 
					 | 
				
			||||||
        autoAmsCounter = 0;
 | 
					        autoAmsCounter = 0;
 | 
				
			||||||
        oledShowWeight(weight);
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      autoAmsCounter = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Wenn Waage nicht Kalibriert
 | 
					  // Wenn Waage nicht Kalibriert
 | 
				
			||||||
  if (scaleCalibrated == 3) 
 | 
					  if (scaleCalibrated == 3) 
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@@ -192,6 +197,11 @@ void loop() {
 | 
				
			|||||||
      vTaskDelay(2000 / portTICK_PERIOD_MS);
 | 
					      vTaskDelay(2000 / portTICK_PERIOD_MS);
 | 
				
			||||||
      weightSend = 1;
 | 
					      weightSend = 1;
 | 
				
			||||||
      autoSetToBambuSpoolId = spoolId.toInt();
 | 
					      autoSetToBambuSpoolId = spoolId.toInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (octoEnabled) 
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        updateSpoolOcto(autoSetToBambuSpoolId);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								src/nfc.cpp
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								src/nfc.cpp
									
									
									
									
									
								
							@@ -44,8 +44,6 @@ void payloadToJson(uint8_t *data) {
 | 
				
			|||||||
      DeserializationError error = deserializeJson(doc, jsonString);
 | 
					      DeserializationError error = deserializeJson(doc, jsonString);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
      if (!error) {
 | 
					      if (!error) {
 | 
				
			||||||
        const char* version = doc["version"];
 | 
					 | 
				
			||||||
        const char* protocol = doc["protocol"];
 | 
					 | 
				
			||||||
        const char* color_hex = doc["color_hex"];
 | 
					        const char* color_hex = doc["color_hex"];
 | 
				
			||||||
        const char* type = doc["type"];
 | 
					        const char* type = doc["type"];
 | 
				
			||||||
        int min_temp = doc["min_temp"];
 | 
					        int min_temp = doc["min_temp"];
 | 
				
			||||||
@@ -55,8 +53,6 @@ void payloadToJson(uint8_t *data) {
 | 
				
			|||||||
        Serial.println();
 | 
					        Serial.println();
 | 
				
			||||||
        Serial.println("-----------------");
 | 
					        Serial.println("-----------------");
 | 
				
			||||||
        Serial.println("JSON-Parsed Data:");
 | 
					        Serial.println("JSON-Parsed Data:");
 | 
				
			||||||
        Serial.println(version);
 | 
					 | 
				
			||||||
        Serial.println(protocol);
 | 
					 | 
				
			||||||
        Serial.println(color_hex);
 | 
					        Serial.println(color_hex);
 | 
				
			||||||
        Serial.println(type);
 | 
					        Serial.println(type);
 | 
				
			||||||
        Serial.println(min_temp);
 | 
					        Serial.println(min_temp);
 | 
				
			||||||
@@ -93,8 +89,16 @@ bool formatNdefTag() {
 | 
				
			|||||||
    return success;
 | 
					    return success;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t readTagSize()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t buffer[4];
 | 
				
			||||||
 | 
					  memset(buffer, 0, 4);
 | 
				
			||||||
 | 
					  nfc.ntag2xx_ReadPage(3, buffer);
 | 
				
			||||||
 | 
					  return buffer[2]*8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t ntag2xx_WriteNDEF(const char *payload) {
 | 
					uint8_t ntag2xx_WriteNDEF(const char *payload) {
 | 
				
			||||||
  uint8_t tagSize = 240; // 144 bytes is maximum for NTAG213
 | 
					  uint16_t tagSize = readTagSize();
 | 
				
			||||||
  Serial.print("Tag Size: ");Serial.println(tagSize);
 | 
					  Serial.print("Tag Size: ");Serial.println(tagSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint8_t pageBuffer[4] = {0, 0, 0, 0};
 | 
					  uint8_t pageBuffer[4] = {0, 0, 0, 0};
 | 
				
			||||||
@@ -136,6 +140,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) {
 | 
				
			|||||||
  if (combinedData == NULL) 
 | 
					  if (combinedData == NULL) 
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    Serial.println("Fehler: Nicht genug Speicher vorhanden.");
 | 
					    Serial.println("Fehler: Nicht genug Speicher vorhanden.");
 | 
				
			||||||
 | 
					    oledShowMessage("Tag too small");
 | 
				
			||||||
 | 
					    vTaskDelay(2000 / portTICK_PERIOD_MS);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -369,46 +375,51 @@ void scanRfidTask(void * parameter) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (uidLength == 7)
 | 
					        if (uidLength == 7)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          uint8_t data[256];
 | 
					          uint16_t tagSize = readTagSize();
 | 
				
			||||||
 | 
					          if(tagSize > 0)
 | 
				
			||||||
          // We probably have an NTAG2xx card (though it could be Ultralight as well)
 | 
					 | 
				
			||||||
          Serial.println("Seems to be an NTAG2xx tag (7 byte UID)");
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          for (uint8_t i = 0; i < 45; i++) {
 | 
					 | 
				
			||||||
            /*
 | 
					 | 
				
			||||||
            if (i < uidLength) {
 | 
					 | 
				
			||||||
              uidString += String(uid[i], HEX);
 | 
					 | 
				
			||||||
              if (i < uidLength - 1) {
 | 
					 | 
				
			||||||
                  uidString += ":"; // Optional: Trennzeichen hinzufügen
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            */
 | 
					 | 
				
			||||||
            if (!nfc.mifareclassic_ReadDataBlock(i, data + (i - 4) * 4)) 
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              break; // Stop if reading fails
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // Check for NDEF message end
 | 
					 | 
				
			||||||
            if (data[(i - 4) * 4] == 0xFE) 
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              break; // End of NDEF message
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            yield();
 | 
					 | 
				
			||||||
            esp_task_wdt_reset();
 | 
					 | 
				
			||||||
            vTaskDelay(pdMS_TO_TICKS(1));
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if (!decodeNdefAndReturnJson(data)) 
 | 
					 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            oledShowMessage("NFC-Tag unknown");
 | 
					            // Create a buffer depending on the size of the tag
 | 
				
			||||||
            vTaskDelay(2000 / portTICK_PERIOD_MS);
 | 
					            uint8_t* data = (uint8_t*)malloc(tagSize);
 | 
				
			||||||
            hasReadRfidTag = 2;
 | 
					            memset(data, 0, tagSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // We probably have an NTAG2xx card (though it could be Ultralight as well)
 | 
				
			||||||
 | 
					            Serial.println("Seems to be an NTAG2xx tag (7 byte UID)");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            uint8_t numPages = readTagSize()/4;
 | 
				
			||||||
 | 
					            for (uint8_t i = 4; i < 4+numPages; i++) {
 | 
				
			||||||
 | 
					              if (!nfc.ntag2xx_ReadPage(i, data+(i-4) * 4))
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                break; // Stop if reading fails
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              // Check for NDEF message end
 | 
				
			||||||
 | 
					              if (data[(i - 4) * 4] == 0xFE) 
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                break; // End of NDEF message
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              yield();
 | 
				
			||||||
 | 
					              esp_task_wdt_reset();
 | 
				
			||||||
 | 
					              vTaskDelay(pdMS_TO_TICKS(1));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!decodeNdefAndReturnJson(data)) 
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              oledShowMessage("NFC-Tag unknown");
 | 
				
			||||||
 | 
					              vTaskDelay(2000 / portTICK_PERIOD_MS);
 | 
				
			||||||
 | 
					              hasReadRfidTag = 2;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else 
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              hasReadRfidTag = 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            free(data);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          else
 | 
					          else
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            hasReadRfidTag = 1;
 | 
					            oledShowMessage("NFC-Tag read error");
 | 
				
			||||||
 | 
					            hasReadRfidTag = 2;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
         
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										50
									
								
								src/ota.cpp
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/ota.cpp
									
									
									
									
									
								
							@@ -14,11 +14,39 @@ static size_t updateTotalSize = 0;
 | 
				
			|||||||
static size_t updateWritten = 0;
 | 
					static size_t updateWritten = 0;
 | 
				
			||||||
static bool isSpiffsUpdate = false;
 | 
					static bool isSpiffsUpdate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compares two version strings and determines if version1 is less than version2
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param version1 First version string (format: x.y.z)
 | 
				
			||||||
 | 
					 * @param version2 Second version string (format: x.y.z)
 | 
				
			||||||
 | 
					 * @return true if version1 is less than version2
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool isVersionLessThan(const String& version1, const String& version2) {
 | 
				
			||||||
 | 
					    int major1 = 0, minor1 = 0, patch1 = 0;
 | 
				
			||||||
 | 
					    int major2 = 0, minor2 = 0, patch2 = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Parse version1
 | 
				
			||||||
 | 
					    sscanf(version1.c_str(), "%d.%d.%d", &major1, &minor1, &patch1);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Parse version2
 | 
				
			||||||
 | 
					    sscanf(version2.c_str(), "%d.%d.%d", &major2, &minor2, &patch2);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Compare major version
 | 
				
			||||||
 | 
					    if (major1 < major2) return true;
 | 
				
			||||||
 | 
					    if (major1 > major2) return false;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Major versions equal, compare minor
 | 
				
			||||||
 | 
					    if (minor1 < minor2) return true;
 | 
				
			||||||
 | 
					    if (minor1 > minor2) return false;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Minor versions equal, compare patch
 | 
				
			||||||
 | 
					    return patch1 < patch2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void backupJsonConfigs() {
 | 
					void backupJsonConfigs() {
 | 
				
			||||||
    // Bambu Credentials backup
 | 
					    // Bambu Credentials backup
 | 
				
			||||||
    if (SPIFFS.exists("/bambu_credentials.json")) {
 | 
					    if (LittleFS.exists("/bambu_credentials.json")) {
 | 
				
			||||||
        File file = SPIFFS.open("/bambu_credentials.json", "r");
 | 
					        File file = LittleFS.open("/bambu_credentials.json", "r");
 | 
				
			||||||
        if (file) {
 | 
					        if (file) {
 | 
				
			||||||
            bambuCredentialsBackup = file.readString();
 | 
					            bambuCredentialsBackup = file.readString();
 | 
				
			||||||
            file.close();
 | 
					            file.close();
 | 
				
			||||||
@@ -27,8 +55,8 @@ void backupJsonConfigs() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Spoolman URL backup
 | 
					    // Spoolman URL backup
 | 
				
			||||||
    if (SPIFFS.exists("/spoolman_url.json")) {
 | 
					    if (LittleFS.exists("/spoolman_url.json")) {
 | 
				
			||||||
        File file = SPIFFS.open("/spoolman_url.json", "r");
 | 
					        File file = LittleFS.open("/spoolman_url.json", "r");
 | 
				
			||||||
        if (file) {
 | 
					        if (file) {
 | 
				
			||||||
            spoolmanUrlBackup = file.readString();
 | 
					            spoolmanUrlBackup = file.readString();
 | 
				
			||||||
            file.close();
 | 
					            file.close();
 | 
				
			||||||
@@ -40,7 +68,7 @@ void backupJsonConfigs() {
 | 
				
			|||||||
void restoreJsonConfigs() {
 | 
					void restoreJsonConfigs() {
 | 
				
			||||||
    // Restore Bambu credentials
 | 
					    // Restore Bambu credentials
 | 
				
			||||||
    if (bambuCredentialsBackup.length() > 0) {
 | 
					    if (bambuCredentialsBackup.length() > 0) {
 | 
				
			||||||
        File file = SPIFFS.open("/bambu_credentials.json", "w");
 | 
					        File file = LittleFS.open("/bambu_credentials.json", "w");
 | 
				
			||||||
        if (file) {
 | 
					        if (file) {
 | 
				
			||||||
            file.print(bambuCredentialsBackup);
 | 
					            file.print(bambuCredentialsBackup);
 | 
				
			||||||
            file.close();
 | 
					            file.close();
 | 
				
			||||||
@@ -51,7 +79,7 @@ void restoreJsonConfigs() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Restore Spoolman URL
 | 
					    // Restore Spoolman URL
 | 
				
			||||||
    if (spoolmanUrlBackup.length() > 0) {
 | 
					    if (spoolmanUrlBackup.length() > 0) {
 | 
				
			||||||
        File file = SPIFFS.open("/spoolman_url.json", "w");
 | 
					        File file = LittleFS.open("/spoolman_url.json", "w");
 | 
				
			||||||
        if (file) {
 | 
					        if (file) {
 | 
				
			||||||
            file.print(spoolmanUrlBackup);
 | 
					            file.print(spoolmanUrlBackup);
 | 
				
			||||||
            file.close();
 | 
					            file.close();
 | 
				
			||||||
@@ -111,6 +139,16 @@ void handleUpdate(AsyncWebServer &server) {
 | 
				
			|||||||
    updateHandler->setUri("/update");
 | 
					    updateHandler->setUri("/update");
 | 
				
			||||||
    updateHandler->setMethod(HTTP_POST);
 | 
					    updateHandler->setMethod(HTTP_POST);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // Check if current version is less than defined TOOLVERSION before proceeding with update
 | 
				
			||||||
 | 
					    if (isVersionLessThan(VERSION, TOOLDVERSION)) {
 | 
				
			||||||
 | 
					        updateHandler->onRequest([](AsyncWebServerRequest *request) {
 | 
				
			||||||
 | 
					            request->send(400, "application/json", 
 | 
				
			||||||
 | 
					                "{\"success\":false,\"message\":\"Your current version is too old. Please perform a full upgrade.\"}");
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        server.addHandler(updateHandler);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updateHandler->onUpload([](AsyncWebServerRequest *request, String filename,
 | 
					    updateHandler->onUpload([](AsyncWebServerRequest *request, String filename,
 | 
				
			||||||
                             size_t index, uint8_t *data, size_t len, bool final) {
 | 
					                             size_t index, uint8_t *data, size_t len, bool final) {
 | 
				
			||||||
        if (!index) {
 | 
					        if (!index) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ void scale_loop(void * parameter) {
 | 
				
			|||||||
      weight = round(scale.get_units());
 | 
					      weight = round(scale.get_units());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    vTaskDelay(pdMS_TO_TICKS(100)); // Verzögerung, um die CPU nicht zu überlasten
 | 
					    vTaskDelay(pdMS_TO_TICKS(100));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,7 +90,7 @@ uint8_t start_scale() {
 | 
				
			|||||||
  BaseType_t result = xTaskCreatePinnedToCore(
 | 
					  BaseType_t result = xTaskCreatePinnedToCore(
 | 
				
			||||||
    scale_loop, /* Function to implement the task */
 | 
					    scale_loop, /* Function to implement the task */
 | 
				
			||||||
    "ScaleLoop", /* Name of the task */
 | 
					    "ScaleLoop", /* Name of the task */
 | 
				
			||||||
    10000,  /* Stack size in words */
 | 
					    2048,  /* Stack size in words */
 | 
				
			||||||
    NULL,  /* Task input parameter */
 | 
					    NULL,  /* Task input parameter */
 | 
				
			||||||
    scaleTaskPrio,  /* Priority of the task */
 | 
					    scaleTaskPrio,  /* Priority of the task */
 | 
				
			||||||
    &ScaleTask,  /* Task handle. */
 | 
					    &ScaleTask,  /* Task handle. */
 | 
				
			||||||
@@ -110,6 +110,7 @@ uint8_t calibrate_scale() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  //vTaskSuspend(RfidReaderTask);
 | 
					  //vTaskSuspend(RfidReaderTask);
 | 
				
			||||||
  vTaskDelete(RfidReaderTask);
 | 
					  vTaskDelete(RfidReaderTask);
 | 
				
			||||||
 | 
					  vTaskDelete(ScaleTask);
 | 
				
			||||||
  pauseBambuMqttTask = true;
 | 
					  pauseBambuMqttTask = true;
 | 
				
			||||||
  pauseMainTask = 1;
 | 
					  pauseMainTask = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,8 +178,6 @@ uint8_t calibrate_scale() {
 | 
				
			|||||||
        vTaskDelay(pdMS_TO_TICKS(1));
 | 
					        vTaskDelay(pdMS_TO_TICKS(1));
 | 
				
			||||||
        esp_task_wdt_reset();
 | 
					        esp_task_wdt_reset();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
      //ESP.restart();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -212,8 +211,7 @@ uint8_t calibrate_scale() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  oledShowMessage("Scale Ready");
 | 
					  oledShowMessage("Scale Ready");
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  
 | 
					  Serial.println("restart Scale Task");
 | 
				
			||||||
  Serial.println("starte Scale Task");
 | 
					 | 
				
			||||||
  start_scale();
 | 
					  start_scale();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pauseBambuMqttTask = false;
 | 
					  pauseBambuMqttTask = false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -113,12 +113,12 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
 | 
				
			|||||||
// Funktion zum Laden und Ersetzen des Headers in einer HTML-Datei
 | 
					// Funktion zum Laden und Ersetzen des Headers in einer HTML-Datei
 | 
				
			||||||
String loadHtmlWithHeader(const char* filename) {
 | 
					String loadHtmlWithHeader(const char* filename) {
 | 
				
			||||||
    Serial.println("Lade HTML-Datei: " + String(filename));
 | 
					    Serial.println("Lade HTML-Datei: " + String(filename));
 | 
				
			||||||
    if (!SPIFFS.exists(filename)) {
 | 
					    if (!LittleFS.exists(filename)) {
 | 
				
			||||||
        Serial.println("Fehler: Datei nicht gefunden!");
 | 
					        Serial.println("Fehler: Datei nicht gefunden!");
 | 
				
			||||||
        return "Fehler: Datei nicht gefunden!";
 | 
					        return "Fehler: Datei nicht gefunden!";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    File file = SPIFFS.open(filename, "r");
 | 
					    File file = LittleFS.open(filename, "r");
 | 
				
			||||||
    String html = file.readString();
 | 
					    String html = file.readString();
 | 
				
			||||||
    file.close();
 | 
					    file.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -195,7 +195,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für about
 | 
					    // Route für about
 | 
				
			||||||
    server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /about erhalten");
 | 
					        Serial.println("Anfrage für /about erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.html.gz", "text/html");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/index.html.gz", "text/html");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -204,7 +204,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für Waage
 | 
					    // Route für Waage
 | 
				
			||||||
    server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /waage erhalten");
 | 
					        Serial.println("Anfrage für /waage erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/waage.html.gz", "text/html");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -213,7 +213,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für RFID
 | 
					    // Route für RFID
 | 
				
			||||||
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /rfid erhalten");
 | 
					        Serial.println("Anfrage für /rfid erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/rfid.html.gz", "text/html");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -229,7 +229,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für WiFi
 | 
					    // Route für WiFi
 | 
				
			||||||
    server.on("/wifi", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/wifi", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /wifi erhalten");
 | 
					        Serial.println("Anfrage für /wifi erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/wifi.html.gz", "text/html");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/wifi.html.gz", "text/html");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -239,7 +239,10 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    server.on("/spoolman", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/spoolman", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /spoolman erhalten");
 | 
					        Serial.println("Anfrage für /spoolman erhalten");
 | 
				
			||||||
        String html = loadHtmlWithHeader("/spoolman.html");
 | 
					        String html = loadHtmlWithHeader("/spoolman.html");
 | 
				
			||||||
        html.replace("{{spoolmanUrl}}", spoolmanUrl);
 | 
					        html.replace("{{spoolmanUrl}}", (spoolmanUrl != "") ? spoolmanUrl : "");
 | 
				
			||||||
 | 
					        html.replace("{{spoolmanOctoEnabled}}", octoEnabled ? "checked" : "");
 | 
				
			||||||
 | 
					        html.replace("{{spoolmanOctoUrl}}", (octoUrl != "") ? octoUrl : "");
 | 
				
			||||||
 | 
					        html.replace("{{spoolmanOctoToken}}", (octoToken != "") ? octoToken : "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        JsonDocument doc;
 | 
					        JsonDocument doc;
 | 
				
			||||||
        if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is<String>()) 
 | 
					        if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is<String>()) 
 | 
				
			||||||
@@ -277,10 +280,21 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String url = request->getParam("url")->value();
 | 
					        if (request->getParam("octoEnabled")->value() == "true" && (!request->hasParam("octoUrl") || !request->hasParam("octoToken"))) {
 | 
				
			||||||
        url.trim();
 | 
					            request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing OctoPrint URL or Token parameter\"}");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool healthy = saveSpoolmanUrl(url);
 | 
					        String url = request->getParam("url")->value();
 | 
				
			||||||
 | 
					        bool octoEnabled = (request->getParam("octoEnabled")->value() == "true") ? true : false;
 | 
				
			||||||
 | 
					        String octoUrl = request->getParam("octoUrl")->value();
 | 
				
			||||||
 | 
					        String octoToken = (request->getParam("octoToken")->value() != "") ? request->getParam("octoToken")->value() : "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        url.trim();
 | 
				
			||||||
 | 
					        octoUrl.trim();
 | 
				
			||||||
 | 
					        octoToken.trim();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        bool healthy = saveSpoolmanUrl(url, octoEnabled, octoUrl, octoToken);
 | 
				
			||||||
        String jsonResponse = "{\"healthy\": " + String(healthy ? "true" : "false") + "}";
 | 
					        String jsonResponse = "{\"healthy\": " + String(healthy ? "true" : "false") + "}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        request->send(200, "application/json", jsonResponse);
 | 
					        request->send(200, "application/json", jsonResponse);
 | 
				
			||||||
@@ -322,7 +336,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für das Laden der CSS-Datei
 | 
					    // Route für das Laden der CSS-Datei
 | 
				
			||||||
    server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Lade style.css");
 | 
					        Serial.println("Lade style.css");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/style.css.gz", "text/css");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/style.css.gz", "text/css");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -331,7 +345,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Route für das Logo
 | 
					    // Route für das Logo
 | 
				
			||||||
    server.on("/logo.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/logo.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/logo.png.gz", "image/png");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/logo.png.gz", "image/png");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -340,7 +354,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Route für Favicon
 | 
					    // Route für Favicon
 | 
				
			||||||
    server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/favicon.ico", "image/x-icon");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/favicon.ico", "image/x-icon");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
        Serial.println("favicon.ico gesendet");
 | 
					        Serial.println("favicon.ico gesendet");
 | 
				
			||||||
@@ -348,7 +362,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Route für spool_in.png
 | 
					    // Route für spool_in.png
 | 
				
			||||||
    server.on("/spool_in.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/spool_in.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/spool_in.png.gz", "image/png");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/spool_in.png.gz", "image/png");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -357,7 +371,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Route für set_spoolman.png
 | 
					    // Route für set_spoolman.png
 | 
				
			||||||
    server.on("/set_spoolman.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/set_spoolman.png", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/set_spoolman.png.gz", "image/png");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/set_spoolman.png.gz", "image/png");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -367,7 +381,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
    // Route für JavaScript Dateien
 | 
					    // Route für JavaScript Dateien
 | 
				
			||||||
    server.on("/spoolman.js", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/spoolman.js", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /spoolman.js erhalten");
 | 
					        Serial.println("Anfrage für /spoolman.js erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/spoolman.js.gz", "text/javascript");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/spoolman.js.gz", "text/javascript");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -376,7 +390,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    server.on("/rfid.js", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
					    server.on("/rfid.js", HTTP_GET, [](AsyncWebServerRequest *request){
 | 
				
			||||||
        Serial.println("Anfrage für /rfid.js erhalten");
 | 
					        Serial.println("Anfrage für /rfid.js erhalten");
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS,"/rfid.js.gz", "text/javascript");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS,"/rfid.js.gz", "text/javascript");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
					        response->addHeader("Cache-Control", CACHE_CONTROL);
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
@@ -385,7 +399,7 @@ void setupWebserver(AsyncWebServer &server) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Vereinfachter Update-Handler
 | 
					    // Vereinfachter Update-Handler
 | 
				
			||||||
    server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest *request) {
 | 
					    server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest *request) {
 | 
				
			||||||
        AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/upgrade.html.gz", "text/html");
 | 
					        AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/upgrade.html.gz", "text/html");
 | 
				
			||||||
        response->addHeader("Content-Encoding", "gzip");
 | 
					        response->addHeader("Content-Encoding", "gzip");
 | 
				
			||||||
        response->addHeader("Cache-Control", "no-store");
 | 
					        response->addHeader("Cache-Control", "no-store");
 | 
				
			||||||
        request->send(response);
 | 
					        request->send(response);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user