diff --git a/.gitignore b/.gitignore index b9774e9..7709e53 100644 --- a/.gitignore +++ b/.gitignore @@ -32,10 +32,12 @@ test/README data/* !data/ !data/.gitkeep +# important html/bambu_credentials.json html/spoolman_url.json _local/* website/* release.sh .github/copilot-instructions.md -data \ No newline at end of file +data +wiki \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 59dcbc0..2bc2f3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,1793 @@ # Changelog +## [2.0.7] - 2025-09-13 +### Added +- add HTTP service to mDNS responder +- add additional information about Recycling Fabrik in README files +- add Recycling Fabrik section with logo and information +- add RF logo image +- add support information for Recycling Fabrik + +### Changed +- remove unnecessary separator in Recycling Fabrik section + +### Fixed +- update Recycling Fabrik logo display format in README +- prevent weight display during NFC write operations + + +## [2.0.6-beta1] - 2025-09-03 +### Fixed +- prevent weight display during NFC write operations + + +## [2.0.6] - 2025-09-03 +### Fixed +- correct progress bar message and update tare function description + + +## [2.0.5] - 2025-09-03 +### Changed +- adjust auto tare counter threshold and reposition tare check in scale loop +- improve auto tare logic and reset conditions in scale handling + +### Fixed +- update progress bar message from 'Tare scale' to 'Searching scale' +- Scale tare function after boot + + +## [2.0.4-beta2] - 2025-09-03 +### Changed +- adjust auto tare counter threshold and reposition tare check in scale loop +- improve auto tare logic and reset conditions in scale handling + + +## [2.0.4-beta1] - 2025-09-03 +### Changed +- improve auto tare logic and reset conditions in scale handling + + +## [2.0.4] - 2025-09-02 +### Changed +- filter out automatic release documentation commits in changelog categorization +- disable auto tare and weight filter reset in scale loop + + +## [2.0.3] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for version v2.0.3 +- update changelog and header for version v2.0.2-beta6 +- update platformio.ini for beta version v2.0.2-beta6 +- update changelog and header for version v2.0.2-beta5 +- update platformio.ini for beta version v2.0.2-beta5 +- update changelog and header for version v2.0.2-beta4 +- update platformio.ini for beta version v2.0.2-beta4 +- update changelog and header for version v2.0.2-beta3 +- update platformio.ini for beta version v2.0.2-beta3 +- update changelog and header for version v2.0.2-beta2 +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- set scale tare request to true in setup function +- correct assignment operator in scale tare request handling +- correct tare scale request handling in tareScale function +- reset weight filter after tare scale operation +- correct tare scale function to set scaleTareRequest flag +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta6] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for beta version v2.0.2-beta6 +- update changelog and header for version v2.0.2-beta5 +- update platformio.ini for beta version v2.0.2-beta5 +- update changelog and header for version v2.0.2-beta4 +- update platformio.ini for beta version v2.0.2-beta4 +- update changelog and header for version v2.0.2-beta3 +- update platformio.ini for beta version v2.0.2-beta3 +- update changelog and header for version v2.0.2-beta2 +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- set scale tare request to true in setup function +- correct assignment operator in scale tare request handling +- correct tare scale request handling in tareScale function +- reset weight filter after tare scale operation +- correct tare scale function to set scaleTareRequest flag +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta5] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for beta version v2.0.2-beta5 +- update changelog and header for version v2.0.2-beta4 +- update platformio.ini for beta version v2.0.2-beta4 +- update changelog and header for version v2.0.2-beta3 +- update platformio.ini for beta version v2.0.2-beta3 +- update changelog and header for version v2.0.2-beta2 +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- correct tare scale request handling in tareScale function +- reset weight filter after tare scale operation +- correct tare scale function to set scaleTareRequest flag +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta4] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for beta version v2.0.2-beta4 +- update changelog and header for version v2.0.2-beta3 +- update platformio.ini for beta version v2.0.2-beta3 +- update changelog and header for version v2.0.2-beta2 +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- reset weight filter after tare scale operation +- correct tare scale function to set scaleTareRequest flag +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta3] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for beta version v2.0.2-beta3 +- update changelog and header for version v2.0.2-beta2 +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- correct tare scale function to set scaleTareRequest flag +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta2] - 2025-09-02 +### Added +- add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t + +### Changed +- update platformio.ini for beta version v2.0.2-beta2 +- update changelog and header for version v2.0.2-beta1 +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2-beta1] - 2025-09-02 +### Changed +- update platformio.ini for beta version v2.0.2-beta1 + +### Fixed +- reset weight counter logic and update spool ID in loop function +- reduce delay in start_scale function and reset weight after tare + + +## [2.0.2] - 2025-09-01 +### Added +- add weight check and update spool weight in writeJsonToTag function +- add German and English wiki documentation + +### Changed +- update platformio.ini for version v2.0.2 +- remove redundant tare calls in setup and start_scale functions + + +## [2.0.1] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- implement retry mechanism and timeout handling for API requests +- add timeout handling and error states for vendor and filament operations +- enhance weight processing with filtered display and API stability checks +- implement weight stabilization functions and improve tare handling +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for version v2.0.1 +- update changelog and header for version v2.0.0-beta14 +- update platformio.ini for beta version v2.0.0-beta14 +- update changelog and header for version v2.0.0-beta13 +- update platformio.ini for beta version v2.0.0-beta13 +- optimize weight stabilization parameters for improved responsiveness +- update changelog and header for version v2.0.0-beta12 +- update platformio.ini for beta version v2.0.0-beta12 +- update changelog and header for version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta11 +- update platformio.ini for beta version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta10 +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta14] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- implement retry mechanism and timeout handling for API requests +- add timeout handling and error states for vendor and filament operations +- enhance weight processing with filtered display and API stability checks +- implement weight stabilization functions and improve tare handling +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta14 +- update changelog and header for version v2.0.0-beta13 +- update platformio.ini for beta version v2.0.0-beta13 +- optimize weight stabilization parameters for improved responsiveness +- update changelog and header for version v2.0.0-beta12 +- update platformio.ini for beta version v2.0.0-beta12 +- update changelog and header for version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta11 +- update platformio.ini for beta version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta10 +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta13] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- enhance weight processing with filtered display and API stability checks +- implement weight stabilization functions and improve tare handling +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta13 +- optimize weight stabilization parameters for improved responsiveness +- update changelog and header for version v2.0.0-beta12 +- update platformio.ini for beta version v2.0.0-beta12 +- update changelog and header for version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta11 +- update platformio.ini for beta version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta10 +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta12] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- enhance weight processing with filtered display and API stability checks +- implement weight stabilization functions and improve tare handling +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta12 +- update changelog and header for version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta11 +- update platformio.ini for beta version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta10 +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta11] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- implement weight stabilization functions and improve tare handling +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update changelog and header for version v2.0.0-beta11 +- update platformio.ini for beta version v2.0.0-beta11 +- update changelog and header for version v2.0.0-beta10 +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + +## [2.0.0-beta10] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- add fast-path JSON reading for web interface display +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta10 +- update changelog and header for version v2.0.0-beta9 +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta9] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta9 +- update changelog and header for version v2.0.0-beta8 +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta8] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- implement robust page reading with error recovery for NFC tags +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta8 +- update changelog and header for version v2.0.0-beta7 +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta7] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v2.0.0-beta7 +- update changelog and header for version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + + +## [2.0.0-beta6] - 2025-08-30 +### Breaking Changes +- enhance commit categorization for breaking changes +- Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag + +### Added +- implement robust page reading and safe tag detection with error recovery +- add Manufacturer Tags support documentation in German and English +- add display delay for vendor, filament, and spool creation processes +- add progress bar updates for vendor and filament creation processes +- update vendor and filament ID handling to use NULL and add delays for stability +- add delay to ensure proper setting of vendor and filament IDs after API state changes +- enhance NDEF decoding with detailed validation and debugging output +- enhance NDEF decoding to validate structure and extract JSON payload +- add logging for decoded JSON data in NFC processing +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update changelog and header for version v2.0.0-beta6 +- update platformio.ini for beta version v2.0.0-beta6 +- update changelog and header for version v2.0.0-beta5 +- update platformio.ini for beta version v2.0.0-beta5 +- update changelog and header for version v2.0.0-beta4 +- update platformio.ini for beta version v2.0.0-beta4 +- update changelog and header for version v2.0.0-beta3 +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload +- update changelog and header for version v2.0.0-beta2 +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation +- update changelog and header for version v2.0.0-beta1 +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini +- update changelog and header for version v1.5.12-beta18 +- update platformio.ini for beta version v1.5.12-beta18 +- update changelog and header for version v1.5.12-beta17 +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code +- update changelog and header for version v1.5.12-beta16 +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics +- update changelog and header for version v1.5.12-beta15 +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write +- update changelog and header for version v1.5.12-beta14 +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process +- update changelog and header for version v1.5.12-beta13 +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety +- update changelog and header for version v1.5.12-beta12 +- update platformio.ini for beta version v1.5.12-beta12 +- update changelog and header for version v1.5.12-beta11 +- update platformio.ini for beta version v1.5.12-beta11 +- update changelog and header for version v1.5.12-beta10 +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions +- update changelog and header for version v1.5.12-beta9 +- update platformio.ini for beta version v1.5.12-beta9 +- update changelog and header for version v1.5.12-beta8 +- update platformio.ini for beta version v1.5.12-beta8 +- update changelog and header for version v1.5.12-beta7 +- update platformio.ini for beta version v1.5.12-beta7 +- update changelog and header for version v1.5.12-beta6 +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions +- update changelog and header for version v1.5.12-beta5 +- update platformio.ini for beta version v1.5.12-beta5 +- update changelog and header for version v1.5.12-beta4 +- update platformio.ini for beta version v1.5.12-beta4 +- update changelog and header for version v1.5.12-beta3 +- update platformio.ini for beta version v1.5.12-beta3 +- update changelog and header for version v1.5.12-beta2 +- update platformio.ini for beta version v1.5.12-beta2 +- update changelog and header for version v1.5.12-beta1 +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + +### Fixed +- call scale.tare() in setup after starting scale +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version +- increase delay in start_scale function for improved stability +- replace progress bar with message display for remaining weight in sendToApi function +- update vendor check to use shorthand key in payload +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling +- update spoolman ID reset values to 65535 for better API response detection +- correct color_hex key usage and comment out unused date fields in spool creation +- improve API state handling and vendor name formatting +- enhance filament creation logic to include dynamic comments based on payload + +## [2.0.0-beta5] - 2025-08-30 +### Changed +- update platformio.ini for beta version v2.0.0-beta5 + +### Fixed +- call scale.tare() in setup after starting scale + + +## [2.0.0-beta4] - 2025-08-29 +### Changed +- update platformio.ini for beta version v2.0.0-beta4 + +### Fixed +- update createVendor function to use external_id as comment instead of static text +- update to_old_version in platformio.ini to reflect correct previous version + + +## [2.0.0-beta3] - 2025-08-29 +### Changed +- update platformio.ini for beta version v2.0.0-beta3 +- update createVendor and checkVendor functions to accept JsonDocument payload + + +## [2.0.0-beta2] - 2025-08-29 +### Added +- add Manufacturer Tags support documentation in German and English + +### Changed +- update platformio.ini for beta version v2.0.0-beta2 +- clarify product URL description for Manufacturer Tags in German and English documentation + +### Fixed +- increase delay in start_scale function for improved stability + + +## [2.0.0-beta1] - 2025-08-29 +### Changed +- update platformio.ini for beta version v2.0.0-beta1 +- update version to 2.0.0 in platformio.ini + + +## [1.5.12-beta18] - 2025-08-29 +### Added +- add display delay for vendor, filament, and spool creation processes + +### Changed +- update platformio.ini for beta version v1.5.12-beta18 + +### Fixed +- replace progress bar with message display for remaining weight in sendToApi function + + +## [1.5.12-beta17] - 2025-08-29 +### Added +- add progress bar updates for vendor and filament creation processes + +### Changed +- update platformio.ini for beta version v1.5.12-beta17 +- optimize page limit detection and remove redundant verification code + +### Fixed +- update vendor check to use shorthand key in payload + + +## [1.5.12-beta16] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta16 +- Refactor NFC interface handling and improve error diagnostics + + +## [1.5.12-beta15] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta15 +- enhance NFC write operation diagnostics and improve error handling +- enhance NFC write operation handling and prevent tag operations during write + + +## [1.5.12-beta14] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta14 +- optimize JSON payload structure and enhance NFC tag validation process + + +## [1.5.12-beta13] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta13 +- reorganize clearUserDataArea function for improved clarity and safety + + +## [1.5.12-beta12] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta12 + +### Fixed +- reset NFC state on API send failure to allow retry +- update createdFilamentId reset value to 65535 for better task handling +- update createdVendorId reset value to 65535 for improved API handling + + +## [1.5.12-beta11] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta11 + +### Fixed +- update spoolman ID reset values to 65535 for better API response detection + + +## [1.5.12-beta10] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta10 +- streamline task creation in checkVendor and checkFilament functions + + +## [1.5.12-beta9] - 2025-08-29 +### Added +- update vendor and filament ID handling to use NULL and add delays for stability + +### Changed +- update platformio.ini for beta version v1.5.12-beta9 + + +## [1.5.12-beta8] - 2025-08-29 +### Added +- add delay to ensure proper setting of vendor and filament IDs after API state changes + +### Changed +- update platformio.ini for beta version v1.5.12-beta8 + +### Fixed +- correct color_hex key usage and comment out unused date fields in spool creation + + +## [1.5.12-beta7] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta7 + +### Fixed +- improve API state handling and vendor name formatting + + +## [1.5.12-beta6] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta6 +- improve task synchronization in vendor, filament, and spool creation functions + + +## [1.5.12-beta5] - 2025-08-29 +### Added +- enhance NDEF decoding with detailed validation and debugging output + +### Changed +- update platformio.ini for beta version v1.5.12-beta5 + + +## [1.5.12-beta4] - 2025-08-29 +### Added +- enhance NDEF decoding to validate structure and extract JSON payload + +### Changed +- update platformio.ini for beta version v1.5.12-beta4 + + +## [1.5.12-beta3] - 2025-08-29 +### Added +- add logging for decoded JSON data in NFC processing + +### Changed +- update platformio.ini for beta version v1.5.12-beta3 + + +## [1.5.12-beta2] - 2025-08-29 +### Changed +- update platformio.ini for beta version v1.5.12-beta2 + +### Fixed +- enhance filament creation logic to include dynamic comments based on payload + + +## [1.5.12-beta1] - 2025-08-28 +### Added +- implement filament and spool creation in Spoolman API +- Add JSON structure comments for filament and spool creation +- Add vendor and filament management to API; implement recycling factory handling in NFC + +### Changed +- update platformio.ini for beta version v1.5.12-beta1 +- Merge branch 'main' into recyclingfabrik +- Merge branch 'main' into recyclingfabrik + + +## [1.5.12] - 2025-08-28 +### Added +- add numbering to update sections in upgrade.html refactor: improve readability of checkSpoolmanInstance function + +### Changed +- update platformio.ini for version v1.5.12 +- clean up library dependencies in platformio.ini + + +## [1.5.11-beta4] - 2025-08-28 +### Changed +- update platformio.ini for beta version v1.5.11-beta4 + +### Fixed +- remove debug logging from checkSpoolmanInstance function + + +## [1.5.11-beta3] - 2025-08-28 +### Added +- add logging for spoolman status in checkSpoolmanInstance function + +### Changed +- update platformio.ini for beta version v1.5.11-beta3 + + +## [1.5.11-beta2] - 2025-08-28 +### Added +- add logging for healthy spoolman instance check + +### Changed +- update platformio.ini for beta version v1.5.11-beta2 + + +## [1.5.11-beta1] - 2025-08-28 +### Changed +- update platformio.ini for beta version v1.5.11-beta1 + +### Fixed +- adjust spacing in loop structure and enable tare function in scale loop + + +## [1.5.11] - 2025-08-27 +### Changed +- update platformio.ini for version v1.5.11 + + +## [1.5.10] - 2025-08-27 +### Added +- improve weight processing logic and add auto-send feature for Bambu spool ID +- improve weight processing logic and add auto-send feature for Bambu spool ID +- Adds a link to the spool in spoolman when reading a spool tag +- Fixes types and some issues in the new graphics +- Adds ENABLE_HEAP_DEBUGGING define as comment to the build flags +- Adds data directory and further .vscode files to to .gitignore +- Introduces new heap debugging feature and fixes some memory leaks in website feature +- Fixes some issues with the new location tags +- Adds new feature to write and read location tags +- Adds slight debouncing to the scale loop weight logic +- add loadcell desc. +- implement multi-color filament display and styles for dropdown options +- add remaining weight logging for PUT requests and improve error reporting in sendToApi function +- add remaining weight logging and display after successful spool update +- add weight field to update payload in updateSpoolTagId function +- add auto-tare functionality and update scale handling based on touch sensor connection +- add touch sensor connection check and update logic +- add manual tare functionality for scale +- add debounce handling for TTP223 touch sensor +- add TTP223 touch sensor support and wiring configuration +- Renamed states of NFC state machine and introduced new state machine for spoolman API +- add forced cache refresh after removing and saving Bambu credentials +- add functionality to remove Bambu credentials and update API handling +- add rfid_bambu.html and update bambu connection handling +- add error handling for missing vendor IDs in filament data +- add WiFi connection check and restart Bambu if not connected +- added new .step, now with correct individual parts +- added changelog +- Add files via upload +- added .stp files of modifications +- added merged picture +- added pictures of components bought from AliE +- Add files via upload +- added pictures for heat insert location +- added pictures showing heat insert location +- remove unnecessary delay in MQTT setup and add delay before restart +- add new 3D print file for Filaman scale +- added Discord Server +- 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 platformio.ini for version v1.5.10 +- Merge branch 'main' of https://gitlab.fire-devils.org/3D-Druck/Filaman +- Changed Amazon Link for PN532 +- Changed Amazon Link for PN532 +- update changelog and header for version v1.5.9 +- update platformio.ini for version v1.5.9 +- Enhance API to support weight updates after successful spool tag updates +- update changelog and header for version v1.5.8 +- update platformio.ini for version v1.5.8 +- Merge pull request #45 from janecker/nfc_write_improvements +- Introduces periodic Spoolman Healthcheck +- Improves init - NFC reading now only starts after boot is finished +- Further improvements on NFC writing +- Merge pull request #44 from janecker/graphics_rework +- Graphic rework of the NFC writing process +- Remove unused parameter of sendNfcData() +- Reworks startup graphics and timings +- update changelog and header for version v1.5.7 +- update platformio.ini for version v1.5.7 +- clean up unused variables and improve .gitignore entries +- update changelog and header for version v1.5.6 +- update webpages for version v1.5.6 +- update platformio.ini for version v1.5.6 +- Merge pull request #42 from janecker/configuration_nvs_storage +- Merge branch 'main' into configuration_nvs_storage +- Changes configuration storage of spoolman and bambu values +- update changelog and header for version v1.5.5 +- update platformio.ini for version v1.5.5 +- update changelog and header for version v1.5.4 +- update platformio.ini for version v1.5.4 +- Merge branch 'main' of github.com:ManuelW77/Filaman +- Merge pull request #39 from janecker/location_tags +- Merge pull request #38 from janecker/scale_debouncing +- update changelog and header for version v1.5.3 +- update platformio.ini for version v1.5.3 +- Affiliate Links +- update changelog and header for version v1.5.2 +- update platformio.ini for version v1.5.2 +- update changelog and header for version v1.5.1 +- update version to 1.5.1 and improve OTA update handling with task management +- update changelog and header for version v1.4.14 +- update platformio.ini for version v1.4.14 +- update changelog and header for version v1.4.13 +- update platformio.ini for version v1.4.13 +- update changelog and header for version v1.4.12 +- update platformio.ini for version v1.4.12 +- update README files to clarify PN532 DIP switch settings +- update changelog and header for version v1.4.11 +- update platformio.ini for version v1.4.11 +- Merge branch 'main' of github.com:ManuelW77/Filaman +- update changelog and header for version v1.4.10 +- update platformio.ini for version v1.4.10 +- Merge pull request #31 from janecker/nfc_rework +- Introducing enum for handling the NFC state to improve code readability +- update changelog and header for version v1.4.9 +- update platformio.ini for version v1.4.9 +- update changelog and header for version v1.4.8 +- update platformio.ini for version v1.4.8 +- Merge pull request #30 from janecker/main +- Merge branch 'testing' into main +- update changelog and header for version v1.4.7 +- update platformio.ini for version v1.4.7 +- Merge branch 'testing' +- update remove button for Bambu credentials with red background +- Merge pull request #28 from tugsi/main +- update changelog and header for version v1.4.6 +- update platformio.ini for version v1.4.6 +- update changelog and header for version v1.4.5 +- update platformio.ini for version v1.4.5 +- Merge branch 'testing' +- remove unused request_topic subscription and reduce MQTT task stack size +- Merge pull request #26 from tugsi/main +- rename report_topic to topic and update MQTT subscription logic, switched publish topic to request +- update changelog and header for version v1.4.4 +- update platformio.ini for version v1.4.4 +- update changelog and header for version v1.4.3 +- update platformio.ini for version v1.4.3 +- update changelog and header for version v1.4.2 +- update platformio.ini for version v1.4.2 +- increase stack size for BambuMqtt task +- update Discord Link +- update Discord Link +- remove commented-out subscription topic in MQTT setup +- update changelog and header for version v1.4.1 +- update platformio.ini for version v1.4.1 +- refactor length calculation to convert total length to meters before formatting +- Merge pull request #16 from spitzbirne32/main +- improved housing to show display better +- removed CAD, as they were all duplicates +- typo in AliE link +- Delete usermod/spitzbirne32/STL/README.md +- Update README.md +- moved pictures of parts into dedicated folders +- Update README.md +- Update README.md +- Update README.md +- Delete usermod/spitzbirne32/STL/ScaleTop_Heatinsert_Location_usermod_spitzbirne32_.png +- Delete usermod/spitzbirne32/STL/Housing_Heatinsert_Location_usermod_spitzbirne32_.png +- created folders +- Update README.md +- Update README.md +- Create README.md +- Update README.md +- Update README.md +- Create README.md +- Merge pull request #15 from ManuelW77/main +- Merge pull request #14 from janecker/scale-calibration-rework +- Reworks the scale calibration handling +- remove redundant scale calibration checks and enhance task management +- enhance AMS data handling and streamline spool auto-setting logic +- adjust stack size and improve scale calibration logic +- update labels and input types for better clarity and functionality +- update documentation for clarity and accuracy +- update changelog and header for version v1.4.0 +- 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 + +### Fixed +- Fixes issue that scale not calibrated message was not shown +- Improves NFC writing workaround and removes debug output +- Fixes typos in upgrade page +- Reworks graphics of tag reading and some api fixes +- Replaces usage of String with const char* in heap debug function +- Merge pull request #41 from janecker/memory_leak_fixes +- Fixes compiler warnings in nfc +- Memory leak fixes in api and nfc, location tag fix +- Merge pull request #40 from janecker/location_bambu_fix +- uncomment monitor_port configuration in platformio.ini +- update spool weight conditionally based on NFC ID +- update weight field in update payload to only include values greater than 10 +- increase stack size for sendToApi task to improve stability +- adjust tare weight tolerance to ignore deviations of 2g +- improve weight stability check before sending to API +- update touch sensor connection logic to correctly identify connection status +- update TTP223 pin configuration and adjust touch sensor logic +- enhance HTTP method handling in sendToApi function +- improve HTTP client configuration and clear update documents after API calls +- Fixes memory leak in HTTPClient by disabling connection reuse +- update reload logic after removing and saving Bambu credentials for better cache handling +- handle Bambu connection state by introducing bambuDisabled flag +- handle potential undefined value for tray_info_idx in handleSpoolIn function, by @tugsi +- Fix rfid.js-Failure with X1-Series, if you wanna send a Spool to AMS: - Uncaught TypeError: Cannot read properties of undefined (reading 'replace') at handleSpoolIn (rfid.js:493:67) at HTMLButtonElement.onclick ((Index):1:1) handleSpoolIn @ rfid.js:493 onclick @ (Index):1 +- increase MQTT buffer size and adjust task stack size +- Fix BufferSize for larger JSONs from X-Series +- adjust weight threshold for tare check to allow negative values +- use unique client ID for MQTT connection to avoid conflicts +- reload page after firmware update completion +- increase WiFi connection timeout from 5 to 10 seconds +- ensure valid URL format and remove trailing slash in setupWebserver +- correct typo in console log for total length + + +## [1.5.9] - 2025-08-11 +### Changed +- update platformio.ini for version v1.5.9 +- Enhance API to support weight updates after successful spool tag updates + + +## [1.5.8] - 2025-08-10 +### Added +- Adds a link to the spool in spoolman when reading a spool tag +- Fixes types and some issues in the new graphics + +### Changed +- update platformio.ini for version v1.5.8 +- Merge pull request #45 from janecker/nfc_write_improvements +- Introduces periodic Spoolman Healthcheck +- Improves init - NFC reading now only starts after boot is finished +- Further improvements on NFC writing +- Merge pull request #44 from janecker/graphics_rework +- Graphic rework of the NFC writing process +- Remove unused parameter of sendNfcData() +- Reworks startup graphics and timings + +### Fixed +- Fixes issue that scale not calibrated message was not shown +- Improves NFC writing workaround and removes debug output +- Fixes typos in upgrade page +- Reworks graphics of tag reading and some api fixes +- Replaces usage of String with const char* in heap debug function + + ## [1.5.7] - 2025-07-28 ### Changed - update platformio.ini for version v1.5.7 diff --git a/README.de.md b/README.de.md index ab970ab..e499e37 100644 --- a/README.de.md +++ b/README.de.md @@ -11,6 +11,26 @@ oder auf meiner Website: [FilaMan Website](https://www.filaman.app) Deutsches Erklärvideo: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU) Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) +## NEU: Recycling Fabrik + + + Recycling Fabrik + + +FilaMan wird von [Recycling Fabrik](https://www.recyclingfabrik.com) unterstützt. +Recycling Fabrik wird demnächst auf seinen Spulen einen FilaMan tauglichen NFC Tag anbieten. Das hat den Vorteil, +dass die Spulen direkt über FilaMan, ganz automatisch, erkannt und in Spoolman importiert werden können. + +**Was ist Recycling Fabrik?** + +Die Recycling Fabrik ist ein deutsches Unternehmen, das sich der Entwicklung und Herstellung von nachhaltigem 3D-Druck-Filament verschrieben hat. +Ihre Filamente bestehen zu 100 % aus recyceltem Material, welches sowohl vom Endkunden, als auch aus der Industrie stammt – für eine umweltbewusste und ressourcenschonende Zukunft. + +Mehr Informationen und Produkte findest du hier: [www.recyclingfabrik.com](https://www.recyclingfabrik.com) + +--- + + ### Es gibt jetzt auch ein Wiki, dort sind nochmal alle Funktionen beschrieben: [Wiki](https://github.com/ManuelW77/Filaman/wiki) ### ESP32 Hardware-Funktionen @@ -27,6 +47,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Filamentdaten auf NFC-Tags schreiben. - Verwendet das NFC-Tag-Format von [Openspool](https://github.com/spuder/OpenSpool) - Ermöglicht automatische Spulenerkennung im AMS + - **Hersteller Tag Unterstützung:** Automatische Erstellung von Spoolman-Einträgen aus Hersteller NFC-Tags ([Mehr erfahren](README_ManufacturerTags_DE.md)) - **Bambulab AMS-Integration:** - Anzeige der aktuellen AMS-Fachbelegung. - Zuordnung von Filamenten zu AMS-Slots. @@ -39,8 +60,35 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Unterstützt das Spoolman Octoprint Plugin ### Wenn Sie meine Arbeit unterstützen möchten, freue ich mich über einen Kaffee + Buy Me A Coffee +## Hersteller Tags Unterstützung + +🎉 **Aufregende Neuigkeiten!** FilaMan unterstützt jetzt **Hersteller Tags** - NFC-Tags, die direkt von Filament-Herstellern vorprogrammiert geliefert werden! + +### Erster Hersteller-Partner: RecyclingFabrik + +Wir freuen uns anzukündigen, dass [**RecyclingFabrik**](https://www.recyclingfabrik.de) der **erste Filament-Hersteller** sein wird, der FilaMan unterstützt, indem sie NFC-Tags im FilaMan-Format auf ihren Spulen anbieten! + +**Demnächst verfügbar:** RecyclingFabrik-Spulen werden NFC-Tags enthalten, die sich automatisch in Ihr FilaMan-System integrieren, manuelle Einrichtung überflüssig machen und perfekte Kompatibilität gewährleisten. + +### Wie Hersteller Tags funktionieren + +Wenn Sie zum ersten Mal einen Hersteller NFC-Tag scannen: +1. **Automatische Markenerkennung:** FilaMan erkennt den Hersteller und erstellt die Marke in Spoolman +2. **Filament-Typ Erstellung:** Alle Materialspezifikationen werden automatisch hinzugefügt +3. **Spulen-Registrierung:** Ihre spezifische Spule wird mit korrektem Gewicht und Spezifikationen registriert +4. **Zukünftige Schnellerkennung:** Nachfolgende Scans verwenden Fast-Path-Erkennung für sofortige Gewichtsmessung + +**Für detaillierte technische Informationen:** [Hersteller Tags Dokumentation](README_ManufacturerTags_DE.md) + +### Vorteile für Benutzer +- ✅ **Null manuelle Einrichtung** - Einfach scannen und wiegen +- ✅ **Perfekte Datengenauigkeit** - Hersteller-verifizierte Spezifikationen +- ✅ **Sofortige Integration** - Nahtlose Spoolman-Kompatibilität +- ✅ **Zukunftssicher** - Tags funktionieren mit jedem FilaMan-kompatiblen System + ## Detaillierte Funktionalität ### ESP32-Funktionalität @@ -62,7 +110,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. [Amazon Link](https://amzn.to/445aaa9) - **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. -[Amazon Link](https://amzn.to/4iO6CO4) +[Amazon Link](https://amzn.eu/d/gy9vaBX) - **NFC Tags NTAG213 NTAG215:** RFID Tag [Amazon Link](https://amzn.to/3E071xO) - **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch diff --git a/README.md b/README.md index a1238f1..cfef460 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,25 @@ or my website: [FilaMan Website](https://www.filaman.app) german explanatory video: [Youtube](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU) Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) +## NEW: Recycling Fabrik + + + Recycling Fabrik + + +FilaMan is supported by [Recycling Fabrik](https://www.recyclingfabrik.com). +Recycling Fabrik will soon offer a FilaMan-compatible NFC tag on their spools. This has the advantage +that the spools can be automatically recognized and imported into Spoolman directly via FilaMan. + +**What is Recycling Fabrik?** + +Recycling Fabrik is a German company dedicated to developing and manufacturing sustainable 3D printing filament. +Their filaments are made from 100% recycled material from both end customers and industry – for an environmentally conscious and resource-saving future. + +More information and products can be found here: [www.recyclingfabrik.com](https://www.recyclingfabrik.com) + +--- + ### Now more detailed informations about the usage: [Wiki](https://github.com/ManuelW77/Filaman/wiki) ### ESP32 Hardware Features @@ -31,6 +50,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Write filament data to NFC tags. - uses NFC-Tag Format of [Openspool](https://github.com/spuder/OpenSpool) - so you can use it with automatic Spool detection in AMS + - **Manufacturer Tag Support:** Automatic creation of Spoolman entries from manufacturer NFC tags ([Learn more](README_ManufacturerTags_EN.md)) - **Bambulab AMS Integration:** - Display current AMS tray contents. - Assign filaments to AMS slots. @@ -43,8 +63,35 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - Supports Spoolman Octoprint Plugin ### If you want to support my work, i would be happy to get a coffe + Buy Me A Coffee +## Manufacturer Tags Support + +🎉 **Exciting News!** FilaMan now supports **Manufacturer Tags** - NFC tags that come pre-programmed directly from filament manufacturers! + +### First Manufacturer Partner: RecyclingFabrik + +We're thrilled to announce that [**RecyclingFabrik**](https://www.recyclingfabrik.de) will be the **first filament manufacturer** to support FilaMan by offering NFC tags in the FilaMan format on their spools! + +**Coming Soon:** RecyclingFabrik spools will include NFC tags that automatically integrate with your FilaMan system, eliminating manual setup and ensuring perfect compatibility. + +### How Manufacturer Tags Work + +When you scan a manufacturer NFC tag for the first time: +1. **Automatic Brand Detection:** FilaMan recognizes the manufacturer and creates the brand in Spoolman +2. **Filament Type Creation:** All material specifications are automatically added +3. **Spool Registration:** Your specific spool is registered with proper weight and specifications +4. **Future Fast Recognition:** Subsequent scans use fast-path detection for instant weight measurement + +**For detailed technical information:** [Manufacturer Tags Documentation](README_ManufacturerTags_EN.md) + +### Benefits for Users +- ✅ **Zero Manual Setup** - Just scan and weigh +- ✅ **Perfect Data Accuracy** - Manufacturer-verified specifications +- ✅ **Instant Integration** - Seamless Spoolman compatibility +- ✅ **Future-Proof** - Tags work with any FilaMan-compatible system + ## Detailed Functionality ### ESP32 Functionality @@ -66,7 +113,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) - **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. [Amazon Link](https://amzn.to/445aaa9) - **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. -[Amazon Link](https://amzn.to/4iO6CO4) +[Amazon Link](https://amzn.eu/d/gy9vaBX) - **NFC Tags NTAG213 NTAG215:** RFID Tag [Amazon Link](https://amzn.to/3E071xO) - **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch diff --git a/README_ManufacturerTags_DE.md b/README_ManufacturerTags_DE.md new file mode 100644 index 0000000..bd46b35 --- /dev/null +++ b/README_ManufacturerTags_DE.md @@ -0,0 +1,159 @@ +# Hersteller Tags - Deutsche Dokumentation + +## Überblick + +Das FilaMan NFC-System unterstützt **Hersteller Tags**, die es Filament-Produzenten ermöglichen, standardisierte NFC-Tags für ihre Produkte zu erstellen. Beim Scannen dieser Tags werden automatisch die notwendigen Einträge in Spoolman (Marke, Filament-Typ und Spule) erstellt, ohne dass eine manuelle Einrichtung erforderlich ist. + +## Funktionsweise der Hersteller Tags + +### Ablauf + +1. **Tag-Erkennung**: Wenn ein Tag ohne `sm_id` gescannt wird, prüft das System auf Hersteller Tag Format +2. **Marken-Erstellung/Suche**: Das System sucht die Marke in Spoolman oder erstellt sie, falls sie nicht existiert +3. **Filament-Typ-Erstellung/Suche**: Der Filament-Typ wird basierend auf Marke, Material und Spezifikationen erstellt oder gefunden +4. **Spulen-Erstellung**: Ein neuer Spulen-Eintrag wird automatisch mit der Tag-UID als Referenz erstellt +5. **Tag-Update**: Der Tag wird mit der neuen Spoolman Spulen-ID (`sm_id`) aktualisiert + +### Warum Hersteller Tags verwenden? + +- **Automatische Integration**: Keine manuelle Dateneingabe erforderlich +- **Standardisiertes Format**: Konsistente Produktinformationen verschiedener Hersteller +- **Lagerverwaltung**: Automatische Erstellung vollständiger Spoolman-Einträge +- **Rückverfolgbarkeit**: Direkte Verbindung zwischen physischem Produkt und digitalem Inventar + +## Tag-Format Spezifikation + +### JSON-Struktur + +Hersteller Tags müssen eine JSON-Payload mit spezifischen Feldern enthalten, die **kurze Schlüssel** verwenden, um die Tag-Größe zu minimieren: + +```json +{ + "b": "Marke/Hersteller Name", + "an": "Artikelnummer", + "t": "Filament Typ (PLA, PETG, etc)", + "c": "Filament Farbe ohne # (FF5733)", + "mc": "Optional Mehrfarben-Filament Farben ohne # (FF0000,00FF00,0000FF)", + "mcd": "Optional Mehrfarben-Richtung als Wort (coaxial, longitudinal)", + "cn": "Farbname (rot, Blaubeere, Arktisches Blau)", + "et": "Extruder Temp als Zahl in C° (230)", + "bt": "Bett Temp als Zahl in C° (60)", + "di": "Durchmesser als Float (1.75)", + "de": "Dichte als Float (1.24)", + "sw": "Leeres Spulengewicht als Zahl in g (180)", + "u": "URL zum Filament mit der Artikelnummer" +} +``` + +### Pflichtfelder + +- **`b`** (brand): Hersteller/Markenname +- **`an`** (article number): Eindeutige Produktkennung +- **`t`** (type): Materialtyp (PLA, PETG, ABS, etc.) +- **`c`** (color): Hex-Farbcode ohne # +- **`cn`** (color name): Lesbare Farbbezeichnung +- **`et`** (extruder temp): Empfohlene Extruder-Temperatur in Celsius +- **`bt`** (bed temp): Empfohlene Bett-Temperatur in Celsius +- **`di`** (diameter): Filamentdurchmesser in mm +- **`de`** (density): Materialdichte in g/cm³ +- **`sw`** (spool weight): Leeres Spulengewicht in Gramm + +### Optionale Felder + +- **`mc`** (multicolor): Komma-getrennte Hex-Farben für Mehrfarben-Filamente +- **`mcd`** (multicolor direction): Richtung für Mehrfarben (coaxial, longitudinal) +- **`u`** (url): Produkt-URL mit direktem Link zum Artikel zB für Nachbestellung + +### Beispiel Tag + +```json +{"b":"Recycling Fabrik","an":"FX1_PETG-S175-1000-DAEM00055","t":"PETG","c":"FF5733","cn":"Lebendiges Orange","et":"230","bt":"70","di":"1.75","de":"1.24","sw":"180","u":"https://www.recyclingfabrik.com/search?q="} +``` + +## Implementierungsrichtlinien + +### Für Hersteller + +1. **Tag-Kodierung**: NDEF-Format mit MIME-Typ `application/json` verwenden +2. **Datenminimierung**: Kompaktes JSON-Format für Tag-Größenbegrenzungen nutzen +3. **Qualitätskontrolle**: Sicherstellen, dass alle Pflichtfelder vorhanden und korrekt formatiert sind +4. **Testen**: Tags vor der Produktion mit dem FilaMan-System verifizieren + +### Tag-Größe Überlegungen + +- **NTAG213**: 144 Bytes Nutzerdaten (geeignet für einfache Tags) +- **NTAG215**: 504 Bytes Nutzerdaten (empfohlen für umfassende Daten) +- **NTAG216**: 888 Bytes Nutzerdaten (maximale Kompatibilität) + +### Best Practices + +- Markennamen über alle Produkte hinweg konsistent halten +- Standardisierte Materialtypnamen verwenden (PLA, PETG, ABS, etc.) +- Genaue Temperaturempfehlungen angeben +- Aussagekräftige Farbnamen für bessere Benutzererfahrung verwenden +- Tags vor Massenproduktion mit dem FilaMan-System testen + +## System-Integration + +### Spoolman Datenbankstruktur + +Bei der Verarbeitung eines Hersteller Tags erstellt das System: + +1. **Lieferanten-Eintrag**: Markeninformationen in der Spoolman Lieferanten-Datenbank +2. **Filament-Eintrag**: Materialspezifikationen und Eigenschaften +3. **Spulen-Eintrag**: Einzelne Spule mit Gewicht und NFC-Tag-Referenz + +### Fast-Path Erkennung + +Sobald ein Tag verarbeitet und mit `sm_id` aktualisiert wurde, nutzt er das Fast-Path-Erkennungssystem für schnelle nachfolgende Scans. + +## Fehlerbehebung + +### Häufige Probleme + +- **Tag zu klein**: NTAG215 oder NTAG216 für größere JSON-Payloads verwenden +- **Fehlende Felder**: Sicherstellen, dass alle Pflichtfelder vorhanden sind +- **Ungültiges Format**: JSON-Syntax und Feldtypen überprüfen +- **Spoolman-Verbindung**: Sicherstellen, dass FilaMan mit der Spoolman API verbinden kann + +### Validierung + +Das System validiert: + +- JSON-Format Korrektheit +- Vorhandensein der Pflichtfelder +- Datentyp-Konformität +- Tag-Größe Kompatibilität + +## Technische Details + +### Verarbeitungsalgorithmus + +1. Tag-Scan erkennt kein `sm_id` Feld +2. System prüft auf `b` (Marke) und `an` (Artikelnummer) Felder +3. `checkVendor()` erstellt oder findet Marke in Spoolman +4. `checkFilament()` erstellt oder findet Filament-Typ +5. `createSpool()` erstellt neuen Spulen-Eintrag +6. Tag wird mit neuer `sm_id` aktualisiert + +### Fehlerbehandlung + +- Graceful Fallback bei Netzwerkproblemen +- Detaillierte Protokollierung für Debugging +- Benutzer-Feedback bei fehlgeschlagenen Operationen +- Wiederholungsmechanismen für temporäre Fehler + +### Systemverhalten + +#### Bei fehlendem sm_id: +- System prüft auf `b` (brand) und `an` (artnr) Felder +- Falls vorhanden → Hersteller Tag erkannt +- Automatische Erstellung von Lieferant, Filament und Spule in Spoolman +- Tag wird mit neuer `sm_id` beschrieben + +#### Bei vorhandenem sm_id: +- Fast-Path Erkennung für bekannte Spulen +- Sofortige Gewichtsmessung ohne vollständige Tag-Analyse +- Optimierte Performance für häufig verwendete Tags + +Dieses System ermöglicht eine nahtlose Integration von Hersteller-Filamentprodukten in das FilaMan-Ökosystem unter Beibehaltung von Datenkonsistenz und Benutzererfahrung. \ No newline at end of file diff --git a/README_ManufacturerTags_EN.md b/README_ManufacturerTags_EN.md new file mode 100644 index 0000000..f2ad5a8 --- /dev/null +++ b/README_ManufacturerTags_EN.md @@ -0,0 +1,145 @@ +# Manufacturer Tags - English Documentation + +## Overview + +The FilaMan NFC system supports **Manufacturer Tags** that allow filament producers to create standardized NFC tags for their products. When scanned, these tags automatically create the necessary entries in Spoolman (brand, filament type, and spool) without requiring manual setup. + +## How Manufacturer Tags Work + +### Process Flow + +1. **Tag Detection**: When a tag without `sm_id` is scanned, the system checks for manufacturer tag format +2. **Brand Creation/Lookup**: The system searches for the brand in Spoolman or creates it if it doesn't exist +3. **Filament Type Creation/Lookup**: The filament type is created or found based on brand, material, and specifications +4. **Spool Creation**: A new spool entry is automatically created with the tag's UID as reference +5. **Tag Update**: The tag is updated with the new Spoolman spool ID (`sm_id`) + +### Why Use Manufacturer Tags? + +- **Automatic Integration**: No manual data entry required +- **Standardized Format**: Consistent product information across different manufacturers +- **Inventory Management**: Automatic creation of complete Spoolman entries +- **Traceability**: Direct link between physical product and digital inventory + +## Tag Format Specification + +### JSON Structure + +Manufacturer tags must contain a JSON payload with specific fields using **short keys** to minimize tag size: + +```json +{ + "b": "Brand/Vendor Name", + "an": "Article Number", + "t": "Filament Type (PLA, PETG, etc)", + "c": "Filament Color without # (FF5733)", + "mc": "Optional Multicolor Filament Colors without # (FF0000,00FF00,0000FF)", + "mcd": "Optional Multicolor Direction as Word (coaxial, longitudinal)", + "cn": "Color Name (red, Blueberry, Arctic Blue)", + "et": "Extruder Temp as Number in C° (230)", + "bt": "Bed Temp as Number in C° (60)", + "di": "Diameter as Float (1.75)", + "de": "Density as Float (1.24)", + "sw": "Empty Spool Weight as Number in g (180)", + "u": "URL to get the Filament with the Article Number" +} +``` + +### Required Fields + +- **`b`** (brand): Manufacturer/brand name +- **`an`** (article number): Unique product identifier +- **`t`** (type): Material type (PLA, PETG, ABS, etc.) +- **`c`** (color): Hex color code without # +- **`cn`** (color name): Human-readable color name +- **`et`** (extruder temp): Recommended extruder temperature in Celsius +- **`bt`** (bed temp): Recommended bed temperature in Celsius +- **`di`** (diameter): Filament diameter in mm +- **`de`** (density): Material density in g/cm³ +- **`sw`** (spool weight): Empty spool weight in grams + +### Optional Fields + +- **`mc`** (multicolor): Comma-separated hex colors for multicolor filaments +- **`mcd`** (multicolor direction): Direction for multicolor (coaxial, longitudinal) +- **`u`** (url): Product URL with direct link to the article e.g. for reordering + +### Example Tag + +```json +{"b":"Recycling Fabrik","an":"FX1_PETG-S175-1000-DAEM00055","t":"PETG","c":"FF5733","cn":"Vibrant Orange","et":"230","bt":"70","di":"1.75","de":"1.24","sw":"180","u":"https://www.recyclingfabrik.com/search?q="} +``` + +## Implementation Guidelines + +### For Manufacturers + +1. **Tag Encoding**: Use NDEF format with MIME type `application/json` +2. **Data Minimization**: Use the compact JSON format to fit within tag size limits +3. **Quality Control**: Ensure all required fields are present and correctly formatted +4. **Testing**: Verify tags work with FilaMan system before production + +### Tag Size Considerations + +- **NTAG213**: 144 bytes user data (suitable for basic tags) +- **NTAG215**: 504 bytes user data (recommended for comprehensive data) +- **NTAG216**: 888 bytes user data (maximum compatibility) + +### Best Practices + +- Keep brand names consistent across all products +- Use standardized material type names (PLA, PETG, ABS, etc.) +- Provide accurate temperature recommendations +- Include meaningful color names for user experience +- Test tags with the FilaMan system before mass production + +## System Integration + +### Spoolman Database Structure + +When a manufacturer tag is processed, the system creates: + +1. **Vendor Entry**: Brand information in Spoolman vendor database +2. **Filament Entry**: Material specifications and properties +3. **Spool Entry**: Individual spool with weight and NFC tag reference + +### Fast-Path Recognition + +Once a tag is processed and updated with `sm_id`, it uses the fast-path recognition system for quick subsequent scans. + +## Troubleshooting + +### Common Issues + +- **Tag Too Small**: Use NTAG215 or NTAG216 for larger JSON payloads +- **Missing Fields**: Ensure all required fields are present +- **Invalid Format**: Verify JSON syntax and field types +- **Spoolman Connection**: Ensure FilaMan can connect to Spoolman API + +### Validation + +The system validates: +- JSON format correctness +- Required field presence +- Data type compliance +- Tag size compatibility + +## Technical Details + +### Processing Algorithm + +1. Tag scan detects no `sm_id` field +2. System checks for `b` (brand) and `an` (article number) fields +3. `checkVendor()` creates or finds brand in Spoolman +4. `checkFilament()` creates or finds filament type +5. `createSpool()` creates new spool entry +6. Tag is updated with new `sm_id` + +### Error Handling + +- Graceful fallback for network issues +- Detailed logging for debugging +- User feedback for failed operations +- Retry mechanisms for temporary failures + +This system enables seamless integration of manufacturer filament products into the FilaMan ecosystem while maintaining data consistency and user experience. \ No newline at end of file diff --git a/WIKI_DE.md b/WIKI_DE.md new file mode 100644 index 0000000..b4ed552 --- /dev/null +++ b/WIKI_DE.md @@ -0,0 +1,468 @@ +# FilaMan Wiki - Deutsch + +## Inhaltsverzeichnis + +1. [Überblick](#überblick) +2. [Installation](#installation) +3. [Hardware-Anforderungen](#hardware-anforderungen) +4. [Ersteinrichtung](#ersteinrichtung) +5. [Konfiguration](#konfiguration) +6. [Benutzung](#benutzung) +7. [NFC-Tags](#nfc-tags) +8. [Bambu Lab Integration](#bambu-lab-integration) +9. [Spoolman Integration](#spoolman-integration) +10. [Octoprint Integration](#octoprint-integration) +11. [Hersteller Tags](#hersteller-tags) +12. [Fehlerbehebung](#fehlerbehebung) +13. [Support](#support) + +--- + +## Überblick + +FilaMan ist ein umfassendes Filament-Managementsystem für 3D-Drucker, das auf ESP32-Hardware basiert. Es bietet Gewichtsmessung, NFC-Tag-Management und nahtlose Integration mit Spoolman und Bambu Lab 3D-Druckern. + +### Hauptfunktionen + +- **Präzise Gewichtsmessung** mit HX711 Wägezellen-Verstärker +- **NFC-Tag Lesen und Schreiben** für Filament-Identifikation +- **OLED-Display** für Status-Anzeigen +- **WiFi-Konnektivität** mit einfacher Konfiguration +- **Webbasierte Benutzeroberfläche** mit Echtzeit-Updates +- **Spoolman-Integration** für Lagerverwaltung +- **Bambu Lab AMS-Steuerung** via MQTT +- **Openspool NFC-Format** Kompatibilität +- **Hersteller Tag Unterstützung** für automatische Einrichtung + +### Systemvoraussetzungen + +- **ESP32 Development Board** +- **Spoolman Instanz** (erforderlich für volle Funktionalität) +- **WiFi-Netzwerk** +- **Webbrowser** (Chrome/Firefox/Safari) + +--- + +## Installation + +### Einfache Installation (Empfohlen) + +1. **Öffnen Sie den [FilaMan Web-Installer](https://www.filaman.app/installer.html)** + - Verwenden Sie einen Chrome-basierten Browser + +2. **ESP32 vorbereiten** + - Verbinden Sie den ESP32 über USB mit Ihrem Computer + - Klicken Sie auf "Connect" + +3. **Port auswählen** + - Wählen Sie den entsprechenden USB-Port aus + - Bestätigen Sie die Auswahl + +4. **Installation starten** + - Klicken Sie auf "FilaMan installieren" + - Warten Sie, bis der Installationsvorgang abgeschlossen ist + +### Manuelle Kompilierung + +Für erfahrene Benutzer mit PlatformIO: + +```bash +git clone https://github.com/ManuelW77/Filaman.git +cd FilaMan/esp32 +pio lib install +pio run --target upload +``` + +--- + +## Hardware-Anforderungen + +### Erforderliche Komponenten + +| Komponente | Beschreibung | Amazon Link (Affiliate) | +|------------|--------------|-------------------------| +| ESP32 Development Board | Jede ESP32-Variante | [Amazon](https://amzn.to/3FHea6D) | +| HX711 + Wägezelle | 5kg Load Cell Amplifier | [Amazon](https://amzn.to/4ja1KTe) | +| OLED Display | 0.96" I2C 128x64 SSD1306 | [Amazon](https://amzn.to/445aaa9) | +| PN532 NFC Modul | V3 RFID-Modul | [Amazon](https://amzn.eu/d/gy9vaBX) | +| NFC Tags | NTAG213/NTAG215 | [Amazon](https://amzn.to/3E071xO) | +| TTP223 Touch Sensor | Optional für Tara-Funktion | [Amazon](https://amzn.to/4hTChMK) | + +### Pin-Konfiguration + +| Komponente | ESP32 Pin | Funktion | +|------------|-----------|----------| +| HX711 DOUT | 16 | Datenausgang Wägezelle | +| HX711 SCK | 17 | Takt Wägezelle | +| OLED SDA | 21 | I2C Daten | +| OLED SCL | 22 | I2C Takt | +| PN532 IRQ | 32 | Interrupt | +| PN532 RESET | 33 | Reset | +| PN532 SDA | 21 | I2C Daten (geteilt) | +| PN532 SCL | 22 | I2C Takt (geteilt) | +| TTP223 I/O | 25 | Touch-Sensor (optional) | + +### Wichtige Hinweise + +- **PN532 DIP-Schalter** müssen auf I2C-Modus eingestellt sein +- **3V Pin** vom ESP32 für Touch-Sensor verwenden +- **Wägezellen-Verkabelung**: E+ (rot), E- (schwarz), A- (weiß), A+ (grün) + +![Schaltplan](./img/Schaltplan.png) + +--- + +## Ersteinrichtung + +### Nach der Installation + +1. **ESP32 Neustart** + - Das System erstellt automatisch einen WiFi-Hotspot "FilaMan" + +2. **WiFi-Konfiguration** + - Verbinden Sie sich mit dem "FilaMan" Netzwerk + - Öffnen Sie einen Browser (automatisches Portal oder http://192.168.4.1) + - Konfigurieren Sie Ihre WiFi-Zugangsdaten + +3. **Erster Zugriff** + - Nach erfolgreicher WiFi-Verbindung ist das System unter http://filaman.local erreichbar + - Alternativ über die vom Router zugewiesene IP-Adresse + +### Spoolman Vorbereitung + +**Wichtiger Hinweis**: Spoolman muss im Debug-Modus laufen: + +```env +# In der .env Datei von Spoolman auskommentieren: +SPOOLMAN_DEBUG_MODE=TRUE +``` + +Dies ist erforderlich, da Spoolman noch keine CORS-Domain-Konfiguration unterstützt. + +--- + +## Konfiguration + +### Waagen-Kalibrierung + +1. **Kalibrierung starten** + - Gehen Sie zur "Scale" (Waage) Seite + - Bereiten Sie ein 500g Referenzgewicht vor (z.B. Wasserglas) + +2. **Kalibrierungsschritte** + - Folgen Sie den Anweisungen auf dem Display + - Legen Sie das Gewicht auf, wenn gefordert + - Warten Sie, bis die Kalibrierung abgeschlossen ist + +3. **Validierung** + - Testen Sie die Genauigkeit mit bekannten Gewichten + - Bei Bedarf "Tare Scale" für Nullstellung verwenden + +### Spoolman-Verbindung + +1. **Spoolman-URL eingeben** + - Gehen Sie zur "Spoolman/Bambu" Seite + - Geben Sie die vollständige URL Ihrer Spoolman-Instanz ein + - Format: `http://spoolman-server:7912` + +2. **Verbindung testen** + - Das System prüft automatisch die Verbindung + - Erfolgreiche Verbindung wird durch grünen Status angezeigt + +### Bambu Lab Drucker (optional) + +1. **Drucker-Einstellungen** + - Öffnen Sie das Einstellungsmenü auf Ihrem Bambu-Drucker + - Notieren Sie sich die folgenden Daten: + - IP-Adresse des Druckers + - Access Code + - Serial Number + +2. **FilaMan Konfiguration** + - Geben Sie die Drucker-Daten in der "Spoolman/Bambu" Seite ein + - Aktivieren Sie "Auto Send to Bambu" für automatische AMS-Zuordnung + +3. **Auto-Send Timeout** + - Konfigurieren Sie die Wartezeit für automatische Spulen-Erkennung + - Empfohlener Wert: 10-30 Sekunden + +--- + +## Benutzung + +### Grundlegende Bedienung + +1. **Filament wiegen** + - Platzieren Sie die Spule auf der Waage + - Das Gewicht wird automatisch auf dem Display und in der Weboberfläche angezeigt + +2. **NFC-Tag scannen** + - Halten Sie den Tag in die Nähe des PN532-Moduls + - Bei erkannten Tags wird die Spulen-Information angezeigt + - Das Gewicht wird automatisch in Spoolman aktualisiert + +3. **Status-Überwachung** + - **OLED-Display** zeigt aktuelles Gewicht und Verbindungsstatus + - **Weboberfläche** bietet detaillierte Informationen und Steuerung + +### Weboberfläche Navigation + +- **Startseite**: Hauptfunktionen und aktueller Status +- **Scale**: Waagen-Kalibrierung und -Einstellungen +- **Spoolman/Bambu**: System-Konfiguration +- **Statistics**: Nutzungsstatistiken (falls aktiviert) + +--- + +## NFC-Tags + +### Unterstützte Tag-Typen + +- **NTAG213**: 144 Bytes (grundlegende Funktionen) +- **NTAG215**: 504 Bytes (empfohlen) +- **NTAG216**: 888 Bytes (erweiterte Funktionen) + +### Tag beschreiben + +1. **Spule in Spoolman vorbereiten** + - Erstellen Sie eine neue Spule in Spoolman + - Stellen Sie sicher, dass alle erforderlichen Daten eingegeben sind + +2. **Tag-Beschreibung starten** + - Wählen Sie die Spule aus der Liste + - Klicken Sie auf "Write Tag" + - Das Display zeigt "Waiting for Tag" + +3. **Tag auflegen** + - Platzieren Sie den NFC-Tag auf dem PN532-Modul + - Warten Sie auf die Bestätigung + +4. **Erfolgsmeldung** + - Bei erfolgreichem Beschreiben wird ein Häkchen angezeigt + - Der Tag ist nun mit der Spoolman-Spule verknüpft + +### Tag lesen + +1. **Tag scannen** + - Platzieren Sie die Spule mit dem NFC-Tag auf die Waage über dem NFC-Reader + - Bei Problemen beim Lesen: Spule etwas anders positionieren (nicht ganz an den Rand) + - Die Spulen-Information wird automatisch geladen + +2. **Automatische Updates** + - Das aktuelle Gewicht wird in Spoolman übertragen + - Die Spule wird in der Weboberfläche automatisch ausgewählt + +--- + +## Bambu Lab Integration + +### AMS (Automatic Material System) + +1. **AMS-Status anzeigen** + - Die Weboberfläche zeigt den aktuellen Zustand aller AMS-Fächer + - Beladene Fächer werden mit Filament-Informationen angezeigt + +2. **Filament manuell zuordnen** + - Wählen Sie eine Spule aus der Spoolman-Liste + - Klicken Sie auf das entsprechende AMS-Fach-Symbol + - Das Filament wird dem Fach zugeordnet + +3. **Automatische Zuordnung** + - Nach dem Wiegen mit aktiviertem "Auto Send to Bambu" + - Das System wartet auf neue Spulen im AMS + - Kalibrierte Filamente werden automatisch zugeordnet + +### Bambu Studio Integration + +1. **Filament-Profile synchronisieren** + - Kalibrieren Sie Filamente in Bambu Studio + - Verwenden Sie Device → AMS → Bleistift-Symbol → Auswählen + +2. **Setting-IDs speichern** + - FilaMan erkennt verfügbare Setting-IDs automatisch + - Klicken Sie auf "Settings in Spoolman speichern" + - Die Profile werden für zukünftige Drucke verwendet + +### Verbindung wiederherstellen + +- Bei Verbindungsproblemen klicken Sie den roten Punkt in der Menüleiste +- Das System stellt automatisch eine neue Verbindung her + +--- + +## Spoolman Integration + +### Automatische Funktionen + +1. **Spulen-Synchronisation** + - Automatische Übertragung von Gewichtsänderungen + - Echtzeit-Updates der Spulen-Daten + +2. **Extra-Felder** + - FilaMan erstellt automatisch erforderliche benutzerdefinierte Felder + - NFC-Tag-UID wird als Referenz gespeichert + +3. **Filterung** + - "Nur Spulen ohne NFC-Tag anzeigen" für einfache Tag-Zuordnung + - Kategorisierung nach Herstellern und Materialtypen + +### Spoolman Octoprint Plugin + +Für Octoprint-Benutzer ist eine automatische Spulen-Zuordnung verfügbar: + +1. **Plugin installieren** + ``` + https://github.com/ManuelW77/OctoPrint-Spoolman-Filaman/archive/refs/heads/master.zip + ``` + +2. **FilaMan konfigurieren** + - Aktivieren Sie "Send to Octo-Plugin" + - Geben Sie Octoprint-URL und API-Key ein + +3. **Automatische Zuordnung** + - Nach dem Wiegen wird die Spule automatisch in Octoprint aktiviert + - Unterstützt aktuell nur Tool0 (erste Düse) + +--- + +## Hersteller Tags + +### Überblick + +Hersteller Tags ermöglichen es Filament-Produzenten, vorkonfigurierte NFC-Tags zu liefern, die automatisch alle notwendigen Einträge in Spoolman erstellen. + +### Erste Schritte mit Hersteller Tags + +1. **Tag scannen** + - Platzieren Sie die Spule mit dem Hersteller-Tag auf die Waage über dem NFC-Reader + - Bei Problemen beim Lesen: Spule etwas anders positionieren (nicht ganz an den Rand) + - Das System erkennt automatisch das Hersteller-Format + +2. **Automatische Erstellung** + - **Marke** wird in Spoolman angelegt (falls nicht vorhanden) + - **Filament-Typ** wird mit allen Spezifikationen erstellt + - **Spule** wird automatisch registriert + +3. **Zukünftige Scans** + - Nach der ersten Einrichtung nutzen Tags das Fast-Path-System + - Sofortige Gewichtsmessung ohne erneute Einrichtung + +### Unterstützte Hersteller + +- **RecyclingFabrik**: Erster offizieller Partner +- Weitere Hersteller folgen + +### Vorteile + +- ✅ **Null manuelle Einrichtung** +- ✅ **Perfekte Datengenauigkeit** +- ✅ **Sofortige Integration** +- ✅ **Zukunftssicher** + +--- + +## Fehlerbehebung + +### Häufige Probleme + +#### WiFi-Verbindung + +**Problem**: Kann nicht mit FilaMan-Hotspot verbinden +- Lösung: Stellen Sie sicher, dass der ESP32 gestartet ist +- Alternative: Manuell zu http://192.168.4.1 navigieren + +**Problem**: Weboberfläche nicht erreichbar +- Lösung: Prüfen Sie die IP-Adresse im Router +- Alternative: Verwenden Sie http://filaman.local + +#### Waage + +**Problem**: Ungenaue Gewichtsmessungen +- Lösung: Kalibrierung wiederholen +- Tipp: Verwenden Sie "Tare Scale" für Nullstellung + +**Problem**: Wägezelle reagiert nicht +- Lösung: Überprüfen Sie die Verkabelung (E+, E-, A+, A-) +- Tipp: Testen Sie mit einem Multimeter + +#### NFC-Tags + +**Problem**: Tag wird nicht erkannt +- Lösung: Überprüfen Sie die PN532 DIP-Schalter (I2C-Modus) +- Tipp: Spule etwas anders auf der Waage positionieren (nicht ganz an den Rand) + +**Problem**: Tag kann nicht beschrieben werden +- Lösung: Verwenden Sie NTAG215 für bessere Kompatibilität +- Tipp: Stellen Sie sicher, dass der Tag nicht schreibgeschützt ist + +#### Spoolman + +**Problem**: Verbindung zu Spoolman schlägt fehl +- Lösung: Aktivieren Sie SPOOLMAN_DEBUG_MODE=TRUE +- Tipp: Überprüfen Sie die URL-Formatierung + +**Problem**: Spulen werden nicht angezeigt +- Lösung: Stellen Sie sicher, dass Spoolman läuft +- Tipp: Prüfen Sie die Netzwerk-Firewall-Einstellungen + +#### Bambu Lab + +**Problem**: Drucker verbindet nicht +- Lösung: Überprüfen Sie Access Code und IP-Adresse +- Tipp: Stellen Sie sicher, dass der Drucker im LAN-Modus ist + +**Problem**: AMS-Status wird nicht angezeigt +- Lösung: Prüfen Sie die MQTT-Verbindung +- Hinweis: Bambu kann die API jederzeit schließen + +### Debug-Informationen + +Falls Sie Probleme haben, können Sie diese Schritte zur Diagnose verwenden: + +#### Serieller Monitor (für Entwickler) +- Verbinden Sie den ESP32 über USB mit Ihrem Computer +- Öffnen Sie einen seriellen Monitor (z.B. Arduino IDE) mit 115200 Baud +- Sie sehen detaillierte Log-Nachrichten des Systems + +#### Browser-Konsole +- Öffnen Sie die Weboberfläche von FilaMan +- Drücken Sie F12 um die Entwicklertools zu öffnen +- Schauen Sie in der Konsole nach Fehlermeldungen + +#### Neustart bei anhaltenden Problemen +1. ESP32 vom Strom trennen +2. 10 Sekunden warten +3. Wieder anschließen +4. 30 Sekunden für vollständigen Start warten + +--- + +## Support + +### Community + +- **Discord Server**: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) +- **GitHub Issues**: [Filaman Repository](https://github.com/ManuelW77/Filaman/issues) +- **YouTube Kanal**: [Deutsches Erklärvideo](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU) + +### Dokumentation + +- **Offizielle Website**: [www.filaman.app](https://www.filaman.app) +- **GitHub Wiki**: [Detaillierte Dokumentation](https://github.com/ManuelW77/Filaman/wiki) +- **Hardware-Referenz**: ESP32 Pinout-Diagramme in `/img/` + +### Entwicklung unterstützen + +Wenn Sie das Projekt unterstützen möchten: + +[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://www.buymeacoffee.com/manuelw) + +### Lizenz + +Dieses Projekt ist unter der MIT-Lizenz veröffentlicht. Siehe [LICENSE](LICENSE.txt) für Details. + +--- + +**Letzte Aktualisierung**: August 2025 +**Version**: 2.0 +**Maintainer**: Manuel W. \ No newline at end of file diff --git a/WIKI_EN.md b/WIKI_EN.md new file mode 100644 index 0000000..5cee6e4 --- /dev/null +++ b/WIKI_EN.md @@ -0,0 +1,746 @@ +# FilaMan Wiki - English + +## Table of Contents + +1. [Overview](#overview) +2. [Installation](#installation) +3. [Hardware Requirements](#hardware-requirements) +4. [Initial Setup](#initial-setup) +5. [Configuration](#configuration) +6. [Usage](#usage) +7. [NFC Tags](#nfc-tags) +8. [Bambu Lab Integration](#bambu-lab-integration) +9. [Spoolman Integration](#spoolman-integration) +10. [Octoprint Integration](#octoprint-integration) +11. [Manufacturer Tags](#manufacturer-tags) +12. [Troubleshooting](#troubleshooting) +13. [Support](#support) + +--- + +## Overview + +FilaMan is a comprehensive filament management system for 3D printers based on ESP32 hardware. It provides weight measurement, NFC tag management, and seamless integration with Spoolman and Bambu Lab 3D printers. + +### Key Features + +- **Precise weight measurement** with HX711 load cell amplifier +- **NFC tag reading and writing** for filament identification +- **OLED display** for status information +- **WiFi connectivity** with easy configuration +- **Web-based user interface** with real-time updates +- **Spoolman integration** for inventory management +- **Bambu Lab AMS control** via MQTT +- **OpenSpool NFC format** compatibility +- **Manufacturer tag support** for automatic setup + +### System Requirements + +- **ESP32 Development Board** +- **Spoolman Instance** (required for full functionality) +- **WiFi Network** +- **Web Browser** (Chrome/Firefox/Safari) + +--- + +## Installation + +### Easy Installation (Recommended) + +1. **Open the [FilaMan Web Installer](https://www.filaman.app/installer.html)** + - Use a Chrome-based browser + +2. **Prepare ESP32** + - Connect ESP32 via USB to your computer + - Click "Connect" + +3. **Select Port** + - Choose the appropriate USB port + - Confirm selection + +4. **Start Installation** + - Click "Install FilaMan" + - Wait for installation to complete + +### Manual Compilation + +For advanced users with PlatformIO: + +```bash +git clone https://github.com/ManuelW77/Filaman.git +cd FilaMan/esp32 +pio lib install +pio run --target upload +``` + +--- + +## Hardware Requirements + +### Required Components + +| Component | Description | Amazon Link (Affiliate) | +|-----------|-------------|-------------------------| +| ESP32 Development Board | Any ESP32 variant | [Amazon](https://amzn.to/3FHea6D) | +| HX711 + Load Cell | 5kg Load Cell Amplifier | [Amazon](https://amzn.to/4ja1KTe) | +| OLED Display | 0.96" I2C 128x64 SSD1306 | [Amazon](https://amzn.to/445aaa9) | +| PN532 NFC Module | V3 RFID Module | [Amazon](https://amzn.eu/d/gy9vaBX) | +| NFC Tags | NTAG213/NTAG215 | [Amazon](https://amzn.to/3E071xO) | +| TTP223 Touch Sensor | Optional for tare function | [Amazon](https://amzn.to/4hTChMK) | + +### Pin Configuration + +| Component | ESP32 Pin | Function | +|-----------|-----------|----------| +| HX711 DOUT | 16 | Load cell data output | +| HX711 SCK | 17 | Load cell clock | +| OLED SDA | 21 | I2C data | +| OLED SCL | 22 | I2C clock | +| PN532 IRQ | 32 | Interrupt | +| PN532 RESET | 33 | Reset | +| PN532 SDA | 21 | I2C data (shared) | +| PN532 SCL | 22 | I2C clock (shared) | +| TTP223 I/O | 25 | Touch sensor (optional) | + +### Important Notes + +- **PN532 DIP switches** must be set to I2C mode +- **3V pin** from ESP32 for touch sensor +- **Load cell wiring**: E+ (red), E- (black), A- (white), A+ (green) + +![Wiring Diagram](./img/Schaltplan.png) + +--- + +## Initial Setup + +### After Installation + +1. **ESP32 Restart** + - System automatically creates a WiFi hotspot "FilaMan" + +2. **WiFi Configuration** + - Connect to the "FilaMan" network + - Open browser (automatic portal or ) + - Configure your WiFi credentials + +3. **First Access** + - After successful WiFi connection, access system at + - Alternative: Use IP address assigned by router + +### Spoolman Preparation + +**Important Note**: Spoolman must run in debug mode: + +```env +# Uncomment in Spoolman's .env file: +SPOOLMAN_DEBUG_MODE=TRUE +``` + +This is required as Spoolman doesn't support CORS domain configuration yet. + +--- + +## Configuration + +### Scale Calibration + +1. **Start Calibration** + - Go to "Scale" page + - Prepare a 500g reference weight (e.g., water glass) + +2. **Calibration Steps** + - Follow instructions on display + - Place weight when prompted + - Wait for calibration to complete + +3. **Validation** + - Test accuracy with known weights + - Use "Tare Scale" for zero adjustment if needed + +### Spoolman Connection + +1. **Enter Spoolman URL** + - Go to "Spoolman/Bambu" page + - Enter complete URL of your Spoolman instance + - Format: `http://spoolman-server:7912` + +2. **Test Connection** + - System automatically checks connection + - Successful connection shown by green status + +### Bambu Lab Printer (Optional) + +1. **Printer Settings** + - Open settings menu on your Bambu printer + - Note the following data: + - Printer IP address + - Access Code + - Serial Number + +2. **FilaMan Configuration** + - Enter printer data on "Spoolman/Bambu" page + - Enable "Auto Send to Bambu" for automatic AMS assignment + +3. **Auto-Send Timeout** + - Configure waiting time for automatic spool detection + - Recommended value: 10-30 seconds + +--- + +## Usage + +### Basic Operation + +1. **Weigh Filament** + - Place spool on scale + - Weight automatically displayed on screen and web interface + +2. **Scan NFC Tag** + - Hold tag near PN532 module + - Recognized tags display spool information + - Weight automatically updated in Spoolman + +3. **Status Monitoring** + - **OLED Display** shows current weight and connection status + - **Web Interface** provides detailed information and control + +### Web Interface Navigation + +- **Home**: Main functions and current status +- **Scale**: Scale calibration and settings +- **Spoolman/Bambu**: System configuration +- **Statistics**: Usage statistics (if enabled) + +--- + +## NFC Tags + +### Supported Tag Types + +- **NTAG213**: 144 bytes (basic functions) +- **NTAG215**: 504 bytes (recommended) +- **NTAG216**: 888 bytes (extended functions) + +### Writing Tags + +1. **Prepare Spool in Spoolman** + - Create new spool in Spoolman + - Ensure all required data is entered + +2. **Start Tag Writing** + - Select spool from list + - Click "Write Tag" + - Display shows "Waiting for Tag" + +3. **Place Tag** + - Position NFC tag on PN532 module + - Wait for confirmation + +4. **Success Message** + - Successful writing shows checkmark + - Tag is now linked to Spoolman spool + +### Reading Tags + +1. **Scan Tag** + - Place the spool with NFC tag on the scale over the NFC reader + - If reading fails: Reposition spool slightly (not completely at the edge) + - Spool information automatically loaded + +2. **Automatic Updates** + - Current weight transferred to Spoolman + - Spool automatically selected in web interface + +--- + +## Bambu Lab Integration + +### AMS (Automatic Material System) + +1. **Display AMS Status** + - Web interface shows current state of all AMS slots + - Loaded slots display filament information + +2. **Manual Filament Assignment** + - Select spool from Spoolman list + - Click corresponding AMS slot icon + - Filament assigned to slot + +3. **Automatic Assignment** + - After weighing with "Auto Send to Bambu" enabled + - System waits for new spools in AMS + - Calibrated filaments automatically assigned + +### Bambu Studio Integration + +1. **Sync Filament Profiles** + - Calibrate filaments in Bambu Studio + - Use Device → AMS → Pencil icon → Select + +2. **Save Setting IDs** + - FilaMan automatically detects available setting IDs + - Click "Save Settings to Spoolman" + - Profiles used for future prints + +### Restore Connection + +- For connection issues, click red dot in menu bar +- System automatically establishes new connection + +--- + +## Spoolman Integration + +### Automatic Functions + +1. **Spool Synchronization** + - Automatic transfer of weight changes + - Real-time updates of spool data + +2. **Extra Fields** + - FilaMan automatically creates required custom fields + - NFC tag UID stored as reference + +3. **Filtering** + - "Show only spools without NFC tag" for easy tag assignment + - Categorization by manufacturers and material types + +### Spoolman Octoprint Plugin + +For Octoprint users, automatic spool assignment is available: + +1. **Install Plugin** + + ```text + https://github.com/ManuelW77/OctoPrint-Spoolman-Filaman/archive/refs/heads/master.zip + ``` + +2. **Configure FilaMan** + - Enable "Send to Octo-Plugin" + - Enter Octoprint URL and API key + +3. **Automatic Assignment** + - After weighing, spool automatically activated in Octoprint + - Currently supports only Tool0 (first nozzle) + +--- + +## Manufacturer Tags + +### Overview + +Manufacturer tags allow filament producers to provide pre-configured NFC tags that automatically create all necessary entries in Spoolman. + +### Getting Started with Manufacturer Tags + +1. **Scan Tag** + - Place spool with manufacturer tag on the scale over the NFC reader + - If reading fails: Reposition spool slightly (not completely at the edge) + - System automatically recognizes manufacturer format + +2. **Automatic Creation** + - **Brand** created in Spoolman (if not present) + - **Filament type** created with all specifications + - **Spool** automatically registered + +3. **Future Scans** + - After initial setup, tags use fast-path system + - Immediate weight measurement without re-setup + +### Supported Manufacturers + +- **RecyclingFabrik**: First official partner +- More manufacturers coming soon + +### Benefits + +- ✅ **Zero manual setup** +- ✅ **Perfect data accuracy** +- ✅ **Instant integration** +- ✅ **Future-proof** + +--- + +## Troubleshooting + +### Common Issues + +#### WiFi Connection + +**Issue**: Cannot connect to FilaMan hotspot + +- Solution: Ensure ESP32 is started +- Alternative: Manually navigate to + +**Issue**: Web interface not accessible + +- Solution: Check IP address in router +- Alternative: Use + +#### Scale + +**Issue**: Inaccurate weight measurements + +- Solution: Repeat calibration +- Tip: Use "Tare Scale" for zero adjustment + +**Issue**: Load cell not responding + +- Solution: Check wiring (E+, E-, A+, A-) +- Tip: Test with multimeter + +#### NFC Tags + +**Issue**: Tag not recognized + +- Solution: Check PN532 DIP switches (I2C mode) +- Tip: Reposition spool slightly on scale (not completely at the edge) + +**Issue**: Cannot write tag + +- Solution: Use NTAG215 for better compatibility +- Tip: Ensure tag is not write-protected + +#### Spoolman + +**Issue**: Connection to Spoolman fails + +- Solution: Enable SPOOLMAN_DEBUG_MODE=TRUE +- Tip: Check URL formatting + +**Issue**: Spools not displayed + +- Solution: Ensure Spoolman is running +- Tip: Check network firewall settings + +#### Bambu Lab + +**Issue**: Printer won't connect + +- Solution: Check access code and IP address +- Tip: Ensure printer is in LAN mode + +**Issue**: AMS status not displayed + +- Solution: Check MQTT connection +- Note: Bambu may close API at any time + +### Debug Information + +If you have problems, you can use these steps for diagnosis: + +#### Serial Monitor (for developers) + +- Connect the ESP32 via USB to your computer +- Open a serial monitor (e.g., Arduino IDE) with 115200 baud +- You will see detailed log messages from the system + +#### Browser Console + +- Open the FilaMan web interface +- Press F12 to open developer tools +- Check the console for error messages + +--- + +## Maintenance and Updates + +### Firmware Update + +1. **Via Web Interface**: Access `http://filaman.local/upgrade.html` +2. **Select firmware file** (.bin format) +3. **Upload** - System restarts automatically +4. **Configuration preserved** - Settings remain intact + +### System Reset + +For persistent issues: + +1. Disconnect ESP32 from power +2. Wait 10 seconds +3. Reconnect +4. Wait 30 seconds for complete startup + +--- + +## Support and Information + +**Manufacturer**: Your Company Name +**Maintainer**: Manuel W. + +### Scale Technology + +#### Weight Stabilization + +The system uses multiple filters for precise measurements: + +```cpp +// Moving Average Filter with 8 values +#define MOVING_AVERAGE_SIZE 8 +// Low-Pass Filter for smoothing +#define LOW_PASS_ALPHA 0.3f +// Thresholds for updates +#define DISPLAY_THRESHOLD 0.3f // Display update +#define API_THRESHOLD 1.5f // API actions +``` + +#### Calibration Algorithm + +1. **System Pause**: All tasks are temporarily paused +2. **Zero Setting**: Tare scale without weight +3. **Reference Measurement**: 500g weight for 10 measurements +4. **Calculation**: `newValue = rawValue / SCALE_LEVEL_WEIGHT` +5. **NVS Storage**: Permanent value with verification +6. **Filter Reset**: New baseline for stabilization + +#### Auto-Tare Logic + +```cpp +// Conditions for Auto-Tare +if (autoTare && (weight > 2 && weight < 7) || weight < -2) { + scale_tare_counter++; + if (scale_tare_counter >= 5) { + // Automatic zero setting + scale.tare(); + resetWeightFilter(); + } +} +``` + +### NFC Technology + +#### PN532 Communication + +- **Interface**: I2C at 400kHz +- **IRQ Pin**: Interrupt-based tag detection +- **Reset Handling**: Automatic recovery from communication errors +- **DIP Switches**: Must be set to I2C mode (00) + +#### NDEF Implementation + +```json +// FilaMan Spoolman Format (with sm_id) +{ + "sm_id": "123", + "color": "#FF5733", + "type": "PLA", + "brand": "Example Brand" +} +``` + +#### Manufacturer Tag Schema + +Compact JSON format for storage efficiency: + +```json +{ + "b": "RecyclingFabrik", // brand + "an": "FX1_PLA-S175-1000-RED", // article number + "t": "PLA", // type + "c": "FF0000", // color (hex without #) + "cn": "Red", // color name + "et": "210", // extruder temp + "bt": "60", // bed temp + "di": "1.75", // diameter + "de": "1.24", // density + "sw": "240", // spool weight + "u": "https://www.yoururl.com/search?q=" // URL used vor Brand Link and Filament Link +} +``` + +### Display System + +#### OLED Architecture (SSD1306) + +- **Resolution**: 128x64 pixels monochrome +- **Areas**: + - Status bar: 0-16 pixels (version, icons) + - Main area: 17-64 pixels (weight, messages) +- **Update Interval**: 1 second for status line + +#### Icon System + +Bitmap icons for various states: + +```cpp +// Status Icons (16x16 pixels) +- icon_success: Checkmark for successful operations +- icon_failed: X for errors +- icon_transfer: Arrow for data transmission +- icon_loading: Loading circle for ongoing operations + +// Connection Icons with strikethrough indicator +- wifi_on/wifi_off: WLAN status +- bambu_on: Bambu Lab connection +- spoolman_on: Spoolman API status +``` + +### API Integration + +#### Spoolman REST API + +FilaMan interacts with the following endpoints: + +```http +GET /api/v1/spool/ # List spools +POST /api/v1/spool/ # Create new spool +PUT /api/v1/spool/{id}/ # Update spool + +GET /api/v1/vendor/ # List vendors +POST /api/v1/vendor/ # Create new vendor + +GET /api/v1/filament/ # List filaments +POST /api/v1/filament/ # Create new filament +``` + +#### Request Handling + +```cpp +// Sequential API processing +enum spoolmanApiStateType { + API_IDLE = 0, + API_PROCESSING = 1, + API_ERROR = 2 +}; +``` + +Prevents simultaneous API calls and deadlocks. + +#### Weight Update Logic + +```cpp +// Conditions for Spoolman update +if (activeSpoolId != "" && + weigthCouterToApi > 3 && // 3+ stable measurements + weightSend == 0 && // Not yet sent + weight > 5 && // Minimum weight 5g + spoolmanApiState == API_IDLE) { + updateSpoolWeight(activeSpoolId, weight); +} +``` + +### Bambu Lab MQTT + +#### Connection Parameters + +```cpp +// SSL/TLS Configuration +#define BAMBU_PORT 8883 +#define BAMBU_USERNAME "bblp" + +// Topic Structure +String topic = "device/" + bambu_serial + "/report"; +String request_topic = "device/" + bambu_serial + "/request"; +``` + +#### AMS Data Structure + +```cpp +struct AMSData { + String tray_id; + String tray_type; + String tray_color; + String tray_material; + String setting_id; + String tray_info_idx; + bool has_spool; +}; +``` + +#### Auto-Send Mechanism + +```cpp +// After tag recognition +if (bambuCredentials.autosend_enable) { + autoSetToBambuSpoolId = activeSpoolId.toInt(); + // Countdown starts automatically + // Waits for new spool in AMS +} +``` + +### WebSocket Communication + +#### Message Types + +```javascript +// Client → Server +{ + "type": "writeNfcTag", + "tagType": "spool", + "payload": { /* JSON data */ } +} + +{ + "type": "scale", + "payload": "tare|calibrate|setAutoTare", + "enabled": true +} + +// Server → Client +{ + "type": "heartbeat", + "freeHeap": 245, + "bambu_connected": true, + "spoolman_connected": true +} + +{ + "type": "amsData", + "data": [ /* AMS array */ ] +} +``` + +#### Connection Management + +- **Auto-Reconnect**: Client-side reconnection +- **Heartbeat**: Every 30 seconds for connection monitoring +- **Cleanup**: Automatic removal of dead connections + +### Watchdog and Error Handling + +#### System Watchdog + +```cpp +// WDT Configuration +esp_task_wdt_init(10, true); // 10s timeout, panic on overflow +esp_task_wdt_add(NULL); // Add current task +``` + +#### Error Recovery + +- **NFC Reset**: Automatic PN532 restart on communication errors +- **MQTT Reconnect**: Bambu Lab connection automatically restored +- **WiFi Monitoring**: Connection check every 60 seconds + +--- + +## Support + +### Community + +- **Discord Server**: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) +- **GitHub Issues**: [Filaman Repository](https://github.com/ManuelW77/Filaman/issues) +- **YouTube Channel**: [German explanation video](https://youtu.be/uNDe2wh9SS8?si=b-jYx4I1w62zaOHU) + +### Documentation + +- **Official Website**: [www.filaman.app](https://www.filaman.app) +- **GitHub Wiki**: [Detailed documentation](https://github.com/ManuelW77/Filaman/wiki) +- **Hardware Reference**: ESP32 pinout diagrams in `/img/` + +### Support Development + +If you'd like to support the project: + +[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://www.buymeacoffee.com/manuelw) + +### License + +This project is released under the MIT License. See [LICENSE](LICENSE.txt) for details. + +--- + +**Last Updated**: August 2025 +**Version**: 2.0 +**Maintainer**: Manuel W. \ No newline at end of file diff --git a/html/bambu_credentials.json b/html/bambu_credentials.json new file mode 100644 index 0000000..ad0d698 --- /dev/null +++ b/html/bambu_credentials.json @@ -0,0 +1 @@ +{"bambu_ip": "192.168.1.14", "bambu_accesscode": "22772584", "bambu_serialnr": "01P00C492600230","autoSendToBambu":true,"autoSendTime": 60} \ No newline at end of file diff --git a/html/upgrade.html b/html/upgrade.html index 70d82ee..5bbcedf 100644 --- a/html/upgrade.html +++ b/html/upgrade.html @@ -56,7 +56,7 @@
-

Firmware Update

+

1) Firmware Update

Upload a new firmware file (upgrade_filaman_firmware_*.bin)

@@ -67,7 +67,7 @@
-

Webpage Update

+

2) Webpage Update

Upload a new webpage file (upgrade_filaman_website_*.bin)

diff --git a/img/rf-logo.png b/img/rf-logo.png new file mode 100644 index 0000000..78e80b4 Binary files /dev/null and b/img/rf-logo.png differ diff --git a/platformio.ini b/platformio.ini index f1d49c8..e10f3f6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,8 +9,8 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.7" -to_old_version = "1.5.0" +version = "2.0.7" +to_old_version = "1.5.10" ## [env:esp32dev] @@ -23,10 +23,7 @@ monitor_speed = 115200 lib_deps = tzapu/WiFiManager @ ^2.0.17 https://github.com/me-no-dev/ESPAsyncWebServer.git#master - #me-no-dev/AsyncTCP @ ^1.1.1 https://github.com/esphome/AsyncTCP.git - #mathieucarbou/ESPAsyncWebServer @ ^3.6.0 - #esp32async/AsyncTCP @ ^3.3.5 bogde/HX711 @ ^0.7.5 adafruit/Adafruit SSD1306 @ ^2.5.13 adafruit/Adafruit GFX Library @ ^1.11.11 @@ -36,7 +33,6 @@ lib_deps = digitaldragon/SSLClient @ ^1.3.2 ; Enable SPIFFS upload -#board_build.filesystem = spiffs board_build.filesystem = littlefs ; Update partition settings board_build.partitions = partitions.csv diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index 5a9b732..6058f2d 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -14,17 +14,45 @@ def get_version(): return version_match.group(1) if version_match else None def get_last_tag(): + """Get the last non-beta tag for changelog generation""" try: - result = subprocess.run(['git', 'describe', '--tags', '--abbrev=0'], + # Get all tags sorted by version + result = subprocess.run(['git', 'tag', '-l', '--sort=-version:refname'], capture_output=True, text=True) - return result.stdout.strip() + if result.returncode != 0: + return None + + tags = result.stdout.strip().split('\n') + + # Find the first (newest) non-beta tag + for tag in tags: + if tag and not '-beta' in tag.lower(): + print(f"Using last stable tag for changelog: {tag}") + return tag + + # Fallback: if no non-beta tags found, use the newest tag + print("No stable tags found, using newest tag") + if tags and tags[0]: + return tags[0] + return None except subprocess.CalledProcessError: return None def categorize_commit(commit_msg): """Categorize commit messages based on conventional commits""" lower_msg = commit_msg.lower() - if any(x in lower_msg for x in ['feat', 'add', 'new']): + + # Filter out automatic release documentation commits + if ('docs:' in lower_msg and + ('update changelog and header for version' in lower_msg or + 'update platformio.ini for' in lower_msg)): + return None # Skip these commits + + # Check for breaking changes first + if ('!' in commit_msg and any(x in lower_msg for x in ['feat!', 'fix!', 'chore!', 'refactor!'])) or \ + 'breaking change' in lower_msg or 'breaking:' in lower_msg: + return 'Breaking Changes' + elif any(x in lower_msg for x in ['feat', 'add', 'new']): return 'Added' elif any(x in lower_msg for x in ['fix', 'bug']): return 'Fixed' @@ -34,6 +62,7 @@ def categorize_commit(commit_msg): def get_changes_from_git(): """Get changes from git commits since last tag""" changes = { + 'Breaking Changes': [], 'Added': [], 'Changed': [], 'Fixed': [] @@ -54,9 +83,12 @@ def get_changes_from_git(): for commit in commits: if commit: category = categorize_commit(commit) - # Clean up commit message - clean_msg = re.sub(r'^(feat|fix|chore|docs|style|refactor|perf|test)(\(.*\))?:', '', commit).strip() - changes[category].append(clean_msg) + if category is not None: # Skip commits that return None (filtered out) + # Clean up commit message + clean_msg = re.sub(r'^(feat|fix|chore|docs|style|refactor|perf|test)(\(.*\))?!?:', '', commit).strip() + # Remove BREAKING CHANGE prefix if present + clean_msg = re.sub(r'^breaking change:\s*', '', clean_msg, flags=re.IGNORECASE).strip() + changes[category].append(clean_msg) except subprocess.CalledProcessError: print("Error: Failed to get git commits") diff --git a/src/api.cpp b/src/api.cpp index 8770fd2..3129d20 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -4,8 +4,11 @@ #include "commonFS.h" #include #include "debug.h" - +#include "scale.h" +#include "nfc.h" +#include volatile spoolmanApiStateType spoolmanApiState = API_IDLE; + //bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; @@ -13,6 +16,12 @@ bool sendOctoUpdate = false; String octoUrl = ""; String octoToken = ""; uint16_t remainingWeight = 0; +uint16_t createdVendorId = 0; // Store ID of newly created vendor +uint16_t foundVendorId = 0; // Store ID of found vendor +uint16_t foundFilamentId = 0; // Store ID of found filament +uint16_t createdFilamentId = 0; // Store ID of newly created filament +uint16_t createdSpoolId = 0; // Store ID of newly created spool +uint16_t updateOctoSpoolId = 0; // Store spool ID for OctoPrint update bool spoolmanConnected = false; bool spoolmanExtraFieldsChecked = false; TaskHandle_t* apiTask; @@ -23,6 +32,10 @@ struct SendToApiParams { String spoolsUrl; String updatePayload; String octoToken; + // Weight update parameters for sequential execution + bool triggerWeightUpdate; + String spoolIdForWeight; + uint16_t weightValue; }; JsonDocument fetchSingleSpoolInfo(int spoolId) { @@ -98,38 +111,83 @@ void sendToApi(void *parameter) { // Wait until API is IDLE while(spoolmanApiState != API_IDLE){ - Serial.println("Waiting!"); + vTaskDelay(100 / portTICK_PERIOD_MS); yield(); } spoolmanApiState = API_TRANSMITTING; SendToApiParams* params = (SendToApiParams*)parameter; - // Extrahiere die Werte + // Extract values including weight update parameters SpoolmanApiRequestType requestType = params->requestType; String httpType = params->httpType; String spoolsUrl = params->spoolsUrl; String updatePayload = params->updatePayload; - String octoToken = params->octoToken; + String octoToken = params->octoToken; + bool triggerWeightUpdate = params->triggerWeightUpdate; + String spoolIdForWeight = params->spoolIdForWeight; + uint16_t weightValue = params->weightValue; - HTTPClient http; - http.setReuse(false); + // Retry mechanism with configurable parameters + const uint8_t MAX_RETRIES = 3; + const uint16_t RETRY_DELAY_MS = 1000; // 1 second between retries + const uint16_t HTTP_TIMEOUT_MS = 10000; // 10 second HTTP timeout + + bool success = false; + int httpCode = -1; + String responsePayload = ""; + + // Try request with retries + for (uint8_t attempt = 1; attempt <= MAX_RETRIES && !success; attempt++) { + Serial.printf("API Request attempt %d/%d to: %s\n", attempt, MAX_RETRIES, spoolsUrl.c_str()); + + HTTPClient http; + http.setReuse(false); + http.setTimeout(HTTP_TIMEOUT_MS); // Set HTTP timeout + + http.begin(spoolsUrl); + http.addHeader("Content-Type", "application/json"); + if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); - http.begin(spoolsUrl); - http.addHeader("Content-Type", "application/json"); - if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); + // Execute HTTP request based on type + if (httpType == "PATCH") httpCode = http.PATCH(updatePayload); + else if (httpType == "POST") httpCode = http.POST(updatePayload); + else if (httpType == "GET") httpCode = http.GET(); + else httpCode = http.PUT(updatePayload); - int httpCode; - if (httpType == "PATCH") httpCode = http.PATCH(updatePayload); - else if (httpType == "POST") httpCode = http.POST(updatePayload); - else httpCode = http.PUT(updatePayload); + // Check if request was successful + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED) { + responsePayload = http.getString(); + success = true; + Serial.printf("API Request successful on attempt %d, HTTP Code: %d\n", attempt, httpCode); + } else { + Serial.printf("API Request failed on attempt %d, HTTP Code: %d (%s)\n", + attempt, httpCode, http.errorToString(httpCode).c_str()); + + // Don't retry on certain error codes (client errors) + if (httpCode >= 400 && httpCode < 500 && httpCode != 408 && httpCode != 429) { + Serial.println("Client error detected, stopping retries"); + break; + } + + // Wait before retry (except on last attempt) + if (attempt < MAX_RETRIES) { + Serial.printf("Waiting %dms before retry...\n", RETRY_DELAY_MS); + http.end(); + vTaskDelay(RETRY_DELAY_MS / portTICK_PERIOD_MS); + continue; + } + } + + http.end(); + } - if (httpCode == HTTP_CODE_OK) { - Serial.println("Spoolman erfolgreich aktualisiert"); + // Process successful response + if (success) { + Serial.println("Spoolman Abfrage erfolgreich"); // Restgewicht der Spule auslesen - String payload = http.getString(); JsonDocument doc; - DeserializationError error = deserializeJson(doc, payload); + DeserializationError error = deserializeJson(doc, responsePayload); if (error) { Serial.print("Fehler beim Parsen der JSON-Antwort: "); Serial.println(error.c_str()); @@ -142,7 +200,8 @@ void sendToApi(void *parameter) { //oledShowMessage("Remaining: " + String(remaining_weight) + "g"); if(!octoEnabled){ // TBD: Do not use Strings... - oledShowProgressBar(1, 1, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + //oledShowProgressBar(1, 1, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + oledShowMessage("Remaining: " + String(remainingWeight) + "g"); remainingWeight = 0; }else{ // ocoto is enabled, trigger octo update @@ -157,12 +216,147 @@ void sendToApi(void *parameter) { break; case API_REQUEST_OCTO_SPOOL_UPDATE: // TBD: Do not use Strings... - oledShowProgressBar(5, 5, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + //oledShowProgressBar(5, 5, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + oledShowMessage("Remaining: " + String(remainingWeight) + "g"); remainingWeight = 0; break; + case API_REQUEST_VENDOR_CREATE: + Serial.println("Vendor successfully created!"); + createdVendorId = doc["id"].as(); + Serial.print("Created Vendor ID: "); + Serial.println(createdVendorId); + oledShowProgressBar(1, 1, "Vendor", "Created!"); + break; + case API_REQUEST_VENDOR_CHECK: + if (doc.isNull() || doc.size() == 0) { + Serial.println("Vendor not found in response"); + foundVendorId = 0; + } else { + foundVendorId = doc[0]["id"].as(); + Serial.print("Found Vendor ID: "); + Serial.println(foundVendorId); + } + break; + case API_REQUEST_FILAMENT_CHECK: + if (doc.isNull() || doc.size() == 0) { + Serial.println("Filament not found in response"); + foundFilamentId = 0; + } else { + foundFilamentId = doc[0]["id"].as(); + Serial.print("Found Filament ID: "); + Serial.println(foundFilamentId); + } + break; + case API_REQUEST_FILAMENT_CREATE: + Serial.println("Filament successfully created!"); + createdFilamentId = doc["id"].as(); + Serial.print("Created Filament ID: "); + Serial.println(createdFilamentId); + oledShowProgressBar(1, 1, "Filament", "Created!"); + break; + case API_REQUEST_SPOOL_CREATE: + Serial.println("Spool successfully created!"); + createdSpoolId = doc["id"].as(); + Serial.print("Created Spool ID: "); + Serial.println(createdSpoolId); + oledShowProgressBar(1, 1, "Spool", "Created!"); + break; } } doc.clear(); + } else if (httpCode == HTTP_CODE_CREATED) { + Serial.println("Spoolman erfolgreich erstellt"); + + // Parse response for created resources + JsonDocument doc; + DeserializationError error = deserializeJson(doc, responsePayload); + if (error) { + Serial.print("Fehler beim Parsen der JSON-Antwort: "); + Serial.println(error.c_str()); + } else { + switch(requestType){ + case API_REQUEST_VENDOR_CREATE: + Serial.println("Vendor successfully created!"); + createdVendorId = doc["id"].as(); + Serial.print("Created Vendor ID: "); + Serial.println(createdVendorId); + oledShowProgressBar(1, 1, "Vendor", "Created!"); + break; + case API_REQUEST_FILAMENT_CREATE: + Serial.println("Filament successfully created!"); + createdFilamentId = doc["id"].as(); + Serial.print("Created Filament ID: "); + Serial.println(createdFilamentId); + oledShowProgressBar(1, 1, "Filament", "Created!"); + break; + case API_REQUEST_SPOOL_CREATE: + Serial.println("Spool successfully created!"); + createdSpoolId = doc["id"].as(); + Serial.print("Created Spool ID: "); + Serial.println(createdSpoolId); + oledShowProgressBar(1, 1, "Spool", "Created!"); + break; + default: + // Handle other create operations if needed + break; + } + } + doc.clear(); + + // Execute weight update if requested and tag update was successful + if (triggerWeightUpdate && requestType == API_REQUEST_SPOOL_TAG_ID_UPDATE && weightValue > 10) { + Serial.println("Executing weight update after successful tag update"); + + // Prepare weight update request + String weightUrl = spoolmanUrl + apiUrl + "/spool/" + spoolIdForWeight + "/measure"; + JsonDocument weightDoc; + weightDoc["weight"] = weightValue; + + String weightPayload; + serializeJson(weightDoc, weightPayload); + + Serial.print("Weight update URL: "); + Serial.println(weightUrl); + Serial.print("Weight update payload: "); + Serial.println(weightPayload); + + // Execute weight update + HTTPClient weightHttp; + weightHttp.setReuse(false); + weightHttp.setTimeout(HTTP_TIMEOUT_MS); + weightHttp.begin(weightUrl); + weightHttp.addHeader("Content-Type", "application/json"); + + int weightHttpCode = weightHttp.PUT(weightPayload); + + if (weightHttpCode == HTTP_CODE_OK) { + Serial.println("Weight update successful"); + String weightResponse = weightHttp.getString(); + JsonDocument weightResponseDoc; + DeserializationError weightError = deserializeJson(weightResponseDoc, weightResponse); + + if (!weightError) { + remainingWeight = weightResponseDoc["remaining_weight"].as(); + Serial.print("Updated weight: "); + Serial.println(remainingWeight); + + if (!octoEnabled) { + oledShowProgressBar(1, 1, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + remainingWeight = 0; + } else { + sendOctoUpdate = true; + } + } + weightResponseDoc.clear(); + } else { + Serial.print("Weight update failed with HTTP code: "); + Serial.println(weightHttpCode); + oledShowProgressBar(1, 1, "Failure!", "Weight update"); + } + + weightHttp.end(); + weightDoc.clear(); + } } else { switch(requestType){ case API_REQUEST_SPOOL_WEIGHT_UPDATE: @@ -176,14 +370,32 @@ void sendToApi(void *parameter) { case API_REQUEST_BAMBU_UPDATE: oledShowProgressBar(1, 1, "Failure!", "Bambu update"); break; + case API_REQUEST_VENDOR_CHECK: + oledShowProgressBar(1, 1, "Failure!", "Vendor check"); + foundVendorId = 0; // Set to 0 to indicate error/not found + break; + case API_REQUEST_VENDOR_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Vendor create"); + createdVendorId = 0; // Set to 0 to indicate error + break; + case API_REQUEST_FILAMENT_CHECK: + oledShowProgressBar(1, 1, "Failure!", "Filament check"); + foundFilamentId = 0; // Set to 0 to indicate error/not found + break; + case API_REQUEST_FILAMENT_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Filament create"); + createdFilamentId = 0; // Set to 0 to indicate error + break; + case API_REQUEST_SPOOL_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Spool create"); + createdSpoolId = 0; // Set to 0 to indicate error instead of hanging + break; } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); - - // TBD: really required? vTaskDelay(2000 / portTICK_PERIOD_MS); + nfcReaderState = NFC_IDLE; // Reset NFC state to allow retry } - http.end(); vTaskDelay(50 / portTICK_PERIOD_MS); // Speicher freigeben @@ -211,7 +423,8 @@ bool updateSpoolTagId(String uidString, const char* payload) { return false; } - String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + doc["sm_id"].as(); + String spoolId = doc["sm_id"].as(); + String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId; Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); @@ -235,22 +448,26 @@ bool updateSpoolTagId(String uidString, const char* payload) { params->httpType = "PATCH"; params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; + + // Add weight update parameters for sequential execution + params->triggerWeightUpdate = (weight > 10); + params->spoolIdForWeight = spoolId; + params->weightValue = weight; - // Erstelle die Task + // Erstelle die Task mit erhöhter Stackgröße für zusätzliche HTTP-Anfrage BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion "SendToApiTask", // Task-Name - 6144, // Stackgröße in Bytes + 8192, // Erhöhte Stackgröße für zusätzliche HTTP-Anfrage (void*)params, // Parameter 0, // Priorität - apiTask // Task-Handle (nicht benötigt) + apiTask // Task-Handle (nicht benötigt) ); updateDoc.clear(); - // Update Spool weight - //TBD: how to handle this with spool and locatin tags? Also potential parallel access again - //if (weight > 10) updateSpoolWeight(doc["sm_id"].as(), weight); + // Update Spool weight now handled sequentially in sendToApi task + // to prevent parallel API access issues return true; } @@ -440,6 +657,414 @@ bool updateSpoolBambuData(String payload) { return true; } +// #### Brand Filament +uint16_t createVendor(const JsonDocument& payload) { + oledShowProgressBar(2, 5, "New Brand", "Create new Vendor"); + + // Create new vendor in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdVendorId global variable + // Note: This function assumes that the caller has already ensured API is IDLE + createdVendorId = 65535; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/vendor"; + Serial.print("Create vendor with URL: "); + Serial.println(spoolsUrl); + + // Create JSON payload for vendor creation + JsonDocument vendorDoc; + vendorDoc["name"] = payload["b"].as(); + + // Extract domain from URL if present, otherwise use brand name + String externalId = ""; + if (payload["u"].is()) { + String url = payload["u"].as(); + // Extract domain from URL (e.g., "https://www.blubb.de/f1234/?suche=irgendwas" -> "https://www.blubb.de") + int protocolEnd = url.indexOf("://"); + if (protocolEnd != -1) { + int pathStart = url.indexOf("/", protocolEnd + 3); + externalId = (pathStart != -1) ? url.substring(0, pathStart) : url; + } else { + externalId = url; // No protocol found, use as is + } + } else { + externalId = payload["b"].as(); + } + vendorDoc["comment"] = externalId; + + String vendorPayload; + serializeJson(vendorDoc, vendorPayload); + Serial.print("Vendor Payload: "); + Serial.println(vendorPayload); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + vendorDoc.clear(); + return 0; + } + params->requestType = API_REQUEST_VENDOR_CREATE; + params->httpType = "POST"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = vendorPayload; + + // Create task without additional API state check since caller ensures synchronization + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + NULL // Task-Handle (nicht benötigt) + ); + + if (result != pdPASS) { + Serial.println("Failed to create vendor task!"); + delete params; + vendorDoc.clear(); + return 0; + } + + vendorDoc.clear(); + + // Delay for Display Bar + vTaskDelay(1000 / portTICK_PERIOD_MS); + + // Wait for task completion and return the created vendor ID + // Note: createdVendorId will be set by sendToApi when response is received + while(createdVendorId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + return createdVendorId; +} + +uint16_t checkVendor(const JsonDocument& payload) { + oledShowProgressBar(1, 5, "New Brand", "Check Vendor"); + + // Check if vendor exists using task system + foundVendorId = 65535; // Reset to invalid value to detect when API response is received + + String vendorName = payload["b"].as(); + vendorName.trim(); + vendorName.replace(" ", "+"); + String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendorName; + Serial.print("Check vendor with URL: "); + Serial.println(spoolsUrl); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + return 0; + } + params->requestType = API_REQUEST_VENDOR_CHECK; + params->httpType = "GET"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = ""; // Empty for GET request + + // Check if API is idle before creating task + while (spoolmanApiState != API_IDLE) + { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // Erstelle die Task + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + NULL // Task-Handle (nicht benötigt) + ); + + // Wait until foundVendorId is updated by the API response (not 65535 anymore) + while (foundVendorId == 65535) + { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + // Check if vendor was found + if (foundVendorId == 0) { + Serial.println("Vendor not found, creating new vendor..."); + uint16_t vendorId = createVendor(payload); + if (vendorId == 0) { + Serial.println("Failed to create vendor, returning 0."); + return 0; // Failed to create vendor + } else { + Serial.println("Vendor created with ID: " + String(vendorId)); + return vendorId; + } + } else { + Serial.println("Vendor found: " + payload["b"].as()); + Serial.print("Vendor ID: "); + Serial.println(foundVendorId); + return foundVendorId; + } +} + +uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { + oledShowProgressBar(4, 5, "New Brand", "Create Filament"); + + // Create new filament in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdFilamentId global variable + // Note: This function assumes that the caller has already ensured API is IDLE + createdFilamentId = 65535; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/filament"; + Serial.print("Create filament with URL: "); + Serial.println(spoolsUrl); + + // Create JSON payload for filament creation + JsonDocument filamentDoc; + filamentDoc["name"] = payload["cn"].as(); + filamentDoc["vendor_id"] = String(vendorId); + filamentDoc["material"] = payload["t"].as(); + filamentDoc["density"] = (payload["de"].is() && payload["de"].as().length() > 0) ? payload["de"].as() : "1.24"; + filamentDoc["diameter"] = (payload["di"].is() && payload["di"].as().length() > 0) ? payload["di"].as() : "1.75"; + filamentDoc["weight"] = String(weight); + filamentDoc["spool_weight"] = payload["sw"].as(); + filamentDoc["article_number"] = payload["an"].as(); + filamentDoc["settings_extruder_temp"] = payload["et"].is() ? payload["et"].as() : ""; + filamentDoc["settings_bed_temp"] = payload["bt"].is() ? payload["bt"].as() : ""; + + if (payload["an"].is()) + { + filamentDoc["external_id"] = payload["an"].as(); + filamentDoc["comment"] = payload["u"].is() ? payload["u"].as() + payload["an"].as() : "automatically generated"; + } + else + { + filamentDoc["comment"] = payload["u"].is() ? payload["u"].as() : "automatically generated"; + } + + if (payload["mc"].is()) { + filamentDoc["multi_color_hexes"] = payload["mc"].as(); + filamentDoc["multi_color_direction"] = payload["mcd"].is() ? payload["mcd"].as() : ""; + } + else + { + filamentDoc["color_hex"] = (payload["c"].is() && payload["c"].as().length() >= 6) ? payload["c"].as() : "FFFFFF"; + } + + String filamentPayload; + serializeJson(filamentDoc, filamentPayload); + Serial.print("Filament Payload: "); + Serial.println(filamentPayload); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + filamentDoc.clear(); + return 0; + } + params->requestType = API_REQUEST_FILAMENT_CREATE; + params->httpType = "POST"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = filamentPayload; + + // Create task without additional API state check since caller ensures synchronization + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + NULL // Task-Handle (nicht benötigt) + ); + + if (result != pdPASS) { + Serial.println("Failed to create filament task!"); + delete params; + filamentDoc.clear(); + return 0; + } + + filamentDoc.clear(); + + // Delay for Display Bar + vTaskDelay(1000 / portTICK_PERIOD_MS); + + // Wait for task completion and return the created filament ID + // Note: createdFilamentId will be set by sendToApi when response is received + while(createdFilamentId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + return createdFilamentId; +} + +uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { + oledShowProgressBar(3, 5, "New Brand", "Check Filament"); + + // Check if filament exists using task system + foundFilamentId = 65535; // Reset to invalid value to detect when API response is received + + String spoolsUrl = spoolmanUrl + apiUrl + "/filament?vendor.id=" + String(vendorId) + "&external_id=" + String(payload["artnr"].as()); + Serial.print("Check filament with URL: "); + Serial.println(spoolsUrl); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + return 0; + } + params->requestType = API_REQUEST_FILAMENT_CHECK; + params->httpType = "GET"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = ""; // Empty for GET request + + // Erstelle die Task + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + NULL // Task-Handle (nicht benötigt) + ); + + // Wait until foundFilamentId is updated by the API response (not 65535 anymore) + while (foundFilamentId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + // Check if filament was found + if (foundFilamentId == 0) { + Serial.println("Filament not found, creating new filament..."); + uint16_t filamentId = createFilament(vendorId, payload); + if (filamentId == 0) { + Serial.println("Failed to create filament, returning 0."); + return 0; // Failed to create filament + } else { + Serial.println("Filament created with ID: " + String(filamentId)); + return filamentId; + } + } else { + Serial.println("Filament found for vendor ID: " + String(vendorId)); + Serial.print("Filament ID: "); + Serial.println(foundFilamentId); + return foundFilamentId; + } +} + +uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& payload, String uidString) { + oledShowProgressBar(5, 5, "New Brand", "Create new Spool"); + + // Create new spool in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdSpoolId global variable + // Note: This function assumes that the caller has already ensured API is IDLE + createdSpoolId = 65535; // Reset to invalid value to detect when API response is received + + String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; + Serial.print("Create spool with URL: "); + Serial.println(spoolsUrl); + + // Create JSON payload for spool creation + JsonDocument spoolDoc; + spoolDoc["filament_id"] = String(filamentId); + spoolDoc["initial_weight"] = weight > 10 ? String(weight - payload["sw"].as()) : "1000"; + spoolDoc["spool_weight"] = (payload["sw"].is() && payload["sw"].as().length() > 0) ? payload["sw"].as() : "180"; + spoolDoc["remaining_weight"] = spoolDoc["initial_weight"]; + spoolDoc["lot_nr"] = (payload["an"].is() && payload["an"].as().length() > 0) ? payload["an"].as() : ""; + spoolDoc["comment"] = "automatically generated"; + spoolDoc["extra"]["nfc_id"] = "\"" + uidString + "\""; + + String spoolPayload; + serializeJson(spoolDoc, spoolPayload); + Serial.print("Spool Payload: "); + Serial.println(spoolPayload); + spoolDoc.clear(); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + spoolDoc.clear(); + return 0; + } + params->requestType = API_REQUEST_SPOOL_CREATE; + params->httpType = "POST"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = spoolPayload; + + // Create task without additional API state check since caller ensures synchronization + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + NULL // Task-Handle (nicht benötigt) + ); + + if (result != pdPASS) { + Serial.println("Failed to create spool task!"); + delete params; + return 0; + } + + // Wait for task completion and return the created spool ID + // Note: createdSpoolId will be set by sendToApi when response is received + while(createdSpoolId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + // Check if spool creation was successful + if (createdSpoolId == 0) { + Serial.println("ERROR: Spool creation failed"); + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; + } + + // Write data to tag with startWriteJsonToTag + // void startWriteJsonToTag(const bool isSpoolTag, const char* payload); + + // Create optimized JSON structure with sm_id at the beginning for fast-path detection + JsonDocument optimizedPayload; + optimizedPayload["sm_id"] = String(createdSpoolId); // Place sm_id first for fast scanning + optimizedPayload["b"] = payload["b"].as(); + optimizedPayload["cn"] = payload["an"].as(); + + String payloadString; + serializeJson(optimizedPayload, payloadString); + + Serial.println("Optimized JSON with sm_id first:"); + Serial.println(payloadString); + + optimizedPayload.clear(); + + nfcReaderState = NFC_IDLE; + + // Delay for Display Bar + vTaskDelay(1000 / portTICK_PERIOD_MS); + + startWriteJsonToTag(true, payloadString.c_str()); + + return createdSpoolId; +} + +bool createBrandFilament(JsonDocument& payload, String uidString) { + uint16_t vendorId = checkVendor(payload); + if (vendorId == 0) { + Serial.println("ERROR: Failed to create/find vendor"); + return false; + } + + uint16_t filamentId = checkFilament(vendorId, payload); + if (filamentId == 0) { + Serial.println("ERROR: Failed to create/find filament"); + return false; + } + + uint16_t spoolId = createSpool(vendorId, filamentId, payload, uidString); + if (spoolId == 0) { + Serial.println("ERROR: Failed to create spool"); + return false; + } + + Serial.println("SUCCESS: Brand filament created with Spool ID: " + String(spoolId)); + return true; +} + // #### Spoolman init bool checkSpoolmanExtraFields() { // Only check extra fields if they have not been checked before @@ -649,9 +1274,10 @@ bool checkSpoolmanInstance() { Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); } http.end(); - returnValue = false; spoolmanApiState = API_IDLE; - }else{ + } + else + { // If the check is skipped, return the previous status Serial.println("Skipping spoolman healthcheck, API is active."); returnValue = spoolmanConnected; diff --git a/src/api.h b/src/api.h index 4ad427f..a8aac63 100644 --- a/src/api.h +++ b/src/api.h @@ -17,7 +17,12 @@ typedef enum { API_REQUEST_BAMBU_UPDATE, API_REQUEST_SPOOL_TAG_ID_UPDATE, API_REQUEST_SPOOL_WEIGHT_UPDATE, - API_REQUEST_SPOOL_LOCATION_UPDATE + API_REQUEST_SPOOL_LOCATION_UPDATE, + API_REQUEST_VENDOR_CREATE, + API_REQUEST_VENDOR_CHECK, + API_REQUEST_FILAMENT_CHECK, + API_REQUEST_FILAMENT_CREATE, + API_REQUEST_SPOOL_CREATE } SpoolmanApiRequestType; extern volatile spoolmanApiStateType spoolmanApiState; @@ -28,6 +33,7 @@ extern bool sendOctoUpdate; extern String octoUrl; extern String octoToken; extern bool spoolmanConnected; +extern uint16_t updateOctoSpoolId; bool checkSpoolmanInstance(); bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk); @@ -40,5 +46,6 @@ uint8_t updateSpoolLocation(String spoolId, String location); bool initSpoolman(); // Neue Funktion zum Initialisieren von Spoolman bool updateSpoolBambuData(String payload); // Neue Funktion zum Aktualisieren der Bambu-Daten bool updateSpoolOcto(int spoolId); // Neue Funktion zum Aktualisieren der Octo-Daten +bool createBrandFilament(JsonDocument& payload, String uidString); #endif diff --git a/src/bambu.cpp b/src/bambu.cpp index 21fc6fa..3e2ae43 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -21,7 +21,7 @@ TaskHandle_t BambuMqttTask; bool bambuDisabled = false; bool bambu_connected = false; -int autoSetToBambuSpoolId = 0; +uint16_t autoSetToBambuSpoolId = 0; BambuCredentials bambuCredentials; @@ -33,6 +33,7 @@ AMSData ams_data[MAX_AMS]; // Definition des Arrays; bool removeBambuCredentials() { if (BambuMqttTask) { vTaskDelete(BambuMqttTask); + BambuMqttTask = NULL; } Preferences preferences; @@ -63,6 +64,7 @@ bool removeBambuCredentials() { bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) { if (BambuMqttTask) { vTaskDelete(BambuMqttTask); + BambuMqttTask = NULL; } bambuCredentials.ip = ip.c_str(); @@ -593,6 +595,7 @@ void reconnect() { Serial.println("Disable Bambu MQTT Task after 5 retries"); //vTaskSuspend(BambuMqttTask); vTaskDelete(BambuMqttTask); + BambuMqttTask = NULL; break; } @@ -681,6 +684,7 @@ void bambu_restart() { if (BambuMqttTask) { vTaskDelete(BambuMqttTask); + BambuMqttTask = NULL; delay(10); } setupMqtt(); diff --git a/src/bambu.h b/src/bambu.h index bf8836e..4fce1f3 100644 --- a/src/bambu.h +++ b/src/bambu.h @@ -37,7 +37,7 @@ extern bool bambu_connected; extern int ams_count; extern AMSData ams_data[MAX_AMS]; //extern bool autoSendToBambu; -extern int autoSetToBambuSpoolId; +extern uint16_t autoSetToBambuSpoolId; extern bool bambuDisabled; extern BambuCredentials bambuCredentials; diff --git a/src/display.cpp b/src/display.cpp index 0ccaa5f..c515b3d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -235,7 +235,7 @@ void oledShowIcon(const char* icon) { display.display(); } -void oledShowProgressBar(const uint8_t step, const uint8_t numSteps, const char* largeText, const char* statusMessage){ +void oledShowProgressBar(const uint8_t step, const uint8_t numSteps, const char* largeText, const char* statusMessage) { assert(step <= numSteps); // clear data and bar area diff --git a/src/main.cpp b/src/main.cpp index 2b75b6c..c9a41ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,7 @@ void setup() { // Scale start_scale(touchSensorConnected); + scaleTareRequest = true; // WDT initialisieren mit 10 Sekunden Timeout bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus @@ -134,7 +135,7 @@ void loop() { } // Wenn Bambu auto set Spool aktiv - if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0) + if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0 && !nfcWriteInProgress) { if (!bambuDisabled && !bambu_connected) { @@ -153,7 +154,9 @@ void loop() { { autoSetToBambuSpoolId = 0; autoAmsCounter = 0; - oledShowWeight(weight); + if (!nfcWriteInProgress) { + oledShowWeight(weight); + } } } else @@ -171,13 +174,18 @@ void loop() { oledShowMessage("Scale not calibrated"); vTaskDelay(1000 / portTICK_PERIOD_MS); } - }else{ + } + else + { // Ausgabe der Waage auf Display - if(pauseMainTask == 0) + // Block weight display during NFC write operations + if(pauseMainTask == 0 && !nfcWriteInProgress) { + // Use filtered weight for smooth display, but still check API weight for significant changes + int16_t displayWeight = getFilteredDisplayWeight(); if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0))) { - (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); + (displayWeight < 2) ? ((displayWeight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(displayWeight); } mainTaskWasPaused = false; } @@ -192,17 +200,6 @@ void loop() { { lastWeightReadTime = currentMillis; - // Prüfen ob die Waage korrekt genullt ist - // Abweichung von 2g ignorieren - if (autoTare && (weight > 2 && weight < 7) || weight < -2) - { - scale_tare_counter++; - } - else - { - scale_tare_counter = 0; - } - // Prüfen ob das Gewicht gleich bleibt und dann senden if (abs(weight - lastWeight) <= 2 && weight > 5) { @@ -216,7 +213,6 @@ void loop() { } // reset weight counter after writing tag - // TBD: what exactly is the logic behind this? if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS) { weigthCouterToApi = 0; @@ -225,7 +221,8 @@ void loop() { lastWeight = weight; // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden - if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS && tagProcessed == false && spoolmanApiState == API_IDLE) { + if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS && tagProcessed == false && spoolmanApiState == API_IDLE) + { // set the current tag as processed to prevent it beeing processed again tagProcessed = true; @@ -233,6 +230,15 @@ void loop() { { weightSend = 1; + // Set Bambu spool ID for auto-send if enabled + if (bambuCredentials.autosend_enable) + { + autoSetToBambuSpoolId = activeSpoolId.toInt(); + } + if (octoEnabled) + { + updateOctoSpoolId = activeSpoolId.toInt(); + } } else { @@ -241,13 +247,28 @@ void loop() { } } - if(sendOctoUpdate && spoolmanApiState == API_IDLE){ - autoSetToBambuSpoolId = activeSpoolId.toInt(); + // Handle successful tag write: Send weight to Spoolman but NEVER auto-send to Bambu + if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_WRITE_SUCCESS && tagProcessed == false && spoolmanApiState == API_IDLE) + { + // set the current tag as processed to prevent it beeing processed again + tagProcessed = true; - if(octoEnabled) + if (updateSpoolWeight(activeSpoolId, weight)) { - updateSpoolOcto(autoSetToBambuSpoolId); + weightSend = 1; + Serial.println("Tag written: Weight sent to Spoolman, but NO auto-send to Bambu"); + // INTENTIONALLY do NOT set autoSetToBambuSpoolId here to prevent Bambu auto-send } + else + { + oledShowIcon("failed"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } + } + + if(octoEnabled && sendOctoUpdate && spoolmanApiState == API_IDLE) + { + updateSpoolOcto(updateOctoSpoolId); sendOctoUpdate = false; } } diff --git a/src/nfc.cpp b/src/nfc.cpp index 5a8bdc1..9e92b76 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -23,6 +23,7 @@ bool tagProcessed = false; volatile bool pauseBambuMqttTask = false; volatile bool nfcReadingTaskSuspendRequest = false; volatile bool nfcReadingTaskSuspendState = false; +volatile bool nfcWriteInProgress = false; // Prevent any tag operations during write struct NfcWriteParameterType { bool tagType; @@ -39,7 +40,6 @@ volatile nfcReaderStateType nfcReaderState = NFC_IDLE; // 6 = reading // ***** PN532 - // ##### Funktionen für RFID ##### void payloadToJson(uint8_t *data) { const char* startJson = strchr((char*)data, '{'); @@ -60,7 +60,7 @@ void payloadToJson(uint8_t *data) { int min_temp = doc["min_temp"]; int max_temp = doc["max_temp"]; const char* brand = doc["brand"]; - + Serial.println(); Serial.println("-----------------"); Serial.println("JSON-Parsed Data:"); @@ -100,9 +100,7 @@ bool formatNdefTag() { } return success; - } - -uint16_t readTagSize() +}uint16_t readTagSize() { uint8_t buffer[4]; memset(buffer, 0, 4); @@ -110,115 +108,1135 @@ uint16_t readTagSize() return buffer[2]*8; } +// Robust page reading with error recovery +bool robustPageRead(uint8_t page, uint8_t* buffer) { + const int MAX_READ_ATTEMPTS = 3; + + for (int attempt = 0; attempt < MAX_READ_ATTEMPTS; attempt++) { + esp_task_wdt_reset(); + yield(); + + if (nfc.ntag2xx_ReadPage(page, buffer)) { + return true; + } + + Serial.printf("Page %d read failed, attempt %d/%d\n", page, attempt + 1, MAX_READ_ATTEMPTS); + + // Try to stabilize connection between attempts + if (attempt < MAX_READ_ATTEMPTS - 1) { + vTaskDelay(pdMS_TO_TICKS(25)); + + // Re-verify tag presence with quick check + uint8_t uid[7]; + uint8_t uidLength; + if (!nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 100)) { + Serial.println("Tag lost during read operation"); + return false; + } + } + } + + return false; +} + +String detectNtagType() +{ + // Read capability container from page 3 to determine exact NTAG type + uint8_t ccBuffer[4]; + memset(ccBuffer, 0, 4); + + if (!nfc.ntag2xx_ReadPage(3, ccBuffer)) { + Serial.println("Failed to read capability container"); + return "UNKNOWN"; + } + + // Also read configuration pages to get more info + uint8_t configBuffer[4]; + memset(configBuffer, 0, 4); + + Serial.print("Capability Container: "); + for (int i = 0; i < 4; i++) { + if (ccBuffer[i] < 0x10) Serial.print("0"); + Serial.print(ccBuffer[i], HEX); + Serial.print(" "); + } + Serial.println(); + + // NTAG type detection based on capability container + // CC[2] contains the data area size in bytes / 8 + uint16_t dataAreaSize = ccBuffer[2] * 8; + + Serial.print("Data area size from CC: "); + Serial.println(dataAreaSize); + + // Try to read different configuration pages to determine exact type + String tagType = "UNKNOWN"; + + // Try to read page 41 (NTAG213 ends at page 39, so this should fail) + uint8_t testBuffer[4]; + bool canReadPage41 = nfc.ntag2xx_ReadPage(41, testBuffer); + + // Try to read page 130 (NTAG215 ends at page 129, so this should fail for NTAG213/215) + bool canReadPage130 = nfc.ntag2xx_ReadPage(130, testBuffer); + + if (dataAreaSize <= 180 && !canReadPage41) { + tagType = "NTAG213"; + Serial.println("Detected: NTAG213 (cannot read beyond page 39)"); + } else if (dataAreaSize <= 540 && canReadPage41 && !canReadPage130) { + tagType = "NTAG215"; + Serial.println("Detected: NTAG215 (can read page 41, cannot read page 130)"); + } else if (dataAreaSize <= 928 && canReadPage130) { + tagType = "NTAG216"; + Serial.println("Detected: NTAG216 (can read page 130)"); + } else { + // Fallback: use data area size from capability container + if (dataAreaSize <= 180) { + tagType = "NTAG213"; + Serial.println("Fallback detection: NTAG213 based on data area size"); + } else if (dataAreaSize <= 540) { + tagType = "NTAG215"; + Serial.println("Fallback detection: NTAG215 based on data area size"); + } else { + tagType = "NTAG216"; + Serial.println("Fallback detection: NTAG216 based on data area size"); + } + } + + return tagType; +} + +uint16_t getAvailableUserDataSize() +{ + String tagType = detectNtagType(); + uint16_t userDataSize = 0; + + if (tagType == "NTAG213") { + // NTAG213: User data from page 4-39 (36 pages * 4 bytes = 144 bytes) + userDataSize = 144; + Serial.println("NTAG213 confirmed - 144 bytes user data available"); + } else if (tagType == "NTAG215") { + // NTAG215: User data from page 4-129 (126 pages * 4 bytes = 504 bytes) + userDataSize = 504; + Serial.println("NTAG215 confirmed - 504 bytes user data available"); + } else if (tagType == "NTAG216") { + // NTAG216: User data from page 4-225 (222 pages * 4 bytes = 888 bytes) + userDataSize = 888; + Serial.println("NTAG216 confirmed - 888 bytes user data available"); + } else { + // Unknown tag type, use conservative estimate + uint16_t tagSize = readTagSize(); + userDataSize = tagSize - 60; // Reserve 60 bytes for headers/config + Serial.print("Unknown NTAG type, using conservative estimate: "); + Serial.println(userDataSize); + } + + return userDataSize; +} + +uint16_t getMaxUserDataPages() +{ + String tagType = detectNtagType(); + uint16_t maxPages = 0; + + if (tagType == "NTAG213") { + maxPages = 39; // Pages 4-39 are user data + } else if (tagType == "NTAG215") { + maxPages = 129; // Pages 4-129 are user data + } else if (tagType == "NTAG216") { + maxPages = 225; // Pages 4-225 are user data + } else { + // Conservative fallback + maxPages = 39; + Serial.println("Unknown tag type, using NTAG213 page limit as fallback"); + } + + Serial.print("Maximum writable page: "); + Serial.println(maxPages); + return maxPages; +} + +bool initializeNdefStructure() { + // Write minimal NDEF structure without destroying the tag + // This creates a clean slate while preserving tag functionality + + Serial.println("Initialisiere sichere NDEF-Struktur..."); + + // Minimal NDEF structure: TLV with empty message + uint8_t minimalNdef[8] = { + 0x03, // NDEF Message TLV Tag + 0x03, // Length (3 bytes for minimal empty record) + 0xD0, // NDEF Record Header (TNF=0x0:Empty + SR + ME + MB) + 0x00, // Type Length (0 = empty record) + 0x00, // Payload Length (0 = empty record) + 0xFE, // Terminator TLV + 0x00, 0x00 // Padding + }; + + // Write the minimal structure starting at page 4 + uint8_t pageBuffer[4]; + + for (int i = 0; i < 8; i += 4) { + memcpy(pageBuffer, &minimalNdef[i], 4); + + if (!nfc.ntag2xx_WritePage(4 + (i / 4), pageBuffer)) { + Serial.print("Fehler beim Initialisieren von Seite "); + Serial.println(4 + (i / 4)); + return false; + } + + Serial.print("Seite "); + Serial.print(4 + (i / 4)); + Serial.print(" initialisiert: "); + for (int j = 0; j < 4; j++) { + if (pageBuffer[j] < 0x10) Serial.print("0"); + Serial.print(pageBuffer[j], HEX); + Serial.print(" "); + } + Serial.println(); + } + + Serial.println("✓ Sichere NDEF-Struktur initialisiert"); + Serial.println("✓ Tag bleibt funktionsfähig und überschreibbar"); + return true; +} + +bool clearUserDataArea() { + // IMPORTANT: Only clear user data pages, NOT configuration pages + // NTAG layout: Pages 0-3 (header), 4-N (user data), N+1-N+3 (config) - NEVER touch config! + String tagType = detectNtagType(); + + // Calculate safe user data page ranges (NEVER touch config pages!) + uint16_t firstUserPage = 4; + uint16_t lastUserPage = 0; + + if (tagType == "NTAG213") { + lastUserPage = 39; // Pages 40-42 are config - DO NOT TOUCH! + Serial.println("NTAG213: Sichere Löschung Seiten 4-39"); + } else if (tagType == "NTAG215") { + lastUserPage = 129; // Pages 130-132 are config - DO NOT TOUCH! + Serial.println("NTAG215: Sichere Löschung Seiten 4-129"); + } else if (tagType == "NTAG216") { + lastUserPage = 225; // Pages 226-228 are config - DO NOT TOUCH! + Serial.println("NTAG216: Sichere Löschung Seiten 4-225"); + } else { + // Conservative fallback - only clear a small safe area + lastUserPage = 39; + Serial.println("UNKNOWN TAG: Konservative Löschung Seiten 4-39"); + } + + Serial.println("WARNUNG: Vollständiges Löschen kann Tag beschädigen!"); + Serial.println("Verwende stattdessen selective NDEF-Überschreibung..."); + + // Instead of clearing everything, just write a minimal NDEF structure + // This is much safer and preserves tag integrity + return initializeNdefStructure(); +} + uint8_t ntag2xx_WriteNDEF(const char *payload) { + // Determine exact tag type and capabilities first + String tagType = detectNtagType(); uint16_t tagSize = readTagSize(); - Serial.print("Tag Size: ");Serial.println(tagSize); + uint16_t availableUserData = getAvailableUserDataSize(); + uint16_t maxWritablePage = getMaxUserDataPages(); + + Serial.println("=== NFC TAG ANALYSIS ==="); + Serial.print("Tag Type: ");Serial.println(tagType); + Serial.print("Total Tag Size: ");Serial.println(tagSize); + Serial.print("Available User Data: ");Serial.println(availableUserData); + Serial.print("Max Writable Page: ");Serial.println(maxWritablePage); + Serial.println("========================"); + + // Perform additional tag validation by testing write boundaries + Serial.println("=== TAG VALIDATION ==="); + uint8_t testBuffer[4] = {0x00, 0x00, 0x00, 0x00}; + + // Test if we can actually read the max page + if (!nfc.ntag2xx_ReadPage(maxWritablePage, testBuffer)) { + Serial.print("WARNING: Cannot read declared max page "); + Serial.println(maxWritablePage); + + // Find actual maximum writable page by testing backwards with optimized approach + uint16_t actualMaxPage = maxWritablePage; + Serial.println("Searching for actual maximum writable page..."); + + // Use binary search approach for faster page limit detection + uint16_t lowPage = 4; + uint16_t highPage = maxWritablePage; + uint16_t testAttempts = 0; + const uint16_t maxTestAttempts = 15; // Limit search attempts + + while (lowPage <= highPage && testAttempts < maxTestAttempts) { + uint16_t midPage = (lowPage + highPage) / 2; + testAttempts++; + + Serial.print("Testing page "); + Serial.print(midPage); + Serial.print(" (attempt "); + Serial.print(testAttempts); + Serial.print("/"); + Serial.print(maxTestAttempts); + Serial.print(")... "); + + if (nfc.ntag2xx_ReadPage(midPage, testBuffer)) { + Serial.println("✓"); + actualMaxPage = midPage; + lowPage = midPage + 1; // Search higher + } else { + Serial.println("❌"); + highPage = midPage - 1; // Search lower + } + + // Small delay to prevent interface overload + vTaskDelay(5 / portTICK_PERIOD_MS); + yield(); + } + + Serial.print("Found actual max readable page: "); + Serial.println(actualMaxPage); + Serial.print("Search completed in "); + Serial.print(testAttempts); + Serial.println(" attempts"); + + maxWritablePage = actualMaxPage; + } else { + Serial.print("✓ Max page ");Serial.print(maxWritablePage);Serial.println(" is readable"); + } + + // Calculate maximum available user data based on actual writable pages + uint16_t actualUserDataSize = (maxWritablePage - 3) * 4; // -3 because pages 0-3 are header + availableUserData = actualUserDataSize; + + Serial.print("Actual available user data: "); + Serial.print(actualUserDataSize); + Serial.println(" bytes"); + Serial.println("========================"); uint8_t pageBuffer[4] = {0, 0, 0, 0}; Serial.println("Beginne mit dem Schreiben der NDEF-Nachricht..."); // Figure out how long the string is - uint8_t len = strlen(payload); + uint16_t payloadLen = strlen(payload); Serial.print("Länge der Payload: "); - Serial.println(len); + Serial.println(payloadLen); Serial.print("Payload: ");Serial.println(payload); - // Setup the record header - // See NFCForum-TS-Type-2-Tag_1.1.pdf for details - uint8_t pageHeader[21] = { - /* NDEF Message TLV - JSON Record */ - 0x03, /* Tag Field (0x03 = NDEF Message) */ - (uint8_t)(len+3+16), /* Payload Length (including NDEF header) */ - 0xD2, /* NDEF Record Header (TNF=0x2:MIME Media + SR + ME + MB) */ - 0x10, /* Type Length for the record type indicator */ - (uint8_t)(len), /* Payload len */ - 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '/', 'j', 's', 'o', 'n' - }; + // MIME type for JSON + const char mimeType[] = "application/json"; + uint8_t mimeTypeLen = strlen(mimeType); + + // Calculate NDEF record size + uint8_t ndefRecordHeaderSize = 3; // Header byte + Type Length + Payload Length (short record) + uint16_t ndefRecordSize = ndefRecordHeaderSize + mimeTypeLen + payloadLen; + + // Calculate TLV size - need to check if we need extended length format + uint8_t tlvHeaderSize; + uint16_t totalTlvSize; + + if (ndefRecordSize <= 254) { + // Standard TLV format: Tag (1) + Length (1) + Value (ndefRecordSize) + tlvHeaderSize = 2; + totalTlvSize = tlvHeaderSize + ndefRecordSize + 1; // +1 for terminator TLV + } else { + // Extended TLV format: Tag (1) + 0xFF + Length (2) + Value (ndefRecordSize) + tlvHeaderSize = 4; + totalTlvSize = tlvHeaderSize + ndefRecordSize + 1; // +1 for terminator TLV + } - // Make sure the URI payload will fit in dataLen (include 0xFE trailer) - if ((len < 1) || (len + 1 > (tagSize - sizeof(pageHeader)))) - { + Serial.print("NDEF Record Size: "); + Serial.println(ndefRecordSize); + Serial.print("Total TLV Size: "); + Serial.println(totalTlvSize); + + // Check if the message fits in the available user data space + if (totalTlvSize > availableUserData) { Serial.println(); Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!"); - Serial.println("Fehler: Die Nutzlast passt nicht in die Datenlänge."); + Serial.println("FEHLER: Payload zu groß für diesen Tag-Typ!"); + Serial.print("Tag-Typ: ");Serial.println(tagType); + Serial.print("Benötigt: ");Serial.print(totalTlvSize);Serial.println(" Bytes"); + Serial.print("Verfügbar: ");Serial.print(availableUserData);Serial.println(" Bytes"); + Serial.print("Überschuss: ");Serial.print(totalTlvSize - availableUserData);Serial.println(" Bytes"); + + if (tagType == "NTAG213") { + Serial.println("EMPFEHLUNG: Verwenden Sie einen NTAG215 (504 Bytes) oder NTAG216 (888 Bytes) Tag!"); + Serial.println("Oder kürzen Sie die Payload um mindestens " + String(totalTlvSize - availableUserData) + " Bytes."); + } Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!"); Serial.println(); + + oledShowMessage("Tag zu klein für Payload"); + vTaskDelay(3000 / portTICK_PERIOD_MS); return 0; } - // Kombiniere Header und Payload - int totalSize = sizeof(pageHeader) + len; - uint8_t* combinedData = (uint8_t*) malloc(totalSize); - if (combinedData == NULL) - { - Serial.println("Fehler: Nicht genug Speicher vorhanden."); - oledShowMessage("Tag too small"); + Serial.println("✓ Payload passt in den Tag - Schreibvorgang wird fortgesetzt"); + + // STEP 1: NFC Interface Reset and Reinitialization + Serial.println(); + Serial.println("=== SCHRITT 1: NFC-INTERFACE RESET UND NEUINITIALISIERUNG ==="); + + // First, check if the NFC interface is working at all + Serial.println("Teste aktuellen NFC-Interface-Zustand..."); + + // Try to read capability container (which worked during detection) + uint8_t ccTest[4]; + bool ccReadable = nfc.ntag2xx_ReadPage(3, ccTest); + Serial.print("Capability Container (Seite 3) lesbar: "); + Serial.println(ccReadable ? "✓" : "❌"); + + if (!ccReadable) { + Serial.println("❌ NFC-Interface ist nicht funktionsfähig - führe Reset durch"); + + // Perform NFC interface reset and reinitialization + Serial.println("Führe NFC-Interface Reset durch..."); + + // Step 1: Try to reinitialize the NFC interface completely + Serial.println("1. Neuinitialisierung des PN532..."); + + // Reinitialize the PN532 + nfc.begin(); + vTaskDelay(500 / portTICK_PERIOD_MS); // Give it time to initialize + + // Check firmware version to ensure communication is working + uint32_t versiondata = nfc.getFirmwareVersion(); + if (versiondata) { + Serial.print("PN532 Firmware Version: 0x"); + Serial.println(versiondata, HEX); + Serial.println("✓ PN532 Kommunikation wiederhergestellt"); + } else { + Serial.println("❌ PN532 Kommunikation fehlgeschlagen"); + oledShowMessage("NFC Reset failed"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + // Step 2: Reconfigure SAM + Serial.println("2. SAM-Konfiguration..."); + nfc.SAMConfig(); + vTaskDelay(200 / portTICK_PERIOD_MS); + + // Step 3: Re-detect the tag + Serial.println("3. Tag-Wiedererkennung..."); + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uidLength; + bool tagRedetected = false; + + for (int attempts = 0; attempts < 5; attempts++) { + Serial.print("Tag-Erkennungsversuch "); + Serial.print(attempts + 1); + Serial.print("/5... "); + + if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000)) { + Serial.println("✓"); + tagRedetected = true; + break; + } else { + Serial.println("❌"); + vTaskDelay(300 / portTICK_PERIOD_MS); + } + } + + if (!tagRedetected) { + Serial.println("❌ Tag konnte nach Reset nicht wiedererkannt werden"); + oledShowMessage("Tag lost after reset"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.println("✓ Tag erfolgreich wiedererkannt"); + + // Step 4: Test basic page reading + Serial.println("4. Test der Grundfunktionalität..."); + vTaskDelay(200 / portTICK_PERIOD_MS); // Give interface time to stabilize + + ccReadable = nfc.ntag2xx_ReadPage(3, ccTest); + Serial.print("Capability Container nach Reset lesbar: "); + Serial.println(ccReadable ? "✓" : "❌"); + + if (!ccReadable) { + Serial.println("❌ NFC-Interface funktioniert nach Reset immer noch nicht"); + oledShowMessage("NFC still broken"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.println("✓ NFC-Interface erfolgreich wiederhergestellt"); + } else { + Serial.println("✓ NFC-Interface ist funktionsfähig"); + } + + // Display CC content for debugging + if (ccReadable) { + Serial.print("CC Inhalt: "); + for (int i = 0; i < 4; i++) { + if (ccTest[i] < 0x10) Serial.print("0"); + Serial.print(ccTest[i], HEX); + Serial.print(" "); + } + Serial.println(); + } + + Serial.println("=== SCHRITT 2: INTERFACE-FUNKTIONSTEST ==="); + + // Test a few critical pages to ensure stable operation + uint8_t testData[4]; + bool basicPagesReadable = true; + + for (uint8_t testPage = 0; testPage <= 6; testPage++) { + bool readable = nfc.ntag2xx_ReadPage(testPage, testData); + Serial.print("Seite "); + Serial.print(testPage); + Serial.print(": "); + if (readable) { + Serial.print("✓ - "); + for (int i = 0; i < 4; i++) { + if (testData[i] < 0x10) Serial.print("0"); + Serial.print(testData[i], HEX); + Serial.print(" "); + } + Serial.println(); + } else { + Serial.println("❌ - Nicht lesbar"); + if (testPage >= 3 && testPage <= 6) { // Critical pages for NDEF + basicPagesReadable = false; + } + } + vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads + } + + if (!basicPagesReadable) { + Serial.println("❌ KRITISCHER FEHLER: Grundlegende NDEF-Seiten nicht lesbar!"); + Serial.println("Tag oder Interface ist defekt"); + oledShowMessage("Tag/Interface defect"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.println("✓ Alle kritischen Seiten sind lesbar"); + Serial.println("==================================================="); + + Serial.println(); + Serial.println("=== SCHRITT 3: SCHREIBBEREITSCHAFTSTEST ==="); + + // Test write capabilities before attempting the full write + Serial.println("Teste Schreibfähigkeiten des Tags..."); + + uint8_t testPage[4] = {0xAA, 0xBB, 0xCC, 0xDD}; // Test pattern + uint8_t originalPage[4]; // Store original content + + // First, read original content of test page + if (!nfc.ntag2xx_ReadPage(10, originalPage)) { + Serial.println("FEHLER: Kann Testseite nicht lesen für Backup"); + oledShowMessage("Test page read error"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.print("Original Inhalt Seite 10: "); + for (int i = 0; i < 4; i++) { + if (originalPage[i] < 0x10) Serial.print("0"); + Serial.print(originalPage[i], HEX); + Serial.print(" "); + } + Serial.println(); + + // Perform write test + if (!nfc.ntag2xx_WritePage(10, testPage)) { + Serial.println("FEHLER: Schreibtest fehlgeschlagen!"); + Serial.println("Tag ist möglicherweise schreibgeschützt oder defekt"); + + // Additional diagnostics + Serial.println("=== ERWEITERTE SCHREIBTEST-DIAGNOSE ==="); + + // Check if tag is still present + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uidLength; + bool tagStillPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000); + Serial.print("Tag noch erkannt: "); + Serial.println(tagStillPresent ? "✓" : "❌"); + + if (!tagStillPresent) { + Serial.println("URSACHE: Tag wurde während Schreibtest entfernt!"); + oledShowMessage("Tag removed"); + } else { + Serial.println("URSACHE: Tag ist vorhanden aber nicht beschreibbar"); + Serial.println("Möglicherweise: Schreibschutz, Defekt, oder Interface-Problem"); + oledShowMessage("Tag write protected?"); + } + Serial.println("=========================================="); + + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + // Verify test write + uint8_t readBack[4]; + vTaskDelay(20 / portTICK_PERIOD_MS); // Wait for write to complete + + if (!nfc.ntag2xx_ReadPage(10, readBack)) { + Serial.println("FEHLER: Kann Testdaten nicht zurücklesen!"); + oledShowMessage("Test verify failed"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + bool testSuccess = true; + for (int i = 0; i < 4; i++) { + if (readBack[i] != testPage[i]) { + testSuccess = false; + break; + } + } + + if (!testSuccess) { + Serial.println("FEHLER: Schreibtest fehlgeschlagen - Daten stimmen nicht überein!"); + Serial.print("Geschrieben: "); + for (int i = 0; i < 4; i++) { + Serial.print(testPage[i], HEX); Serial.print(" "); + } + Serial.println(); + Serial.print("Gelesen: "); + for (int i = 0; i < 4; i++) { + Serial.print(readBack[i], HEX); Serial.print(" "); + } + Serial.println(); + return 0; + } + + // Restore original content + Serial.println("Stelle ursprünglichen Inhalt wieder her..."); + if (!nfc.ntag2xx_WritePage(10, originalPage)) { + Serial.println("WARNUNG: Konnte ursprünglichen Inhalt nicht wiederherstellen!"); + } else { + Serial.println("✓ Ursprünglicher Inhalt wiederhergestellt"); + } + + Serial.println("✓ Schreibtest erfolgreich - Tag ist voll funktionsfähig"); + Serial.println("======================================================"); + + // STEP 4: NDEF initialization with verification + Serial.println(); + Serial.println("=== SCHRITT 4: NDEF-INITIALISIERUNG ==="); + if (!initializeNdefStructure()) { + Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); + oledShowMessage("NDEF init failed"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + return 0; + } + + // Verify NDEF initialization + uint8_t ndefCheck[8]; + bool ndefVerified = true; + for (uint8_t page = 4; page < 6; page++) { + if (!nfc.ntag2xx_ReadPage(page, &ndefCheck[(page-4)*4])) { + ndefVerified = false; + break; + } + } + + if (ndefVerified) { + Serial.print("NDEF-Header nach Initialisierung: "); + for (int i = 0; i < 8; i++) { + if (ndefCheck[i] < 0x10) Serial.print("0"); + Serial.print(ndefCheck[i], HEX); + Serial.print(" "); + } + Serial.println(); + } + + Serial.println("✓ NDEF-Struktur initialisiert und verifiziert"); + Serial.println("=========================================="); + + // STEP 5: Allow interface to stabilize before major write operation + Serial.println(); + Serial.println("=== SCHRITT 5: NFC-INTERFACE STABILISIERUNG ==="); + Serial.println("Stabilisiere NFC-Interface vor Hauptschreibvorgang..."); + + // Give the interface time to fully settle after NDEF initialization + vTaskDelay(200 / portTICK_PERIOD_MS); + + // Test interface stability with a simple read + uint8_t stabilityTest[4]; + bool interfaceStable = false; + for (int attempts = 0; attempts < 3; attempts++) { + if (nfc.ntag2xx_ReadPage(4, stabilityTest)) { + Serial.print("Interface stability test "); + Serial.print(attempts + 1); + Serial.println("/3: ✓"); + interfaceStable = true; + break; + } else { + Serial.print("Interface stability test "); + Serial.print(attempts + 1); + Serial.println("/3: ❌"); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + } + + if (!interfaceStable) { + Serial.println("FEHLER: NFC-Interface ist nicht stabil genug für Schreibvorgang"); + oledShowMessage("NFC Interface unstable"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.println("✓ NFC-Interface ist stabil - Schreibvorgang kann beginnen"); + Serial.println("========================================================="); + + // Allocate memory for the complete TLV structure + uint8_t* tlvData = (uint8_t*) malloc(totalTlvSize); + if (tlvData == NULL) { + Serial.println("Fehler: Nicht genug Speicher für TLV-Daten vorhanden."); + oledShowMessage("Memory error"); vTaskDelay(2000 / portTICK_PERIOD_MS); return 0; } - // Kombiniere Header und Payload - memcpy(combinedData, pageHeader, sizeof(pageHeader)); - memcpy(&combinedData[sizeof(pageHeader)], payload, len); + // Build TLV structure + uint16_t offset = 0; + + // TLV Header + tlvData[offset++] = 0x03; // NDEF Message TLV Tag + + if (ndefRecordSize <= 254) { + // Standard length format + tlvData[offset++] = (uint8_t)ndefRecordSize; + } else { + // Extended length format + tlvData[offset++] = 0xFF; + tlvData[offset++] = (uint8_t)(ndefRecordSize >> 8); // High byte + tlvData[offset++] = (uint8_t)(ndefRecordSize & 0xFF); // Low byte + } - // Schreibe die Seiten - uint8_t a = 0; - uint8_t i = 0; - while (totalSize > 0) { + // NDEF Record Header + tlvData[offset++] = 0xD2; // NDEF Record Header (TNF=0x2:MIME Media + SR + ME + MB) + tlvData[offset++] = mimeTypeLen; // Type Length + tlvData[offset++] = (uint8_t)payloadLen; // Payload Length (short record format) + + // MIME Type + memcpy(&tlvData[offset], mimeType, mimeTypeLen); + offset += mimeTypeLen; + + // JSON Payload + memcpy(&tlvData[offset], payload, payloadLen); + offset += payloadLen; + + // Terminator TLV + tlvData[offset] = 0xFE; + + Serial.print("Gesamt-TLV-Länge: "); + Serial.println(offset + 1); + + // Debug: Print first 64 bytes of TLV data + Serial.println("TLV Daten (erste 64 Bytes):"); + for (int i = 0; i < min((int)(offset + 1), 64); i++) { + if (tlvData[i] < 0x10) Serial.print("0"); + Serial.print(tlvData[i], HEX); + Serial.print(" "); + if ((i + 1) % 16 == 0) Serial.println(); + } + Serial.println(); + + // Write data to tag pages (starting from page 4) + uint16_t bytesWritten = 0; + uint8_t pageNumber = 4; + uint16_t totalBytes = offset + 1; + + Serial.println(); + Serial.println("=== SCHRITT 6: SCHREIBE NEUE NDEF-DATEN ==="); + Serial.print("Schreibe "); + Serial.print(totalBytes); + Serial.print(" Bytes in "); + Serial.print((totalBytes + 3) / 4); // Round up division + Serial.println(" Seiten..."); + + while (bytesWritten < totalBytes && pageNumber <= maxWritablePage) { + // Additional safety check before writing each page + if (pageNumber > maxWritablePage) { + Serial.print("STOP: Reached maximum writable page "); + Serial.println(maxWritablePage); + break; + } + + // Clear page buffer memset(pageBuffer, 0, 4); - int bytesToWrite = (totalSize < 4) ? totalSize : 4; - memcpy(pageBuffer, combinedData + a, bytesToWrite); + + // Calculate how many bytes to write to this page + uint16_t bytesToWrite = min(4, (int)(totalBytes - bytesWritten)); + + // Copy data to page buffer + memcpy(pageBuffer, &tlvData[bytesWritten], bytesToWrite); - //uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID - //uint8_t uidLength; - //nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 100); + // Write page to tag with retry mechanism + bool writeSuccess = false; + for (int writeAttempt = 0; writeAttempt < 3; writeAttempt++) { + if (nfc.ntag2xx_WritePage(pageNumber, pageBuffer)) { + writeSuccess = true; + break; + } else { + Serial.print("Schreibversuch "); + Serial.print(writeAttempt + 1); + Serial.print("/3 für Seite "); + Serial.print(pageNumber); + Serial.println(" fehlgeschlagen"); + + if (writeAttempt < 2) { + vTaskDelay(50 / portTICK_PERIOD_MS); // Wait before retry + } + } + } - if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer))) - { - Serial.println("Fehler beim Schreiben der Seite."); - free(combinedData); + if (!writeSuccess) { + Serial.print("FEHLER beim Schreiben der Seite "); + Serial.println(pageNumber); + Serial.print("Möglicherweise Page-Limit erreicht für "); + Serial.println(tagType); + Serial.print("Erwartetes Maximum: "); + Serial.println(maxWritablePage); + Serial.print("Tatsächliches Maximum scheint niedriger zu sein!"); + + // Update max page for future operations + if (pageNumber > 4) { + Serial.print("Setze neues Maximum auf Seite "); + Serial.println(pageNumber - 1); + } + + free(tlvData); return 0; } - yield(); - //esp_task_wdt_reset(); + // IMMEDIATE verification after each write - this is critical! + Serial.print("Verifiziere Seite "); + Serial.print(pageNumber); + Serial.print("... "); + + uint8_t verifyBuffer[4]; + vTaskDelay(20 / portTICK_PERIOD_MS); // Increased delay before verification + + // Verification with retry mechanism + bool verifySuccess = false; + for (int verifyAttempt = 0; verifyAttempt < 3; verifyAttempt++) { + if (nfc.ntag2xx_ReadPage(pageNumber, verifyBuffer)) { + bool writeMatches = true; + for (int i = 0; i < bytesToWrite; i++) { + if (verifyBuffer[i] != pageBuffer[i]) { + writeMatches = false; + Serial.println(); + Serial.print("VERIFIKATIONSFEHLER bei Byte "); + Serial.print(i); + Serial.print(" - Erwartet: 0x"); + Serial.print(pageBuffer[i], HEX); + Serial.print(", Gelesen: 0x"); + Serial.println(verifyBuffer[i], HEX); + break; + } + } + + if (writeMatches) { + verifySuccess = true; + break; + } else if (verifyAttempt < 2) { + Serial.print("Verifikationsversuch "); + Serial.print(verifyAttempt + 1); + Serial.println("/3 fehlgeschlagen, wiederhole..."); + vTaskDelay(30 / portTICK_PERIOD_MS); + } + } else { + Serial.print("Verifikations-Read-Versuch "); + Serial.print(verifyAttempt + 1); + Serial.println("/3 fehlgeschlagen"); + if (verifyAttempt < 2) { + vTaskDelay(30 / portTICK_PERIOD_MS); + } + } + } + + if (!verifySuccess) { + Serial.println("❌ SCHREIBVORGANG/VERIFIKATION FEHLGESCHLAGEN!"); + free(tlvData); + return 0; + } else { + Serial.println("✓"); + } - i++; - a += 4; - totalSize -= bytesToWrite; + Serial.print("Seite "); + Serial.print(pageNumber); + Serial.print(" ✓: "); + for (int i = 0; i < 4; i++) { + if (pageBuffer[i] < 0x10) Serial.print("0"); + Serial.print(pageBuffer[i], HEX); + Serial.print(" "); + } + Serial.println(); + + bytesWritten += bytesToWrite; + pageNumber++; + + yield(); + vTaskDelay(10 / portTICK_PERIOD_MS); // Slightly increased delay between page writes } - // Ensure the NDEF message is properly terminated - memset(pageBuffer, 0, 4); - pageBuffer[0] = 0xFE; // NDEF record footer - if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer))) - { - Serial.println("Fehler beim Schreiben des End-Bits."); - free(combinedData); + free(tlvData); + + if (bytesWritten < totalBytes) { + Serial.println("WARNUNG: Nicht alle Daten konnten geschrieben werden!"); + Serial.print("Geschrieben: "); + Serial.print(bytesWritten); + Serial.print(" von "); + Serial.print(totalBytes); + Serial.println(" Bytes"); + Serial.print("Gestoppt bei Seite: "); + Serial.println(pageNumber - 1); return 0; } - - Serial.println("NDEF-Nachricht erfolgreich geschrieben."); - free(combinedData); + + Serial.println(); + Serial.println("✓ NDEF-Nachricht erfolgreich geschrieben!"); + Serial.print("✓ Tag-Typ: ");Serial.println(tagType); + Serial.print("✓ Insgesamt ");Serial.print(bytesWritten);Serial.println(" Bytes geschrieben"); + Serial.print("✓ Verwendete Seiten: 4-");Serial.println(pageNumber - 1); + Serial.print("✓ Speicher-Auslastung: "); + Serial.print((bytesWritten * 100) / availableUserData); + Serial.println("%"); + Serial.println("✓ Bestehende Daten wurden überschrieben"); + + // CRITICAL: Allow NFC interface to stabilize after write operation + Serial.println(); + Serial.println("=== SCHRITT 7: NFC-INTERFACE STABILISIERUNG NACH SCHREIBVORGANG ==="); + Serial.println("Stabilisiere NFC-Interface nach Schreibvorgang..."); + + // Give the tag and interface time to settle after write operation + vTaskDelay(300 / portTICK_PERIOD_MS); // Increased stabilization time + + // Test if the interface is still responsive + uint8_t postWriteTest[4]; + bool interfaceResponsive = false; + + for (int stabilityAttempt = 0; stabilityAttempt < 5; stabilityAttempt++) { + Serial.print("Post-write interface test "); + Serial.print(stabilityAttempt + 1); + Serial.print("/5... "); + + if (nfc.ntag2xx_ReadPage(3, postWriteTest)) { // Read capability container + Serial.println("✓"); + interfaceResponsive = true; + break; + } else { + Serial.println("❌"); + + if (stabilityAttempt < 4) { + Serial.println("Warte und versuche Interface zu stabilisieren..."); + vTaskDelay(200 / portTICK_PERIOD_MS); + + // Try to re-establish communication with a simple tag presence check + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uidLength; + bool tagStillPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000); + Serial.print("Tag presence check: "); + Serial.println(tagStillPresent ? "✓" : "❌"); + + if (!tagStillPresent) { + Serial.println("Tag wurde während/nach Schreibvorgang entfernt!"); + break; + } + } + } + } + + if (!interfaceResponsive) { + Serial.println("WARNUNG: NFC-Interface reagiert nach Schreibvorgang nicht mehr stabil"); + Serial.println("Schreibvorgang war erfolgreich, aber Interface benötigt möglicherweise Reset"); + } else { + Serial.println("✓ NFC-Interface ist nach Schreibvorgang stabil"); + } + + Serial.println("=================================================================="); + return 1; } -bool decodeNdefAndReturnJson(const byte* encodedMessage) { +bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { oledShowProgressBar(1, octoEnabled?5:4, "Reading", "Decoding data"); - byte typeLength = encodedMessage[3]; - byte payloadLength = encodedMessage[4]; + // Debug: Print first 32 bytes of the raw data + Serial.println("Raw NDEF data (first 32 bytes):"); + for (int i = 0; i < 32; i++) { + if (encodedMessage[i] < 0x10) Serial.print("0"); + Serial.print(encodedMessage[i], HEX); + Serial.print(" "); + if ((i + 1) % 16 == 0) Serial.println(); + } + Serial.println(); + + // Look for the NDEF TLV structure starting from the beginning + int tlvOffset = 0; + bool foundNdefTlv = false; + + // Search for NDEF TLV (0x03) in the first few bytes + for (int i = 0; i < 16; i++) { + if (encodedMessage[i] == 0x03) { + tlvOffset = i; + foundNdefTlv = true; + Serial.print("Found NDEF TLV at offset: "); + Serial.println(tlvOffset); + break; + } + } + + if (!foundNdefTlv) { + Serial.println("No NDEF TLV found in tag data"); + return false; + } + + // Get the NDEF message length from TLV + uint16_t ndefMessageLength = 0; + int ndefRecordOffset = 0; + + if (encodedMessage[tlvOffset + 1] == 0xFF) { + // Extended length format: next 2 bytes contain the actual length + ndefMessageLength = (encodedMessage[tlvOffset + 2] << 8) | encodedMessage[tlvOffset + 3]; + ndefRecordOffset = tlvOffset + 4; // Skip TLV tag + 0xFF + 2 length bytes + Serial.print("NDEF Message Length (extended): "); + } else { + // Standard length format: single byte contains the length + ndefMessageLength = encodedMessage[tlvOffset + 1]; + ndefRecordOffset = tlvOffset + 2; // Skip TLV tag + 1 length byte + Serial.print("NDEF Message Length (standard): "); + } + Serial.println(ndefMessageLength); + + // Get pointer to NDEF record + const byte* ndefRecord = &encodedMessage[ndefRecordOffset]; + + // Parse NDEF record header + byte recordHeader = ndefRecord[0]; + byte typeLength = ndefRecord[1]; + + Serial.print("NDEF Record Header: 0x"); + Serial.println(recordHeader, HEX); + Serial.print("Type Length: "); + Serial.println(typeLength); + + // Determine payload length (can be 1 or 4 bytes depending on SR flag) + uint32_t payloadLength = 0; + byte payloadLengthBytes = 1; + byte payloadLengthOffset = 2; + + // Check if Short Record (SR) flag is set (bit 4) + if (recordHeader & 0x10) { // SR flag + payloadLength = ndefRecord[2]; + payloadLengthBytes = 1; + payloadLengthOffset = 2; + } else { + // Long record format (4 bytes for payload length) + payloadLength = (ndefRecord[2] << 24) | (ndefRecord[3] << 16) | + (ndefRecord[4] << 8) | ndefRecord[5]; + payloadLengthBytes = 4; + payloadLengthOffset = 2; + } + + Serial.print("Payload Length: "); + Serial.println(payloadLength); + Serial.print("Payload Length Bytes: "); + Serial.println(payloadLengthBytes); + + // Check for ID field (if IL flag is set) + byte idLength = 0; + if (recordHeader & 0x08) { // IL flag + idLength = ndefRecord[payloadLengthOffset + payloadLengthBytes]; + Serial.print("ID Length: "); + Serial.println(idLength); + } + + // Calculate offset to payload + byte payloadOffset = 1 + 1 + payloadLengthBytes + typeLength + idLength; + + Serial.print("Calculated payload offset: "); + Serial.println(payloadOffset); + + // Verify we have enough data + if (payloadOffset + payloadLength > ndefMessageLength) { + Serial.println("Invalid NDEF structure - payload extends beyond message"); + Serial.print("Payload offset + length: "); + Serial.print(payloadOffset + payloadLength); + Serial.print(", NDEF message length: "); + Serial.println(ndefMessageLength); + return false; + } + + // Print the record type for debugging + Serial.print("Record Type: "); + for (int i = 0; i < typeLength; i++) { + Serial.print((char)ndefRecord[1 + 1 + payloadLengthBytes + i]); + } + Serial.println(); nfcJsonData = ""; - for (int i = 2; i < payloadLength+2; i++) - { - nfcJsonData += (char)encodedMessage[3 + typeLength + i]; + // Extract JSON payload with validation + uint32_t actualJsonLength = 0; + for (uint32_t i = 0; i < payloadLength; i++) { + byte currentByte = ndefRecord[payloadOffset + i]; + + // Stop at null terminator or if we find the end of JSON + if (currentByte == 0x00) { + Serial.print("Found null terminator at position: "); + Serial.println(i); + break; + } + + // Only add printable characters and common JSON characters + if (currentByte >= 32 && currentByte <= 126) { + nfcJsonData += (char)currentByte; + actualJsonLength++; + } else { + Serial.print("Skipping non-printable byte at position "); + Serial.print(i); + Serial.print(": 0x"); + Serial.println(currentByte, HEX); + } + + // Check if we've reached the end of a JSON object + if (currentByte == '}') { + // Count opening and closing braces to detect complete JSON + int braceCount = 0; + for (uint32_t j = 0; j <= i; j++) { + if (ndefRecord[payloadOffset + j] == '{') braceCount++; + else if (ndefRecord[payloadOffset + j] == '}') braceCount--; + } + + if (braceCount == 0) { + Serial.print("Found complete JSON object at position: "); + Serial.println(i); + actualJsonLength = i + 1; + break; + } + } } + Serial.print("Actual JSON length extracted: "); + Serial.println(actualJsonLength); + Serial.print("Total nfcJsonData length: "); + Serial.println(nfcJsonData.length()); + Serial.println("=== DECODED JSON DATA START ==="); + Serial.println(nfcJsonData); + Serial.println("=== DECODED JSON DATA END ==="); + + // Check if JSON was truncated + if (nfcJsonData.length() < payloadLength && !nfcJsonData.endsWith("}")) { + Serial.println("WARNING: JSON payload appears to be truncated!"); + Serial.print("Expected payload length: "); + Serial.println(payloadLength); + Serial.print("Actual extracted length: "); + Serial.println(nfcJsonData.length()); + } + + // Trim any trailing whitespace or invalid characters + nfcJsonData.trim(); + // JSON-Dokument verarbeiten - JsonDocument doc; // Passen Sie die Größe an den JSON-Inhalt an + JsonDocument doc; DeserializationError error = deserializeJson(doc, nfcJsonData); if (error) { @@ -235,7 +1253,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { // Sende die aktualisierten AMS-Daten an alle WebSocket-Clients Serial.println("JSON-Dokument erfolgreich verarbeitet"); Serial.println(doc.as()); - if (doc["sm_id"].is() && doc["sm_id"] != "") + if (doc["sm_id"].is() && doc["sm_id"] != "" && doc["sm_id"] != "0") { oledShowProgressBar(2, octoEnabled?5:4, "Spool Tag", "Weighing"); Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); @@ -255,6 +1273,16 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { oledShowProgressBar(1, 1, "Failure", "Scan spool first"); } } + // Brand Filament not registered to Spoolman + else if ((!doc["sm_id"].is() || (doc["sm_id"].is() && (doc["sm_id"] == "0" || doc["sm_id"] == ""))) + && doc["b"].is() && doc["an"].is()) + { + doc["sm_id"] = "0"; // Ensure sm_id is set to 0 + // If no sm_id is present but the brand is Brand Filament then + // create a new spool, maybe brand too, in Spoolman + Serial.println("New Brand Filament Tag found!"); + createBrandFilament(doc, uidString); + } else { Serial.println("Keine SPOOL-ID gefunden."); @@ -271,6 +1299,289 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { return true; } +// Read complete JSON data for fast-path to enable web interface display +bool readCompleteJsonForFastPath() { + Serial.println("=== FAST-PATH: Reading complete JSON for web interface ==="); + + // Read tag size first + uint16_t tagSize = readTagSize(); + if (tagSize == 0) { + Serial.println("FAST-PATH: Could not determine tag size"); + return false; + } + + // Create buffer for complete data + uint8_t* data = (uint8_t*)malloc(tagSize); + if (!data) { + Serial.println("FAST-PATH: Could not allocate memory for complete read"); + return false; + } + memset(data, 0, tagSize); + + // Read all pages + uint8_t numPages = tagSize / 4; + for (uint8_t i = 4; i < 4 + numPages; i++) { + if (!robustPageRead(i, data + (i - 4) * 4)) { + Serial.printf("FAST-PATH: Failed to read page %d\n", i); + free(data); + return false; + } + + // Check for NDEF message end + if (data[(i - 4) * 4] == 0xFE) { + Serial.println("FAST-PATH: Found NDEF message end marker"); + break; + } + + yield(); + esp_task_wdt_reset(); + vTaskDelay(pdMS_TO_TICKS(2)); + } + + // Decode NDEF and extract JSON + bool success = decodeNdefAndReturnJson(data, ""); // Empty UID string for fast-path + + free(data); + + if (success) { + Serial.println("✓ FAST-PATH: Complete JSON data successfully loaded"); + Serial.print("nfcJsonData length: "); + Serial.println(nfcJsonData.length()); + } else { + Serial.println("✗ FAST-PATH: Failed to decode complete JSON data"); + } + + return success; +} + +bool quickSpoolIdCheck(String uidString) { + // Fast-path: Read NDEF structure to quickly locate and check JSON payload + // This dramatically speeds up known spool recognition + + // CRITICAL: Do not execute during write operations! + if (nfcWriteInProgress) { + Serial.println("FAST-PATH: Skipped during write operation"); + return false; + } + + Serial.println("=== FAST-PATH: Quick sm_id Check ==="); + + // Read enough pages to cover NDEF header + beginning of payload (pages 4-8 = 20 bytes) + uint8_t ndefData[20]; + memset(ndefData, 0, 20); + + for (uint8_t page = 4; page < 9; page++) { + if (!robustPageRead(page, ndefData + (page - 4) * 4)) { + Serial.print("FAST-PATH: Failed to read page "); + Serial.print(page); + Serial.println(" - falling back to full read"); + return false; // Fall back to full read if any page read fails + } + } + + // Parse NDEF structure to find JSON payload start + Serial.print("Raw NDEF data (first 20 bytes): "); + for (int i = 0; i < 20; i++) { + if (ndefData[i] < 0x10) Serial.print("0"); + Serial.print(ndefData[i], HEX); + Serial.print(" "); + } + Serial.println(); + + // Look for NDEF TLV (0x03) at the beginning + int tlvOffset = -1; + for (int i = 0; i < 8; i++) { + if (ndefData[i] == 0x03) { + tlvOffset = i; + Serial.print("Found NDEF TLV at offset: "); + Serial.println(tlvOffset); + break; + } + } + + if (tlvOffset == -1) { + Serial.println("✗ FAST-PATH: No NDEF TLV found"); + return false; + } + + // Parse NDEF record to find JSON payload + int ndefRecordStart; + if (ndefData[tlvOffset + 1] == 0xFF) { + // Extended length format + ndefRecordStart = tlvOffset + 4; + } else { + // Standard length format + ndefRecordStart = tlvOffset + 2; + } + + if (ndefRecordStart >= 20) { + Serial.println("✗ FAST-PATH: NDEF record starts beyond read data"); + return false; + } + + // Parse NDEF record header + uint8_t recordHeader = ndefData[ndefRecordStart]; + uint8_t typeLength = ndefData[ndefRecordStart + 1]; + + // Calculate payload offset + uint8_t payloadLengthBytes = (recordHeader & 0x10) ? 1 : 4; // SR flag check + uint8_t idLength = (recordHeader & 0x08) ? ndefData[ndefRecordStart + 2 + payloadLengthBytes + typeLength] : 0; // IL flag check + + int payloadOffset = ndefRecordStart + 1 + 1 + payloadLengthBytes + typeLength + idLength; + + Serial.print("NDEF Record Header: 0x"); + Serial.print(recordHeader, HEX); + Serial.print(", Type Length: "); + Serial.print(typeLength); + Serial.print(", Payload offset: "); + Serial.println(payloadOffset); + + // Check if payload starts within our read data + if (payloadOffset >= 20) { + Serial.println("✗ FAST-PATH: JSON payload starts beyond quick read data - need more pages"); + + // Read additional pages to get to JSON payload + uint8_t extraData[16]; // Read 4 more pages + memset(extraData, 0, 16); + + for (uint8_t page = 9; page < 13; page++) { + if (!robustPageRead(page, extraData + (page - 9) * 4)) { + Serial.print("FAST-PATH: Failed to read additional page "); + Serial.print(page); + Serial.println(" - falling back to full read"); + return false; // Fall back to full read if extended read fails + } + } + + // Combine data + uint8_t combinedData[36]; + memcpy(combinedData, ndefData, 20); + memcpy(combinedData + 20, extraData, 16); + + // Extract JSON from combined data + String jsonStart = ""; + int jsonStartPos = payloadOffset; + for (int i = 0; i < 36 - payloadOffset && i < 30; i++) { + uint8_t currentByte = combinedData[payloadOffset + i]; + if (currentByte >= 32 && currentByte <= 126) { + jsonStart += (char)currentByte; + } + // Stop at first brace to get just the beginning + if (currentByte == '{' && i > 0) break; + } + + Serial.print("JSON start from extended read: "); + Serial.println(jsonStart); + + // Check for sm_id pattern - look for non-zero sm_id values + if (jsonStart.indexOf("\"sm_id\":\"") >= 0) { + int smIdStart = jsonStart.indexOf("\"sm_id\":\"") + 9; + int smIdEnd = jsonStart.indexOf("\"", smIdStart); + + if (smIdEnd > smIdStart && smIdEnd < jsonStart.length()) { + String quickSpoolId = jsonStart.substring(smIdStart, smIdEnd); + Serial.print("Found sm_id in extended read: "); + Serial.println(quickSpoolId); + + // Only process if sm_id is not "0" (known spool) + if (quickSpoolId != "0" && quickSpoolId.length() > 0) { + Serial.println("✓ FAST-PATH: Known spool detected!"); + + // Set as active spool immediately + activeSpoolId = quickSpoolId; + lastSpoolId = activeSpoolId; + + // Read complete JSON data for web interface display + Serial.println("FAST-PATH: Reading complete JSON data for web interface..."); + if (readCompleteJsonForFastPath()) { + Serial.println("✓ FAST-PATH: Complete JSON data loaded for web interface"); + } else { + Serial.println("⚠ FAST-PATH: Could not read complete JSON, web interface may show limited data"); + } + + oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); + Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); + return true; + } else { + Serial.println("✗ FAST-PATH: sm_id is 0 - new brand filament, need full read"); + return false; + } + } + } + + Serial.println("✗ FAST-PATH: No sm_id pattern in extended read"); + return false; + } + + // Extract JSON payload from the available data + String quickJson = ""; + for (int i = payloadOffset; i < 20 && i < payloadOffset + 15; i++) { + uint8_t currentByte = ndefData[i]; + if (currentByte >= 32 && currentByte <= 126) { + quickJson += (char)currentByte; + } + } + + Serial.print("Quick JSON data: "); + Serial.println(quickJson); + + // Look for sm_id pattern in the beginning of JSON - check for known vs new spools + if (quickJson.indexOf("\"sm_id\":\"") >= 0) { + Serial.println("✓ FAST-PATH: sm_id field found"); + + // Extract sm_id from quick data + int smIdStart = quickJson.indexOf("\"sm_id\":\"") + 9; + int smIdEnd = quickJson.indexOf("\"", smIdStart); + + if (smIdEnd > smIdStart && smIdEnd < quickJson.length()) { + String quickSpoolId = quickJson.substring(smIdStart, smIdEnd); + Serial.print("✓ Quick extracted sm_id: "); + Serial.println(quickSpoolId); + + // Only process known spools (sm_id != "0") via fast path + if (quickSpoolId != "0" && quickSpoolId.length() > 0) { + Serial.println("✓ FAST-PATH: Known spool detected!"); + + // Set as active spool immediately + activeSpoolId = quickSpoolId; + lastSpoolId = activeSpoolId; + + // Read complete JSON data for web interface display + Serial.println("FAST-PATH: Reading complete JSON data for web interface..."); + if (readCompleteJsonForFastPath()) { + Serial.println("✓ FAST-PATH: Complete JSON data loaded for web interface"); + } else { + Serial.println("⚠ FAST-PATH: Could not read complete JSON, web interface may show limited data"); + } + + oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); + Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); + return true; + } else { + Serial.println("✗ FAST-PATH: sm_id is 0 - new brand filament, need full read"); + return false; // sm_id="0" means new brand filament, needs full processing + } + } else { + Serial.println("✗ FAST-PATH: Could not extract complete sm_id value"); + return false; // Need full read to get complete sm_id + } + } + + // Check for other patterns that require full read + if (quickJson.indexOf("\"location\":\"") >= 0) { + Serial.println("✓ FAST-PATH: Location tag detected"); + return false; // Need full read for location processing + } + + if (quickJson.indexOf("\"brand\":\"") >= 0) { + Serial.println("✓ FAST-PATH: Brand filament detected - may need full processing"); + return false; // Need full read for brand filament creation + } + + Serial.println("✗ FAST-PATH: No recognizable pattern - falling back to full read"); + return false; // Fall back to full tag reading +} + void writeJsonToTag(void *parameter) { NfcWriteParameterType* params = (NfcWriteParameterType*)parameter; @@ -279,17 +1590,20 @@ void writeJsonToTag(void *parameter) { Serial.println(params->payload); nfcReaderState = NFC_WRITING; + nfcWriteInProgress = true; // Block high-level tag operations during write - // First request the reading task to be suspended and than wait until it responds - nfcReadingTaskSuspendRequest = true; - while(nfcReadingTaskSuspendState == false){ - vTaskDelay(100 / portTICK_PERIOD_MS); - } + // Do NOT suspend the reading task - we need NFC interface for verification + // Just use nfcWriteInProgress to prevent scanning and fast-path operations + Serial.println("NFC Write Task starting - High-level operations blocked, low-level NFC available"); //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert sendNfcData(); vTaskDelay(100 / portTICK_PERIOD_MS); + + // Show waiting message for tag detection + oledShowProgressBar(0, 1, "Write Tag", "Warte auf Tag"); + // Wait 10sec for tag uint8_t success = 0; String uidString = ""; @@ -336,20 +1650,110 @@ void writeJsonToTag(void *parameter) { if(params->tagType){ // TBD: should this be simplified? if (updateSpoolTagId(uidString, params->payload) && params->tagType) { - + // Check if weight is over 20g and send to Spoolman + if (weight > 20) { + Serial.println("Tag successfully written and weight > 20g - sending weight to Spoolman"); + + // Extract spool ID from payload for weight update + JsonDocument payloadDoc; + DeserializationError error = deserializeJson(payloadDoc, params->payload); + + if (!error && payloadDoc["sm_id"].is()) { + String spoolId = payloadDoc["sm_id"].as(); + if (spoolId != "") { + Serial.printf("Updating spool %s with weight %dg\n", spoolId.c_str(), weight); + updateSpoolWeight(spoolId, weight); + } else { + Serial.println("No valid spool ID found for weight update"); + } + } else { + Serial.println("Error parsing payload for spool ID extraction"); + } + + payloadDoc.clear(); + } else { + Serial.printf("Weight %dg is not above 20g threshold - skipping weight update\n", weight); + } }else{ // Potentially handle errors } }else{ oledShowProgressBar(1, 1, "Write Tag", "Done!"); } - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + + // CRITICAL: Properly stabilize NFC interface after write operation + Serial.println(); + Serial.println("=== POST-WRITE NFC STABILIZATION ==="); + + // Wait for tag operations to complete + vTaskDelay(500 / portTICK_PERIOD_MS); + + // Test tag presence and remove detection + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; uint8_t uidLength; - yield(); - esp_task_wdt_reset(); - while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400)) { + int tagRemovalChecks = 0; + + Serial.println("Warte bis Tag entfernt wird..."); + + // Monitor tag presence + while (tagRemovalChecks < 10) { yield(); - } + esp_task_wdt_reset(); + + bool tagPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500); + + if (!tagPresent) { + Serial.println("✓ Tag wurde entfernt - NFC bereit für nächsten Scan"); + break; + } + + tagRemovalChecks++; + Serial.print("Tag noch vorhanden ("); + Serial.print(tagRemovalChecks); + Serial.println("/10)"); + + vTaskDelay(500 / portTICK_PERIOD_MS); + } + + if (tagRemovalChecks >= 10) { + Serial.println("WARNUNG: Tag wurde nicht entfernt - fahre trotzdem fort"); + } + + // Additional interface stabilization before resuming normal operations + Serial.println("Stabilisiere NFC-Interface für normale Operationen..."); + vTaskDelay(200 / portTICK_PERIOD_MS); + + // Test if interface is ready for normal scanning + uint8_t interfaceTestBuffer[4]; + bool interfaceReady = false; + + for (int testAttempt = 0; testAttempt < 3; testAttempt++) { + // Try a simple interface operation (without requiring tag presence) + Serial.print("Interface readiness test "); + Serial.print(testAttempt + 1); + Serial.print("/3... "); + + // Use a safe read operation that doesn't depend on tag presence + // This tests if the PN532 chip itself is responsive + uint32_t versiondata = nfc.getFirmwareVersion(); + if (versiondata != 0) { + Serial.println("✓"); + interfaceReady = true; + break; + } else { + Serial.println("❌"); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + } + + if (!interfaceReady) { + Serial.println("WARNUNG: NFC-Interface reagiert nicht - könnte normale Scans beeinträchtigen"); + } else { + Serial.println("✓ NFC-Interface ist bereit für normale Scans"); + } + + Serial.println("========================================="); + vTaskResume(RfidReaderTask); vTaskDelay(500 / portTICK_PERIOD_MS); } @@ -372,16 +1776,70 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - nfcReadingTaskSuspendRequest = false; + // Only reset the write protection flag - reading task was never suspended + nfcWriteInProgress = false; // Re-enable high-level tag operations pauseBambuMqttTask = false; + free(params->payload); + delete params; + vTaskDelete(NULL); } +// Ensures sm_id is always the first key in JSON for fast-path detection +String optimizeJsonForFastPath(const char* payload) { + JsonDocument inputDoc; + DeserializationError error = deserializeJson(inputDoc, payload); + + if (error) { + Serial.print("JSON optimization failed: "); + Serial.println(error.c_str()); + return String(payload); // Return original if parsing fails + } + + // Create optimized JSON with sm_id first + JsonDocument optimizedDoc; + + // Always add sm_id first (even if it's "0" for brand filaments) + if (inputDoc["sm_id"].is()) { + optimizedDoc["sm_id"] = inputDoc["sm_id"].as(); + Serial.print("Optimizing JSON: sm_id found = "); + Serial.println(inputDoc["sm_id"].as()); + } else { + optimizedDoc["sm_id"] = "0"; // Default for brand filaments + Serial.println("Optimizing JSON: No sm_id found, setting to '0'"); + } + + // Add all other keys in original order + for (JsonPair kv : inputDoc.as()) { + String key = kv.key().c_str(); + if (key != "sm_id") { // Skip sm_id as it's already added first + optimizedDoc[key] = kv.value(); + } + } + + String optimizedJson; + serializeJson(optimizedDoc, optimizedJson); + + Serial.println("JSON optimized for fast-path detection:"); + Serial.print("Original: "); + Serial.println(payload); + Serial.print("Optimized: "); + Serial.println(optimizedJson); + + inputDoc.clear(); + optimizedDoc.clear(); + + return optimizedJson; +} + void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { + // Optimize JSON to ensure sm_id is first key for fast-path detection + String optimizedPayload = optimizeJsonForFastPath(payload); + NfcWriteParameterType* parameters = new NfcWriteParameterType(); parameters->tagType = isSpoolTag; - parameters->payload = strdup(payload); + parameters->payload = strdup(optimizedPayload.c_str()); // Use optimized payload // Task nicht mehrfach starten if (nfcReaderState == NFC_IDLE || nfcReaderState == NFC_READ_ERROR || nfcReaderState == NFC_READ_SUCCESS) { @@ -401,11 +1859,46 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { } } +// Safe tag detection with manual retry logic and short timeouts +bool safeTagDetection(uint8_t* uid, uint8_t* uidLength) { + const int MAX_ATTEMPTS = 3; + const int SHORT_TIMEOUT = 100; // Very short timeout to prevent hanging + + for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { + // Watchdog reset on each attempt + esp_task_wdt_reset(); + yield(); + + // Use short timeout to avoid blocking + bool success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, uidLength, SHORT_TIMEOUT); + + if (success) { + Serial.printf("✓ Tag detected on attempt %d with %dms timeout\n", attempt + 1, SHORT_TIMEOUT); + return true; + } + + // Short pause between attempts + vTaskDelay(pdMS_TO_TICKS(25)); + + // Refresh RF field after failed attempt (but not on last attempt) + if (attempt < MAX_ATTEMPTS - 1) { + nfc.SAMConfig(); + vTaskDelay(pdMS_TO_TICKS(10)); + } + } + + return false; +} + void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { - // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest && !booting) + // Regular watchdog reset + esp_task_wdt_reset(); + yield(); + + // Skip scanning during write operations, but keep NFC interface active + if (nfcReaderState != NFC_WRITING && !nfcWriteInProgress && !nfcReadingTaskSuspendRequest && !booting) { nfcReadingTaskSuspendState = false; yield(); @@ -414,10 +1907,16 @@ void scanRfidTask(void * parameter) { uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; - success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500); + // Use safe tag detection instead of blocking readPassiveTargetID + success = safeTagDetection(uid, &uidLength); foundNfcTag(nullptr, success); + // Reset activeSpoolId immediately when no tag is detected to prevent stale autoSet + if (!success) { + activeSpoolId = ""; + } + // As long as there is still a tag on the reader, do not try to read it again if (success && nfcReaderState == NFC_IDLE) { @@ -431,10 +1930,34 @@ void scanRfidTask(void * parameter) { oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); - //vTaskDelay(500 / portTICK_PERIOD_MS); + // Reduced stabilization time for better responsiveness + Serial.println("Tag detected, minimal stabilization..."); + vTaskDelay(200 / portTICK_PERIOD_MS); // Reduced from 1000ms to 200ms + + // create Tag UID string + String uidString = ""; + for (uint8_t i = 0; i < uidLength; i++) { + //TBD: Rework to remove all the string operations + uidString += String(uid[i], HEX); + if (i < uidLength - 1) { + uidString += ":"; // Optional: Trennzeichen hinzufügen + } + } if (uidLength == 7) { + // Try fast-path detection first for known spools + if (quickSpoolIdCheck(uidString)) { + Serial.println("✓ FAST-PATH: Tag processed quickly, skipping full read"); + pauseBambuMqttTask = false; + // Set reader back to idle for next scan + nfcReaderState = NFC_READ_SUCCESS; + delay(500); // Small delay before next scan + continue; // Skip full tag reading and continue scan loop + } + + Serial.println("Continuing with full tag read after fast-path check"); + uint16_t tagSize = readTagSize(); if(tagSize > 0) { @@ -444,25 +1967,36 @@ void scanRfidTask(void * parameter) { // We probably have an NTAG2xx card (though it could be Ultralight as well) Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); + Serial.print("Tag size: "); + Serial.print(tagSize); + Serial.println(" bytes"); uint8_t numPages = readTagSize()/4; + for (uint8_t i = 4; i < 4+numPages; i++) { - if (!nfc.ntag2xx_ReadPage(i, data+(i-4) * 4)) + + if (!robustPageRead(i, data+(i-4) * 4)) { - break; // Stop if reading fails + Serial.printf("Failed to read page %d after retries, stopping\n", i); + break; // Stop if reading fails after retries } + // Check for NDEF message end if (data[(i - 4) * 4] == 0xFE) { + Serial.println("Found NDEF message end marker"); break; // End of NDEF message } yield(); esp_task_wdt_reset(); - vTaskDelay(pdMS_TO_TICKS(1)); + // Reduced delay for faster reading + vTaskDelay(pdMS_TO_TICKS(2)); // Reduced from 5ms to 2ms } - - if (!decodeNdefAndReturnJson(data)) + + Serial.println("Tag reading completed, starting NDEF decode..."); + + if (!decodeNdefAndReturnJson(data, uidString)) { oledShowProgressBar(1, 1, "Failure", "Unknown tag"); nfcReaderState = NFC_READ_ERROR; @@ -478,6 +2012,9 @@ void scanRfidTask(void * parameter) { { oledShowProgressBar(1, 1, "Failure", "Tag read error"); nfcReaderState = NFC_READ_ERROR; + // Reset activeSpoolId when tag reading fails to prevent autoSet + activeSpoolId = ""; + Serial.println("Tag read failed - activeSpoolId reset to prevent autoSet"); } } else @@ -485,6 +2022,9 @@ void scanRfidTask(void * parameter) { //TBD: Show error here?! oledShowProgressBar(1, 1, "Failure", "Unkown tag type"); Serial.println("This doesn't seem to be an NTAG2xx tag (UUID length != 7 bytes)!"); + // Reset activeSpoolId when tag type is unknown to prevent autoSet + activeSpoolId = ""; + Serial.println("Unknown tag type - activeSpoolId reset to prevent autoSet"); } } @@ -497,6 +2037,21 @@ void scanRfidTask(void * parameter) { Serial.println("Tag entfernt"); if (!bambuCredentials.autosend_enable) oledShowWeight(weight); } + // Reset state after successful read when tag is removed + else if (!success && nfcReaderState == NFC_READ_SUCCESS) + { + nfcReaderState = NFC_IDLE; + Serial.println("Tag nach erfolgreichem Lesen entfernt - bereit für nächsten Tag"); + } + + // Add a pause after successful reading to prevent immediate re-reading + if (nfcReaderState == NFC_READ_SUCCESS) { + Serial.println("Tag erfolgreich gelesen - warte 3 Sekunden vor nächstem Scan"); + vTaskDelay(3000 / portTICK_PERIOD_MS); // Reduced from 5 seconds to 3 seconds + } else { + // Faster scanning when no tag or idle state + vTaskDelay(150 / portTICK_PERIOD_MS); // Faster scan interval + } // aktualisieren der Website wenn sich der Status ändert sendNfcData(); @@ -504,8 +2059,17 @@ void scanRfidTask(void * parameter) { else { nfcReadingTaskSuspendState = true; - Serial.println("NFC Reading disabled"); - vTaskDelay(1000 / portTICK_PERIOD_MS); + + // Different behavior for write protection vs. full suspension + if (nfcWriteInProgress) { + // During write: Just pause scanning, don't disable NFC interface + // Serial.println("NFC Scanning paused during write operation"); + vTaskDelay(100 / portTICK_PERIOD_MS); // Shorter delay during write + } else { + // Full suspension requested + Serial.println("NFC Reading disabled"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } } yield(); } diff --git a/src/nfc.h b/src/nfc.h index 2c3d5f3..57381e2 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -16,6 +16,8 @@ typedef enum{ void startNfc(); void scanRfidTask(void * parameter); void startWriteJsonToTag(const bool isSpoolTag, const char* payload); +bool quickSpoolIdCheck(String uidString); +bool readCompleteJsonForFastPath(); // Read complete JSON data for fast-path web interface display extern TaskHandle_t RfidReaderTask; extern String nfcJsonData; @@ -23,6 +25,7 @@ extern String activeSpoolId; extern String lastSpoolId; extern volatile nfcReaderStateType nfcReaderState; extern volatile bool pauseBambuMqttTask; +extern volatile bool nfcWriteInProgress; extern bool tagProcessed; diff --git a/src/scale.cpp b/src/scale.cpp index 201618d..699df9d 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -13,7 +13,22 @@ TaskHandle_t ScaleTask; int16_t weight = 0; -uint8_t weigthCouterToApi = 0; +// Weight stabilization variables +#define MOVING_AVERAGE_SIZE 8 // Reduced from 20 to 8 for faster response +#define LOW_PASS_ALPHA 0.3f // Increased from 0.15 to 0.3 for faster tracking +#define DISPLAY_THRESHOLD 0.3f // Reduced from 0.5 to 0.3g for more responsive display +#define API_THRESHOLD 1.5f // Reduced from 2.0 to 1.5g for faster API actions +#define MEASUREMENT_INTERVAL_MS 30 // Reduced from 50ms to 30ms for faster updates + +float weightBuffer[MOVING_AVERAGE_SIZE]; +uint8_t bufferIndex = 0; +bool bufferFilled = false; +float filteredWeight = 0.0f; +int16_t lastDisplayedWeight = 0; +int16_t lastStableWeight = 0; // For API/action triggering +unsigned long lastMeasurementTime = 0; + +uint8_t weightCounterToApi = 0; uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; uint8_t pauseMainTask = 0; @@ -21,6 +36,93 @@ bool scaleCalibrated; bool autoTare = true; bool scaleCalibrationActive = false; +// ##### Weight stabilization functions ##### + +/** + * Reset weight filter buffer - call after tare or calibration + */ +void resetWeightFilter() { + bufferIndex = 0; + bufferFilled = false; + filteredWeight = 0.0f; + lastDisplayedWeight = 0; + lastStableWeight = 0; // Reset stable weight for API actions + + // Initialize buffer with zeros + for (int i = 0; i < MOVING_AVERAGE_SIZE; i++) { + weightBuffer[i] = 0.0f; + } +} + +/** + * Calculate moving average from weight buffer + */ +float calculateMovingAverage() { + float sum = 0.0f; + int count = bufferFilled ? MOVING_AVERAGE_SIZE : bufferIndex; + + for (int i = 0; i < count; i++) { + sum += weightBuffer[i]; + } + + return (count > 0) ? sum / count : 0.0f; +} + +/** + * Apply low-pass filter to smooth weight readings + * Uses exponential smoothing: y_new = alpha * x_new + (1-alpha) * y_old + */ +float applyLowPassFilter(float newValue) { + filteredWeight = LOW_PASS_ALPHA * newValue + (1.0f - LOW_PASS_ALPHA) * filteredWeight; + return filteredWeight; +} + +/** + * Process new weight reading with stabilization + * Returns stabilized weight value + */ +int16_t processWeightReading(float rawWeight) { + // Add to moving average buffer + weightBuffer[bufferIndex] = rawWeight; + bufferIndex = (bufferIndex + 1) % MOVING_AVERAGE_SIZE; + + if (bufferIndex == 0) { + bufferFilled = true; + } + + // Calculate moving average + float avgWeight = calculateMovingAverage(); + + // Apply low-pass filter + float smoothedWeight = applyLowPassFilter(avgWeight); + + // Round to nearest gram + int16_t newWeight = round(smoothedWeight); + + // Update displayed weight if display threshold is reached + if (abs(newWeight - lastDisplayedWeight) >= DISPLAY_THRESHOLD) { + lastDisplayedWeight = newWeight; + } + + // Update global weight for API actions only if stable threshold is reached + int16_t weightToReturn = weight; // Default: keep current weight + + if (abs(newWeight - lastStableWeight) >= API_THRESHOLD) { + lastStableWeight = newWeight; + weightToReturn = newWeight; + } + + return weightToReturn; +} + +/** + * Get current filtered weight for display purposes + * This returns the smoothed weight even if it hasn't triggered API actions + */ +int16_t getFilteredDisplayWeight() { + return lastDisplayedWeight; +} + // ##### Funktionen für Waage ##### uint8_t setAutoTare(bool autoTareValue) { Serial.print("Set AutoTare to "); @@ -39,6 +141,7 @@ uint8_t setAutoTare(bool autoTareValue) { uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); + resetWeightFilter(); return 1; } @@ -48,37 +151,66 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); + //scaleTareRequest == true; + // Initialize weight filter + resetWeightFilter(); + lastMeasurementTime = millis(); + for(;;) { - if (scale.is_ready()) - { - // Waage automatisch Taren, wenn zu lange Abweichung - if (autoTare && scale_tare_counter >= 5) + unsigned long currentTime = millis(); + + // Only measure at defined intervals to reduce noise + if (currentTime - lastMeasurementTime >= MEASUREMENT_INTERVAL_MS) { + if (scale.is_ready()) { - Serial.println("Auto Tare scale"); - scale.tare(); - scale_tare_counter = 0; - } + // Waage manuell Taren + if (scaleTareRequest == true || (autoTare && scale_tare_counter >= 20)) + { + Serial.println("Re-Tare scale"); + oledShowMessage("TARE Scale"); + vTaskDelay(pdMS_TO_TICKS(1000)); + scale.tare(); + resetWeightFilter(); // Reset filter after manual tare + vTaskDelay(pdMS_TO_TICKS(1000)); + oledShowWeight(0); + scaleTareRequest = false; + scale_tare_counter = 0; + weight = 0; // Reset global weight variable after tare + } - // Waage manuell Taren - if (scaleTareRequest == true) - { - Serial.println("Re-Tare scale"); - oledShowMessage("TARE Scale"); - vTaskDelay(pdMS_TO_TICKS(1000)); - scale.tare(); - vTaskDelay(pdMS_TO_TICKS(1000)); - oledShowWeight(0); - scaleTareRequest = false; - } + // Get raw weight reading + float rawWeight = scale.get_units(); + + // Process weight with stabilization + int16_t stabilizedWeight = processWeightReading(rawWeight); + + // Update global weight variable only if it changed significantly (for API actions) + if (stabilizedWeight != weight) { + weight = stabilizedWeight; + } + + // Prüfen ob die Waage korrekt genullt ist + // Abweichung von 2g ignorieren + if (autoTare && (rawWeight > 2 && rawWeight < 7) || rawWeight < -2) + { + scale_tare_counter++; + } + else + { + scale_tare_counter = 0; + } - // Only update weight if median changed more than 1 - int16_t newWeight = round(scale.get_units()); - if(abs(weight-newWeight) > 1){ - weight = newWeight; + // Debug output for monitoring (can be removed in production) + static unsigned long lastDebugTime = 0; + if (currentTime - lastDebugTime > 2000) { // Print every 2 seconds + lastDebugTime = currentTime; + } + + lastMeasurementTime = currentTime; } } - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(10)); // Shorter delay for more responsive loop } } @@ -110,19 +242,23 @@ void start_scale(bool touchSensorConnected) { scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); - oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Tare scale"); - for (uint16_t i = 0; i < 2000; i++) { + oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Serching scale"); + for (uint16_t i = 0; i < 3000; i++) { yield(); vTaskDelay(pdMS_TO_TICKS(1)); esp_task_wdt_reset(); } - if (scale.wait_ready_timeout(1000)) - { - scale.set_scale(calibrationValue); // this value is obtained by calibrating the scale with known weights; see the README for details - scale.tare(); + while(!scale.is_ready()) { + vTaskDelay(pdMS_TO_TICKS(5000)); } + scale.set_scale(calibrationValue); + //vTaskDelay(pdMS_TO_TICKS(5000)); + + // Initialize weight stabilization filter + resetWeightFilter(); + // Display Gewicht oledShowWeight(0); @@ -149,8 +285,8 @@ uint8_t calibrate_scale() { scaleCalibrationActive = true; - vTaskSuspend(RfidReaderTask); - vTaskSuspend(ScaleTask); + if (RfidReaderTask != NULL) vTaskSuspend(RfidReaderTask); + if (ScaleTask != NULL) vTaskSuspend(ScaleTask); pauseBambuMqttTask = true; pauseMainTask = 1; @@ -207,6 +343,7 @@ uint8_t calibrate_scale() { oledShowProgressBar(2, 3, "Scale Cal.", "Remove weight"); scale.set_scale(newCalibrationValue); + resetWeightFilter(); // Reset filter after calibration for (uint16_t i = 0; i < 2000; i++) { yield(); vTaskDelay(pdMS_TO_TICKS(1)); @@ -256,8 +393,8 @@ uint8_t calibrate_scale() { returnState = 0; } - vTaskResume(RfidReaderTask); - vTaskResume(ScaleTask); + if (RfidReaderTask != NULL) vTaskResume(RfidReaderTask); + if (ScaleTask != NULL) vTaskResume(ScaleTask); pauseBambuMqttTask = false; pauseMainTask = 0; scaleCalibrationActive = false; diff --git a/src/scale.h b/src/scale.h index c38583a..aff65e1 100644 --- a/src/scale.h +++ b/src/scale.h @@ -9,9 +9,16 @@ uint8_t start_scale(bool touchSensorConnected); uint8_t calibrate_scale(); uint8_t tareScale(); +// Weight stabilization functions +void resetWeightFilter(); +float calculateMovingAverage(); +float applyLowPassFilter(float newValue); +int16_t processWeightReading(float rawWeight); +int16_t getFilteredDisplayWeight(); + extern HX711 scale; extern int16_t weight; -extern uint8_t weigthCouterToApi; +extern uint8_t weightCounterToApi; extern uint8_t scale_tare_counter; extern uint8_t scaleTareRequest; extern uint8_t pauseMainTask; diff --git a/src/website.cpp b/src/website.cpp index 7c40fc7..0daf49f 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -48,9 +48,15 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp } else if (type == WS_EVT_PONG) { Serial.printf("WebSocket Client #%u pong\n", client->id()); } else if (type == WS_EVT_DATA) { - String message = String((char*)data); JsonDocument doc; - deserializeJson(doc, message); + DeserializationError error = deserializeJson(doc, (char*)data, len); + //String message = String((char*)data); + //deserializeJson(doc, message); + + if (error) { + Serial.println("JSON deserialization failed: " + String(error.c_str())); + return; + } if (doc["type"] == "heartbeat") { // Sende Heartbeat-Antwort @@ -75,7 +81,9 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp else if (doc["type"] == "scale") { uint8_t success = 0; if (doc["payload"] == "tare") { - success = tareScale(); + scaleTareRequest = true; + success = 1; + //success = tareScale(); } if (doc["payload"] == "calibrate") { diff --git a/src/wlan.cpp b/src/wlan.cpp index 92081bc..9dceeb2 100644 --- a/src/wlan.cpp +++ b/src/wlan.cpp @@ -36,6 +36,7 @@ void startMDNS() { vTaskDelay(1000 / portTICK_PERIOD_MS); } } + MDNS.addService("http", "tcp", 80); Serial.println("mDNS responder started"); }