From 3253e7d40771228cc64f3b3776f61a4003c8f50a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 10:41:44 +0100 Subject: [PATCH 001/366] sort vendors alphabetically in the dropdown list --- html/spoolman.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/html/spoolman.js b/html/spoolman.js index 9396d61..7cb2f6a 100644 --- a/html/spoolman.js +++ b/html/spoolman.js @@ -97,13 +97,15 @@ function populateVendorDropdown(data, selectedSmId = null) { ? (weightInKg / 1000).toFixed(2) + " t" : weightInKg.toFixed(2) + " kg"; - // Dropdown mit gefilterten Herstellern befüllen - Object.entries(filteredVendors).forEach(([id, name]) => { - const option = document.createElement("option"); - option.value = id; - option.textContent = name; - vendorSelect.appendChild(option); - }); + // Dropdown mit gefilterten Herstellern befüllen - alphabetisch sortiert + Object.entries(filteredVendors) + .sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) // Sort vendors alphabetically by name + .forEach(([id, name]) => { + const option = document.createElement("option"); + option.value = id; + option.textContent = name; + vendorSelect.appendChild(option); + }); document.getElementById("totalSpools").textContent = totalSpools; document.getElementById("spoolsWithoutTag").textContent = spoolsWithoutTag; From c6e727de0622bd0ad33b392276a993c56a4952e0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 10:41:51 +0100 Subject: [PATCH 002/366] remove unused version and protocol fields from NFC data packet --- html/rfid.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/html/rfid.js b/html/rfid.js index cece33f..d0d2f07 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -640,8 +640,6 @@ function writeNfcTag() { // Erstelle das NFC-Datenpaket mit korrekten Datentypen const nfcData = { - version: "2.0", - protocol: "openspool", color_hex: selectedSpool.filament.color_hex || "FFFFFF", type: selectedSpool.filament.material, min_temp: minTemp, From bec2c9133117b45a24befb14ad16d37ad64562f0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 10:42:06 +0100 Subject: [PATCH 003/366] remove unused version and protocol fields from JSON output; add error message for insufficient memory --- src/nfc.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 3593688..65966c5 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -44,8 +44,6 @@ void payloadToJson(uint8_t *data) { DeserializationError error = deserializeJson(doc, jsonString); if (!error) { - const char* version = doc["version"]; - const char* protocol = doc["protocol"]; const char* color_hex = doc["color_hex"]; const char* type = doc["type"]; int min_temp = doc["min_temp"]; @@ -55,8 +53,6 @@ void payloadToJson(uint8_t *data) { Serial.println(); Serial.println("-----------------"); Serial.println("JSON-Parsed Data:"); - Serial.println(version); - Serial.println(protocol); Serial.println(color_hex); Serial.println(type); Serial.println(min_temp); @@ -144,6 +140,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { if (combinedData == NULL) { Serial.println("Fehler: Nicht genug Speicher vorhanden."); + oledShowMessage("Tag too small"); + vTaskDelay(2000 / portTICK_PERIOD_MS); return 0; } From eb2a8dc128235547a447bf52343ba115f2c7aa15 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 12:18:21 +0100 Subject: [PATCH 004/366] add version comparison function and check for outdated versions before updates --- platformio.ini | 3 +++ src/ota.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/platformio.ini b/platformio.ini index cefcc8f..e6e1177 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,6 +10,8 @@ [common] version = "1.3.99" +to_old_version = "1.4.0" + ## [env:esp32dev] platform = espressif32 @@ -48,6 +50,7 @@ build_flags = #-DNDEBUG -mtext-section-literals -DVERSION=\"${common.version}\" + -DTOOLDVERSION=\"${common.to_old_version}\" -DASYNCWEBSERVER_REGEX #-DCORE_DEBUG_LEVEL=3 -DCONFIG_ARDUHAL_LOG_COLORS=1 diff --git a/src/ota.cpp b/src/ota.cpp index b222889..ed6fc52 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -14,6 +14,34 @@ static size_t updateTotalSize = 0; static size_t updateWritten = 0; static bool isSpiffsUpdate = false; +/** + * Compares two version strings and determines if version1 is less than version2 + * + * @param version1 First version string (format: x.y.z) + * @param version2 Second version string (format: x.y.z) + * @return true if version1 is less than version2 + */ +bool isVersionLessThan(const String& version1, const String& version2) { + int major1 = 0, minor1 = 0, patch1 = 0; + int major2 = 0, minor2 = 0, patch2 = 0; + + // Parse version1 + sscanf(version1.c_str(), "%d.%d.%d", &major1, &minor1, &patch1); + + // Parse version2 + sscanf(version2.c_str(), "%d.%d.%d", &major2, &minor2, &patch2); + + // Compare major version + if (major1 < major2) return true; + if (major1 > major2) return false; + + // Major versions equal, compare minor + if (minor1 < minor2) return true; + if (minor1 > minor2) return false; + + // Minor versions equal, compare patch + return patch1 < patch2; +} void backupJsonConfigs() { // Bambu Credentials backup @@ -111,6 +139,16 @@ void handleUpdate(AsyncWebServer &server) { updateHandler->setUri("/update"); updateHandler->setMethod(HTTP_POST); + // Check if current version is less than defined TOOLVERSION before proceeding with update + if (isVersionLessThan(VERSION, TOOLDVERSION)) { + updateHandler->onRequest([](AsyncWebServerRequest *request) { + request->send(400, "application/json", + "{\"success\":false,\"message\":\"Your current version is too old. Please perform a full upgrade.\"}"); + }); + server.addHandler(updateHandler); + return; + } + updateHandler->onUpload([](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { if (!index) { From 7a2c9d6d171d83950b7a80d175bffd007fff1bae Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 12:18:33 +0100 Subject: [PATCH 005/366] add OctoPrint integration with configurable fields and update functionality --- html/spoolman.html | 29 ++++++++++++++++++++- src/api.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++--- src/api.h | 6 ++++- src/main.cpp | 5 ++++ src/website.cpp | 18 +++++++++++-- 5 files changed, 115 insertions(+), 8 deletions(-) diff --git a/html/spoolman.html b/html/spoolman.html index 9b2bcca..365237a 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -52,11 +52,18 @@ if (spoolmanUrl && spoolmanUrl.trim() !== "") { document.getElementById('spoolmanUrl').value = spoolmanUrl; } + + // Initialize OctoPrint fields visibility + toggleOctoFields(); }; function checkSpoolmanInstance() { const url = document.getElementById('spoolmanUrl').value; - fetch(`/api/checkSpoolman?url=${encodeURIComponent(url)}`) + const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked; + const spoolmanOctoUrl = document.getElementById('spoolmanOctoUrl').value; + const spoolmanOctoToken = document.getElementById('spoolmanOctoToken').value; + + fetch(`/api/checkSpoolman?url=${encodeURIComponent(url)}&octoEnabled=${spoolmanOctoEnabled}&octoUrl=${spoolmanOctoUrl}&octoToken=${spoolmanOctoToken}`) .then(response => response.json()) .then(data => { if (data.healthy) { @@ -90,6 +97,15 @@ document.getElementById('bambuStatusMessage').innerText = 'Error while saving: ' + error.message; }); } + + /** + * Controls visibility of OctoPrint configuration fields based on checkbox state + * Called on page load and when checkbox changes + */ + function toggleOctoFields() { + const octoEnabled = document.getElementById('spoolmanOctoEnabled').checked; + document.getElementById('octoFields').style.display = octoEnabled ? 'block' : 'none'; + } + + + + + + + +
+
+ +
+
+
+

Statistics

+ +
+
+

Spools

+
+ total: + +
+ without Tag: + +
+
+ +
+
+

Overview

+
    +
  • + Manufacturer: + +
  • +
  • + Weight: + +
  • +
  • + Length: + +
  • +
+
+
+

Materials

+
    + +
+
+
+
+
+
+

NFC-Tag

+ +
+
+
+
+ + +
+
+

Spoolman Spools

+ +
+ + +
+
+ + +
+ + +
+
+

Bambu AMS

+
+
Wait for AMS-Data...
+
+
+
+
+
+ + + + + + diff --git a/src/bambu.cpp b/src/bambu.cpp index f5f3752..4278c1e 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -27,6 +27,7 @@ const char* bambu_serialnr = nullptr; String g_bambu_ip = ""; String g_bambu_accesscode = ""; String g_bambu_serialnr = ""; +bool bambuDisabled = false; bool bambu_connected = false; bool autoSendToBambu = false; @@ -654,10 +655,7 @@ bool setupMqtt() { } else { - Serial.println("Fehler: Keine MQTT-Daten vorhanden"); - oledShowMessage("Bambu Credentials Missing"); - oledShowTopRow(); - vTaskDelay(2000 / portTICK_PERIOD_MS); + bambuDisabled = true; return false; } return true; diff --git a/src/bambu.h b/src/bambu.h index 1dc7b3d..1e8de4e 100644 --- a/src/bambu.h +++ b/src/bambu.h @@ -30,6 +30,7 @@ extern int ams_count; extern AMSData ams_data[MAX_AMS]; extern bool autoSendToBambu; extern int autoSetToBambuSpoolId; +extern bool bambuDisabled; bool loadBambuCredentials(); bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime); diff --git a/src/website.cpp b/src/website.cpp index 2e01604..a49bdf8 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -29,7 +29,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp if (type == WS_EVT_CONNECT) { Serial.println("Neuer Client verbunden!"); // Sende die AMS-Daten an den neuen Client - sendAmsData(client); + if (!bambuDisabled) sendAmsData(client); sendNfcData(client); foundNfcTag(client, 0); sendWriteResult(client, 3); @@ -213,7 +213,10 @@ void setupWebserver(AsyncWebServer &server) { // Route für RFID server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("Anfrage für /rfid erhalten"); - AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/rfid.html.gz", "text/html"); + + String page = (bambuDisabled) ? "/rfid.html.gz" : "/rfid_bambu.html.gz"; + AsyncWebServerResponse *response = request->beginResponse(LittleFS, page, "text/html"); + response->addHeader("Content-Encoding", "gzip"); response->addHeader("Cache-Control", CACHE_CONTROL); request->send(response); From 024056cb7db59cf2b3f11e69686577df4147778f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 11:18:04 +0100 Subject: [PATCH 078/366] fix: handle Bambu connection state by introducing bambuDisabled flag --- src/bambu.cpp | 5 ++--- src/main.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/bambu.cpp b/src/bambu.cpp index 4278c1e..56325a1 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -607,14 +607,13 @@ bool setupMqtt() { bool success = loadBambuCredentials(); if (!success) { - Serial.println("Failed to load Bambu credentials"); - oledShowMessage("Bambu Credentials Missing"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + bambuDisabled = true; return false; } if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "") { + bambuDisabled = false; sslClient.setCACert(root_ca); sslClient.setInsecure(); client.setServer(bambu_ip, 8883); diff --git a/src/main.cpp b/src/main.cpp index d9ead63..0b2c635 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,7 +100,7 @@ void loop() { // Wenn Bambu auto set Spool aktiv if (autoSendToBambu && autoSetToBambuSpoolId > 0) { - if (!bambu_connected) + if (!bambuDisabled && !bambu_connected) { bambu_restart(); } From e459b53472db2003ea037451dd88432b4ab897cd Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 18:01:15 +0100 Subject: [PATCH 079/366] feat: add functionality to remove Bambu credentials and update API handling --- html/spoolman.html | 21 +++++++++++++++++++++ src/bambu.cpp | 26 ++++++++++++++++++++++++++ src/bambu.h | 1 + src/commonFS.cpp | 14 ++++++++++++++ src/commonFS.h | 1 + src/website.cpp | 9 +++++++++ 6 files changed, 72 insertions(+) diff --git a/html/spoolman.html b/html/spoolman.html index 1b615f7..a961874 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -57,6 +57,26 @@ toggleOctoFields(); }; + function removeBambuCredentials() { + fetch('/api/bambu?remove=true') + .then(response => response.json()) + .then(data => { + if (data.success) { + document.getElementById('bambuIp').value = ''; + document.getElementById('bambuSerial').value = ''; + document.getElementById('bambuCode').value = ''; + document.getElementById('autoSend').checked = false; + document.getElementById('autoSendTime').value = ''; + document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!'; + } else { + document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.'; + } + }) + .catch(error => { + document.getElementById('bambuStatusMessage').innerText = 'Error while removing: ' + error.message; + }); + } + function checkSpoolmanInstance() { const url = document.getElementById('spoolmanUrl').value; const spoolmanOctoEnabled = document.getElementById('spoolmanOctoEnabled').checked; @@ -162,6 +182,7 @@ +

diff --git a/src/bambu.cpp b/src/bambu.cpp index 56325a1..818f92d 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -38,6 +38,32 @@ int ams_count = 0; String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients AMSData ams_data[MAX_AMS]; // Definition des Arrays; +bool removeBambuCredentials() { + if (BambuMqttTask) { + vTaskDelete(BambuMqttTask); + } + + if (!removeJsonValue("/bambu_credentials.json")) { + Serial.println("Fehler beim Löschen der Bambu-Credentials."); + return false; + } + // Löschen der globalen Variablen + g_bambu_ip = ""; + g_bambu_accesscode = ""; + g_bambu_serialnr = ""; + bambu_ip = nullptr; + bambu_accesscode = nullptr; + bambu_serialnr = nullptr; + autoSendToBambu = false; + autoSetToBambuSpoolId = 0; + ams_count = 0; + amsJsonData = ""; + + bambuDisabled = true; + + return true; +} + bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode, bool autoSend, const String& autoSendTime) { if (BambuMqttTask) { vTaskDelete(BambuMqttTask); diff --git a/src/bambu.h b/src/bambu.h index 1e8de4e..aef6c3b 100644 --- a/src/bambu.h +++ b/src/bambu.h @@ -32,6 +32,7 @@ extern bool autoSendToBambu; extern int autoSetToBambuSpoolId; extern bool bambuDisabled; +bool removeBambuCredentials(); bool loadBambuCredentials(); bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode, const bool autoSend, const String& autoSendTime); bool setupMqtt(); diff --git a/src/commonFS.cpp b/src/commonFS.cpp index 7940b22..b58f68d 100644 --- a/src/commonFS.cpp +++ b/src/commonFS.cpp @@ -1,6 +1,20 @@ #include "commonFS.h" #include +bool removeJsonValue(const char* filename) { + File file = LittleFS.open(filename, "r"); + if (!file) { + return true; + } + file.close(); + if (!LittleFS.remove(filename)) { + Serial.print("Fehler beim Löschen der Datei: "); + Serial.println(filename); + return false; + } + return true; +} + bool saveJsonValue(const char* filename, const JsonDocument& doc) { File file = LittleFS.open(filename, "w"); if (!file) { diff --git a/src/commonFS.h b/src/commonFS.h index d46b1e5..6cc2725 100644 --- a/src/commonFS.h +++ b/src/commonFS.h @@ -5,6 +5,7 @@ #include #include +bool removeJsonValue(const char* filename); bool saveJsonValue(const char* filename, const JsonDocument& doc); bool loadJsonValue(const char* filename, JsonDocument& doc); void initializeFileSystem(); diff --git a/src/website.cpp b/src/website.cpp index a49bdf8..18ac882 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -313,6 +313,15 @@ void setupWebserver(AsyncWebServer &server) { // Route für das Überprüfen der Bambu-Instanz server.on("/api/bambu", HTTP_GET, [](AsyncWebServerRequest *request){ + if (request->hasParam("remove")) { + if (removeBambuCredentials()) { + request->send(200, "application/json", "{\"success\": true}"); + } else { + request->send(500, "application/json", "{\"success\": false, \"error\": \"Fehler beim Löschen der Bambu-Credentials\"}"); + } + return; + } + if (!request->hasParam("bambu_ip") || !request->hasParam("bambu_serialnr") || !request->hasParam("bambu_accesscode")) { request->send(400, "application/json", "{\"success\": false, \"error\": \"Missing parameter\"}"); return; From 1044e91a0af1fb465d5d36b90e445279f194ad43 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 18:03:40 +0100 Subject: [PATCH 080/366] feat: add forced cache refresh after removing and saving Bambu credentials --- html/spoolman.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/html/spoolman.html b/html/spoolman.html index a961874..65d1325 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -68,6 +68,11 @@ document.getElementById('autoSend').checked = false; document.getElementById('autoSendTime').value = ''; document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!'; + // Reload with forced cache refresh after short delay + setTimeout(() => { + window.location.replace('/'); + location.reload(true); + }, 1500); } else { document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.'; } @@ -109,6 +114,11 @@ .then(data => { if (data.healthy) { document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!'; + // Reload with forced cache refresh after short delay + setTimeout(() => { + window.location.replace('/'); + location.reload(true); + }, 1500); } else { document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.'; } From 56d7d8596c9a099ccbbd2e82d1b07bac871d0957 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 18:07:33 +0100 Subject: [PATCH 081/366] style: update remove button for Bambu credentials with red background --- html/spoolman.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/spoolman.html b/html/spoolman.html index 65d1325..16736e0 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -192,7 +192,7 @@ - +

From 95c1bc823c18490a2d261b01377c1ecc42626262 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 18:54:33 +0100 Subject: [PATCH 082/366] docs: update platformio.ini for version v1.4.7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 8cb161f..d8c8b5b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.6" +version = "1.4.7" to_old_version = "1.4.0" ## From b5f0472af4517b116659fbeed68d3644a5f23378 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 18:54:33 +0100 Subject: [PATCH 083/366] docs: update changelog and header for version v1.4.7 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d4e409..e5d1b14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.4.7] - 2025-03-27 +### Added +- add forced cache refresh after removing and saving Bambu credentials +- add functionality to remove Bambu credentials and update API handling +- add rfid_bambu.html and update bambu connection handling + +### Changed +- update platformio.ini for version v1.4.7 +- Merge branch 'testing' +- update remove button for Bambu credentials with red background +- Merge pull request #28 from tugsi/main + +### Fixed +- handle Bambu connection state by introducing bambuDisabled flag +- Fix rfid.js-Failure with X1-Series, if you wanna send a Spool to AMS: - Uncaught TypeError: Cannot read properties of undefined (reading 'replace') at handleSpoolIn (rfid.js:493:67) at HTMLButtonElement.onclick ((Index):1:1) handleSpoolIn @ rfid.js:493 onclick @ (Index):1 + + ## [1.4.6] - 2025-03-26 ### Changed - update platformio.ini for version v1.4.6 From 1484a6b0dae4ec2f5531a33facd423ff3de485e9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 27 Mar 2025 19:13:57 +0100 Subject: [PATCH 084/366] fix: update reload logic after removing and saving Bambu credentials for better cache handling --- html/spoolman.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/html/spoolman.html b/html/spoolman.html index 16736e0..912948d 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -70,8 +70,8 @@ document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials removed!'; // Reload with forced cache refresh after short delay setTimeout(() => { - window.location.replace('/'); - location.reload(true); + window.location.reload(true); + window.location.href = '/'; }, 1500); } else { document.getElementById('bambuStatusMessage').innerText = 'Error while removing Bambu Credentials.'; @@ -116,8 +116,8 @@ document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!'; // Reload with forced cache refresh after short delay setTimeout(() => { - window.location.replace('/'); - location.reload(true); + window.location.reload(true); + window.location.href = '/'; }, 1500); } else { document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.'; From 6cc4efca0a1deef7167549f877aec24785caefd3 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 28 Mar 2025 22:40:50 +0100 Subject: [PATCH 085/366] Fixes memory leak in HTTPClient by disabling connection reuse --- src/api.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api.cpp b/src/api.cpp index d15b273..d613081 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -94,6 +94,7 @@ void sendToApi(void *parameter) { String octoToken = params->octoToken; HTTPClient http; + http.setReuse(false); http.begin(spoolsUrl); http.addHeader("Content-Type", "application/json"); if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); From 2635c196675bc624255506551d9ea21c5e70e907 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 07:52:49 +0100 Subject: [PATCH 086/366] fix: improve HTTP client configuration and clear update documents after API calls --- src/api.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/api.cpp b/src/api.cpp index d15b273..d67d2ed 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -94,6 +94,9 @@ void sendToApi(void *parameter) { String octoToken = params->octoToken; HTTPClient http; + http.setReuse(false); + http.setTimeout(10000); + http.begin(spoolsUrl); http.addHeader("Content-Type", "application/json"); if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); @@ -111,6 +114,7 @@ void sendToApi(void *parameter) { } http.end(); + vTaskDelay(50 / portTICK_PERIOD_MS); // Speicher freigeben delete params; @@ -165,6 +169,8 @@ bool updateSpoolTagId(String uidString, const char* payload) { NULL // Task-Handle (nicht benötigt) ); + updateDoc.clear(); + return true; } @@ -201,6 +207,8 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { NULL // Task-Handle (nicht benötigt) ); + updateDoc.clear(); + return 1; } @@ -238,6 +246,8 @@ bool updateSpoolOcto(int spoolId) { NULL // Task-Handle (nicht benötigt) ); + updateDoc.clear(); + return true; } From 97a050ace83bfc982ccd9fdca90379e2d2bfd563 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 07:58:12 +0100 Subject: [PATCH 087/366] docs: update platformio.ini for version v1.4.8 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index d8c8b5b..4ff1826 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.7" +version = "1.4.8" to_old_version = "1.4.0" ## From d2be75217506fdf26ab87a3581e78bb69b0a03a2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 07:58:12 +0100 Subject: [PATCH 088/366] docs: update changelog and header for version v1.4.8 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d1b14..0c7cd84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.4.8] - 2025-03-29 +### Changed +- update platformio.ini for version v1.4.8 +- Merge pull request #30 from janecker/main +- Merge branch 'testing' into main + +### Fixed +- improve HTTP client configuration and clear update documents after API calls +- Fixes memory leak in HTTPClient by disabling connection reuse +- update reload logic after removing and saving Bambu credentials for better cache handling + + ## [1.4.7] - 2025-03-27 ### Added - add forced cache refresh after removing and saving Bambu credentials From 57723b5354c6d4a1c152c22e4963ea9debfa6dd7 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 10:03:17 +0100 Subject: [PATCH 089/366] fix: enhance HTTP method handling in sendToApi function --- src/api.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 590607a..dac177c 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -100,9 +100,10 @@ void sendToApi(void *parameter) { http.addHeader("Content-Type", "application/json"); if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken); - int httpCode = http.PUT(updatePayload); + int httpCode; if (httpType == "PATCH") httpCode = http.PATCH(updatePayload); - if (httpType == "POST") httpCode = http.POST(updatePayload); + else if (httpType == "POST") httpCode = http.POST(updatePayload); + else httpCode = http.PUT(updatePayload); if (httpCode == HTTP_CODE_OK) { Serial.println("Spoolman erfolgreich aktualisiert"); From 8618b90e332ad544fd32ba6102c1964a8b3c7ecb Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 10:11:25 +0100 Subject: [PATCH 090/366] docs: update platformio.ini for version v1.4.9 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4ff1826..7bad263 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.8" +version = "1.4.9" to_old_version = "1.4.0" ## From 07a919b6ba5e8beffc6dfdb9db8445606097a8f4 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 10:11:25 +0100 Subject: [PATCH 091/366] docs: update changelog and header for version v1.4.9 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c7cd84..e400fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.4.9] - 2025-03-29 +### Changed +- update platformio.ini for version v1.4.9 + +### Fixed +- enhance HTTP method handling in sendToApi function + + ## [1.4.8] - 2025-03-29 ### Changed - update platformio.ini for version v1.4.8 From c701149c64ad752349c79b6687c57f18600c2d6a Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 29 Mar 2025 11:45:38 +0100 Subject: [PATCH 092/366] Introducing enum for handling the NFC state to improve code readability --- src/main.cpp | 11 +++++----- src/nfc.cpp | 28 +++++++++++++------------- src/nfc.h | 14 ++++++++++++- src/website.cpp | 53 +++++++++++++++++++++++-------------------------- 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0b2c635..fee8cd5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,7 +107,7 @@ void loop() { if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval)) { - if (hasReadRfidTag == 0) + if (nfcReaderState == IDLE) { lastAutoSetBambuAmsTime = currentMillis; oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); @@ -141,7 +141,7 @@ void loop() { // Ausgabe der Waage auf Display if(pauseMainTask == 0) { - if (mainTaskWasPaused || (weight != lastWeight && hasReadRfidTag == 0 && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) + if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) { (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); } @@ -154,7 +154,7 @@ void loop() { // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird - if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag < 3) + if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < WRITING) { lastWeightReadTime = currentMillis; @@ -190,7 +190,8 @@ void loop() { } // reset weight counter after writing tag - if (currentMillis - lastWeightReadTime >= weightReadInterval && hasReadRfidTag > 1) + // TBD: what exactly is the logic behind this? + if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != IDLE && nfcReaderState != READ_SUCCESS) { weigthCouterToApi = 0; } @@ -198,7 +199,7 @@ void loop() { lastWeight = weight; // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden - if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && hasReadRfidTag == 1) { + if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == READ_SUCCESS) { oledShowIcon("loading"); if (updateSpoolWeight(spoolId, weight)) { diff --git a/src/nfc.cpp b/src/nfc.cpp index 65966c5..e81f576 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -18,7 +18,7 @@ String spoolId = ""; String nfcJsonData = ""; volatile bool pauseBambuMqttTask = false; -volatile uint8_t hasReadRfidTag = 0; +volatile nfcReaderStateType nfcReaderState = IDLE; // 0 = nicht gelesen // 1 = erfolgreich gelesen // 2 = fehler beim Lesen @@ -242,7 +242,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Erstelle NDEF-Message..."); Serial.println(payload); - hasReadRfidTag = 3; + nfcReaderState = WRITING; vTaskSuspend(RfidReaderTask); vTaskDelay(50 / portTICK_PERIOD_MS); @@ -288,7 +288,7 @@ void writeJsonToTag(void *parameter) { //oledShowMessage("NFC-Tag written"); oledShowIcon("success"); vTaskDelay(1000 / portTICK_PERIOD_MS); - hasReadRfidTag = 5; + nfcReaderState = WRITE_SUCCESS; // aktualisieren der Website wenn sich der Status ändert sendNfcData(nullptr); pauseBambuMqttTask = false; @@ -310,7 +310,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag"); oledShowIcon("failed"); vTaskDelay(2000 / portTICK_PERIOD_MS); - hasReadRfidTag = 4; + nfcReaderState = WRITE_ERROR; } } else @@ -318,7 +318,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Fehler: Kein Tag zu schreiben gefunden."); oledShowMessage("No NFC-Tag found"); vTaskDelay(2000 / portTICK_PERIOD_MS); - hasReadRfidTag = 0; + nfcReaderState = IDLE; } sendWriteResult(nullptr, success); @@ -334,7 +334,7 @@ void startWriteJsonToTag(const char* payload) { char* payloadCopy = strdup(payload); // Task nicht mehrfach starten - if (hasReadRfidTag != 3) { + if (nfcReaderState != WRITING) { // Erstelle die Task xTaskCreate( writeJsonToTag, // Task-Funktion @@ -351,7 +351,7 @@ void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { // Wenn geschrieben wird Schleife aussetzen - if (hasReadRfidTag != 3) + if (nfcReaderState != WRITING) { yield(); @@ -363,12 +363,12 @@ void scanRfidTask(void * parameter) { foundNfcTag(nullptr, success); - if (success && hasReadRfidTag != 1) + if (success && nfcReaderState != READ_SUCCESS) { // Display some basic information about the card Serial.println("Found an ISO14443A card"); - hasReadRfidTag = 6; + nfcReaderState = READING; oledShowIcon("transfer"); vTaskDelay(500 / portTICK_PERIOD_MS); @@ -406,11 +406,11 @@ void scanRfidTask(void * parameter) { { oledShowMessage("NFC-Tag unknown"); vTaskDelay(2000 / portTICK_PERIOD_MS); - hasReadRfidTag = 2; + nfcReaderState = READ_ERROR; } else { - hasReadRfidTag = 1; + nfcReaderState = READ_SUCCESS; } free(data); @@ -418,7 +418,7 @@ void scanRfidTask(void * parameter) { else { oledShowMessage("NFC-Tag read error"); - hasReadRfidTag = 2; + nfcReaderState = READ_ERROR; } } else @@ -427,9 +427,9 @@ void scanRfidTask(void * parameter) { } } - if (!success && hasReadRfidTag > 0) + if (!success && nfcReaderState != IDLE) { - hasReadRfidTag = 0; + nfcReaderState = IDLE; //uidString = ""; nfcJsonData = ""; Serial.println("Tag entfernt"); diff --git a/src/nfc.h b/src/nfc.h index 3610050..342f6fc 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -3,6 +3,16 @@ #include +typedef enum{ + IDLE, + READING, + READ_SUCCESS, + READ_ERROR, + WRITING, + WRITE_SUCCESS, + WRITE_ERROR +} nfcReaderStateType; + void startNfc(); void scanRfidTask(void * parameter); void startWriteJsonToTag(const char* payload); @@ -10,7 +20,9 @@ void startWriteJsonToTag(const char* payload); extern TaskHandle_t RfidReaderTask; extern String nfcJsonData; extern String spoolId; -extern volatile uint8_t hasReadRfidTag; +extern volatile nfcReaderStateType nfcReaderState; extern volatile bool pauseBambuMqttTask; + + #endif \ No newline at end of file diff --git a/src/website.cpp b/src/website.cpp index 18ac882..dd4a760 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -22,7 +22,7 @@ AsyncWebServer server(webserverPort); AsyncWebSocket ws("/ws"); uint8_t lastSuccess = 0; -uint8_t lastHasReadRfidTag = 0; +nfcReaderStateType lastnfcReaderState = IDLE; void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { @@ -139,34 +139,31 @@ void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) { } void sendNfcData(AsyncWebSocketClient *client) { - if (lastHasReadRfidTag == hasReadRfidTag) return; - if (hasReadRfidTag == 0) { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}"); + if (lastnfcReaderState == nfcReaderState) return; + // TBD: Why is there no status for reading the tag? + switch(nfcReaderState){ + case IDLE: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}"); + break; + case READ_SUCCESS: + ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}"); + break; + case READ_ERROR: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}"); + break; + case WRITING: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}"); + break; + case WRITE_SUCCESS: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}"); + break; + case WRITE_ERROR: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}"); + break; + case DEFAULT: + ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}"); } - else if (hasReadRfidTag == 1) { - ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}"); - } - else if (hasReadRfidTag == 2) - { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}"); - } - else if (hasReadRfidTag == 3) - { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}"); - } - else if (hasReadRfidTag == 4) - { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}"); - } - else if (hasReadRfidTag == 5) - { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}"); - } - else - { - ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Something went wrong\"}}"); - } - lastHasReadRfidTag = hasReadRfidTag; + lastnfcReaderState = nfcReaderState; } void sendAmsData(AsyncWebSocketClient *client) { From ac8adca84de8ce1963306314e7e426188e0b922d Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 29 Mar 2025 13:21:47 +0100 Subject: [PATCH 093/366] Renamed states of NFC state machine and introduced new state machine for spoolman API --- src/api.cpp | 8 ++++++-- src/api.h | 6 ++++++ src/display.cpp | 2 +- src/main.cpp | 10 +++++----- src/nfc.cpp | 28 ++++++++++++++-------------- src/nfc.h | 14 +++++++------- src/website.cpp | 18 ++++++++++-------- 7 files changed, 49 insertions(+), 37 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index d613081..984b1b2 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -3,7 +3,8 @@ #include #include "commonFS.h" -bool spoolman_connected = false; +volatile spoolmanApiStateType spoolmanApiState = API_INIT; +//bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; String octoUrl = ""; @@ -85,6 +86,7 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) { } void sendToApi(void *parameter) { + spoolmanApiState = API_TRANSMITTING; SendToApiParams* params = (SendToApiParams*)parameter; // Extrahiere die Werte @@ -116,6 +118,7 @@ void sendToApi(void *parameter) { // Speicher freigeben delete params; vTaskDelete(NULL); + spoolmanApiState = API_IDLE; } bool updateSpoolTagId(String uidString, const char* payload) { @@ -470,7 +473,8 @@ bool checkSpoolmanInstance(const String& url) { return false; } - spoolman_connected = true; + spoolmanApiState = API_IDLE; + oledShowTopRow(); return strcmp(status, "healthy") == 0; } } diff --git a/src/api.h b/src/api.h index 786ece1..88853c8 100644 --- a/src/api.h +++ b/src/api.h @@ -6,7 +6,13 @@ #include "website.h" #include "display.h" #include +typedef enum { + API_INIT, + API_IDLE, + API_TRANSMITTING +} spoolmanApiStateType; +extern volatile spoolmanApiStateType spoolmanApiState; extern bool spoolman_connected; extern String spoolmanUrl; extern bool octoEnabled; diff --git a/src/display.cpp b/src/display.cpp index c5a623f..dab0ccf 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -177,7 +177,7 @@ void oledShowTopRow() { display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE); } - if (spoolman_connected == 1) { + if (spoolmanApiState != API_INIT) { display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); } else { display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE); diff --git a/src/main.cpp b/src/main.cpp index fee8cd5..de8abab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,7 +107,7 @@ void loop() { if (intervalElapsed(currentMillis, lastAutoSetBambuAmsTime, autoSetBambuAmsInterval)) { - if (nfcReaderState == IDLE) + if (nfcReaderState == NFC_IDLE) { lastAutoSetBambuAmsTime = currentMillis; oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); @@ -141,7 +141,7 @@ void loop() { // Ausgabe der Waage auf Display if(pauseMainTask == 0) { - if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) + if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) { (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); } @@ -154,7 +154,7 @@ void loop() { // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird - if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < WRITING) + if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING) { lastWeightReadTime = currentMillis; @@ -191,7 +191,7 @@ void loop() { // reset weight counter after writing tag // TBD: what exactly is the logic behind this? - if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != IDLE && nfcReaderState != READ_SUCCESS) + if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS) { weigthCouterToApi = 0; } @@ -199,7 +199,7 @@ void loop() { lastWeight = weight; // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden - if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == READ_SUCCESS) { + if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS) { oledShowIcon("loading"); if (updateSpoolWeight(spoolId, weight)) { diff --git a/src/nfc.cpp b/src/nfc.cpp index e81f576..855405f 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -18,7 +18,7 @@ String spoolId = ""; String nfcJsonData = ""; volatile bool pauseBambuMqttTask = false; -volatile nfcReaderStateType nfcReaderState = IDLE; +volatile nfcReaderStateType nfcReaderState = NFC_IDLE; // 0 = nicht gelesen // 1 = erfolgreich gelesen // 2 = fehler beim Lesen @@ -242,7 +242,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Erstelle NDEF-Message..."); Serial.println(payload); - nfcReaderState = WRITING; + nfcReaderState = NFC_WRITING; vTaskSuspend(RfidReaderTask); vTaskDelay(50 / portTICK_PERIOD_MS); @@ -288,7 +288,7 @@ void writeJsonToTag(void *parameter) { //oledShowMessage("NFC-Tag written"); oledShowIcon("success"); vTaskDelay(1000 / portTICK_PERIOD_MS); - nfcReaderState = WRITE_SUCCESS; + nfcReaderState = NFC_WRITE_SUCCESS; // aktualisieren der Website wenn sich der Status ändert sendNfcData(nullptr); pauseBambuMqttTask = false; @@ -310,7 +310,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Fehler beim Schreiben der NDEF-Message auf den Tag"); oledShowIcon("failed"); vTaskDelay(2000 / portTICK_PERIOD_MS); - nfcReaderState = WRITE_ERROR; + nfcReaderState = NFC_WRITE_ERROR; } } else @@ -318,7 +318,7 @@ void writeJsonToTag(void *parameter) { Serial.println("Fehler: Kein Tag zu schreiben gefunden."); oledShowMessage("No NFC-Tag found"); vTaskDelay(2000 / portTICK_PERIOD_MS); - nfcReaderState = IDLE; + nfcReaderState = NFC_IDLE; } sendWriteResult(nullptr, success); @@ -334,7 +334,7 @@ void startWriteJsonToTag(const char* payload) { char* payloadCopy = strdup(payload); // Task nicht mehrfach starten - if (nfcReaderState != WRITING) { + if (nfcReaderState != NFC_WRITING) { // Erstelle die Task xTaskCreate( writeJsonToTag, // Task-Funktion @@ -351,7 +351,7 @@ void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != WRITING) + if (nfcReaderState != NFC_WRITING) { yield(); @@ -363,12 +363,12 @@ void scanRfidTask(void * parameter) { foundNfcTag(nullptr, success); - if (success && nfcReaderState != READ_SUCCESS) + if (success && nfcReaderState != NFC_READ_SUCCESS) { // Display some basic information about the card Serial.println("Found an ISO14443A card"); - nfcReaderState = READING; + nfcReaderState = NFC_READING; oledShowIcon("transfer"); vTaskDelay(500 / portTICK_PERIOD_MS); @@ -406,11 +406,11 @@ void scanRfidTask(void * parameter) { { oledShowMessage("NFC-Tag unknown"); vTaskDelay(2000 / portTICK_PERIOD_MS); - nfcReaderState = READ_ERROR; + nfcReaderState = NFC_READ_ERROR; } else { - nfcReaderState = READ_SUCCESS; + nfcReaderState = NFC_READ_SUCCESS; } free(data); @@ -418,7 +418,7 @@ void scanRfidTask(void * parameter) { else { oledShowMessage("NFC-Tag read error"); - nfcReaderState = READ_ERROR; + nfcReaderState = NFC_READ_ERROR; } } else @@ -427,9 +427,9 @@ void scanRfidTask(void * parameter) { } } - if (!success && nfcReaderState != IDLE) + if (!success && nfcReaderState != NFC_IDLE) { - nfcReaderState = IDLE; + nfcReaderState = NFC_IDLE; //uidString = ""; nfcJsonData = ""; Serial.println("Tag entfernt"); diff --git a/src/nfc.h b/src/nfc.h index 342f6fc..0d964f2 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -4,13 +4,13 @@ #include typedef enum{ - IDLE, - READING, - READ_SUCCESS, - READ_ERROR, - WRITING, - WRITE_SUCCESS, - WRITE_ERROR + NFC_IDLE, + NFC_READING, + NFC_READ_SUCCESS, + NFC_READ_ERROR, + NFC_WRITING, + NFC_WRITE_SUCCESS, + NFC_WRITE_ERROR } nfcReaderStateType; void startNfc(); diff --git a/src/website.cpp b/src/website.cpp index dd4a760..bf9e0fb 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -22,7 +22,7 @@ AsyncWebServer server(webserverPort); AsyncWebSocket ws("/ws"); uint8_t lastSuccess = 0; -nfcReaderStateType lastnfcReaderState = IDLE; +nfcReaderStateType lastnfcReaderState = NFC_IDLE; void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { @@ -44,13 +44,15 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp JsonDocument doc; deserializeJson(doc, message); + bool spoolmanConnected = (spoolmanApiState != API_INIT); + if (doc["type"] == "heartbeat") { // Sende Heartbeat-Antwort ws.text(client->id(), "{" "\"type\":\"heartbeat\"," "\"freeHeap\":" + String(ESP.getFreeHeap()/1024) + "," "\"bambu_connected\":" + String(bambu_connected) + "," - "\"spoolman_connected\":" + String(spoolman_connected) + "" + "\"spoolman_connected\":" + String(spoolmanConnected) + "" "}"); } @@ -142,22 +144,22 @@ void sendNfcData(AsyncWebSocketClient *client) { if (lastnfcReaderState == nfcReaderState) return; // TBD: Why is there no status for reading the tag? switch(nfcReaderState){ - case IDLE: + case NFC_IDLE: ws.textAll("{\"type\":\"nfcData\", \"payload\":{}}"); break; - case READ_SUCCESS: + case NFC_READ_SUCCESS: ws.textAll("{\"type\":\"nfcData\", \"payload\":" + nfcJsonData + "}"); break; - case READ_ERROR: + case NFC_READ_ERROR: ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Empty Tag or Data not readable\"}}"); break; - case WRITING: + case NFC_WRITING: ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Schreibe Tag...\"}}"); break; - case WRITE_SUCCESS: + case NFC_WRITE_SUCCESS: ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"info\":\"Tag erfolgreich geschrieben\"}}"); break; - case WRITE_ERROR: + case NFC_WRITE_ERROR: ws.textAll("{\"type\":\"nfcData\", \"payload\":{\"error\":\"Error writing to Tag\"}}"); break; case DEFAULT: From 2bf7c9fb7dbc207f39b40bfc142ac3055b569835 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 14:18:58 +0100 Subject: [PATCH 094/366] feat: add TTP223 touch sensor support and wiring configuration --- src/config.cpp | 6 ++++++ src/config.h | 2 ++ src/main.cpp | 30 ++++++++++-------------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 8c6e814..669456e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -19,6 +19,12 @@ const uint16_t SCALE_LEVEL_WEIGHT = 500; uint16_t defaultScaleCalibrationValue = 430; // ***** HX711 +// ***** TTP223 (Touch Sensor) +// TTP223 circuit wiring +const uint8_t TTP223_PIN = 15; +// ***** TTP223 + + // ***** Display // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // On an ESP32: 21(SDA), 22(SCL) diff --git a/src/config.h b/src/config.h index 822ff8d..dd6cb20 100644 --- a/src/config.h +++ b/src/config.h @@ -11,6 +11,8 @@ extern const uint8_t LOADCELL_SCK_PIN; extern const uint8_t calVal_eepromAdress; extern const uint16_t SCALE_LEVEL_WEIGHT; +extern const uint8_t TTP223_PIN; + extern const int8_t OLED_RESET; extern const uint8_t SCREEN_ADDRESS; extern const uint8_t SCREEN_WIDTH; diff --git a/src/main.cpp b/src/main.cpp index 0b2c635..69b00aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,6 @@ void setup() { setupWebserver(server); // Spoolman API - // api.cpp initSpoolman(); // Bambu MQTT @@ -48,6 +47,7 @@ void setup() { // NFC Reader startNfc(); + // Scale start_scale(); // WDT initialisieren mit 10 Sekunden Timeout @@ -56,6 +56,9 @@ void setup() { // Aktuellen Task (loopTask) zum Watchdog hinzufügen esp_task_wdt_add(NULL); + + // Touch Sensor + pinMode(TTP223_PIN, INPUT_PULLUP); } @@ -91,6 +94,12 @@ const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden ( void loop() { unsigned long currentMillis = millis(); + // Überprüfe den Status des Touch Sensors + if (digitalRead(TTP223_PIN) == LOW) + { + tareScale(); + } + // Überprüfe regelmäßig die WLAN-Verbindung if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) { @@ -158,25 +167,6 @@ void loop() { { lastWeightReadTime = currentMillis; - // Prüfen ob die Waage korrekt genullt ist - if ((weight > 0 && weight < 5) || weight < -1) - { - if(scaleTareCounter < 5) - { - scaleTareCounter++; - } - else - { - scaleTareRequest = true; - scaleTareCounter = 0; - } - - } - else - { - scaleTareCounter = 0; - } - // Prüfen ob das Gewicht gleich bleibt und dann senden if (weight == lastWeight && weight > 5) { From 83d14b32d1551b629328f95df92ec031e76f26ec Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 14:23:55 +0100 Subject: [PATCH 095/366] fix: add debounce handling for TTP223 touch sensor --- src/main.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 69b00aa..4098ca6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -87,17 +87,23 @@ uint8_t autoAmsCounter = 0; uint8_t weightSend = 0; int16_t lastWeight = 0; +// WIFI check variables unsigned long lastWifiCheckTime = 0; const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms) +// Button debounce variables +unsigned long lastButtonPress = 0; +const unsigned long debounceDelay = 500; // 500 ms debounce delay + // ##### PROGRAM START ##### void loop() { unsigned long currentMillis = millis(); // Überprüfe den Status des Touch Sensors - if (digitalRead(TTP223_PIN) == LOW) + if (digitalRead(TTP223_PIN) == LOW && currentMillis - lastButtonPress > debounceDelay) { - tareScale(); + lastButtonPress = currentMillis; + scaleTareRequest = true; } // Überprüfe regelmäßig die WLAN-Verbindung From 823db6157c29d149f6c2f36d437a8b23ee327522 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 29 Mar 2025 14:44:33 +0100 Subject: [PATCH 096/366] fix: add manual tare functionality for scale --- src/scale.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scale.cpp b/src/scale.cpp index 62db4d1..92476f4 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -38,11 +38,15 @@ void scale_loop(void * parameter) { for(;;) { if (scale.is_ready()) { - // Waage nochmal Taren, wenn zu lange Abweichung + // Waage manuell Taren if (scaleTareRequest == true) { Serial.println("Re-Tare scale"); + oledShowMessage("TARE Scale"); + vTaskDelay(pdMS_TO_TICKS(1000)); scale.tare(); + vTaskDelay(pdMS_TO_TICKS(1000)); + oledShowWeight(0); scaleTareRequest = false; } From 29868e7101faf0f0c1ad977395b19e001511d6b1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:19:07 +0200 Subject: [PATCH 097/366] fix: update TTP223 pin configuration and adjust touch sensor logic --- README.de.md | 31 ++++++++++++++++++------------- README.md | 16 ++++++++++------ src/config.cpp | 2 +- src/main.cpp | 2 +- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/README.de.md b/README.de.md index eb81f18..20bb23a 100644 --- a/README.de.md +++ b/README.de.md @@ -55,19 +55,22 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ## Hardware-Anforderungen ### Komponenten -- **ESP32 Entwicklungsboard:** Jede ESP32-Variante. -[Amazon Link](https://amzn.eu/d/aXThslf) -- **HX711 5kg Wägezellen-Verstärker:** Für Gewichtsmessung. -[Amazon Link](https://amzn.eu/d/06A0DLb) -- **OLED 0.96 Zoll I2C weiß/gelb Display:** 128x64 SSD1306. -[Amazon Link](https://amzn.eu/d/0AuBp2c) -- **PN532 NFC NXP RFID-Modul V3:** Für NFC-Tag-Operationen. -[Amazon Link](https://amzn.eu/d/jfIuQXb) -- **NFC Tags NTAG213 NTA215:** RFID Tag -[Amazon Link](https://amzn.eu/d/9Z6mXc1) +- **ESP32 Development Board:** Any ESP32 variant. +[Amazon Link](https://amzn.to/3FHea6D) +- **HX711 5kg Load Cell Amplifier:** For weight measurement. +[Amazon Link](https://amzn.to/4ja1KTe) +- **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. +[Amazon Link](https://amzn.to/445aaa9) +- **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. +[Amazon Link](https://amzn.to/4iO6CO4) +- **NFC Tags NTAG213 NTAG215:** RFID Tag +[Amazon Link](https://amzn.to/3E071xO) +- **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch +[Amazon Link](https://amzn.to/4hTChMK) -### Pin-Konfiguration -| Komponente | ESP32 Pin | + +### Pin Konfiguration +| Component | ESP32 Pin | |-------------------|-----------| | HX711 DOUT | 16 | | HX711 SCK | 17 | @@ -77,8 +80,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | PN532 RESET | 33 | | PN532 SDA | 21 | | PN532 SCL | 22 | +| TTP223 I/O | 25 | -**Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** +**!! Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** +**Nutze den 3V Pin vom ESP für den Touch Sensor** ![Wiring](./img/Schaltplan.png) diff --git a/README.md b/README.md index 0415795..cae3237 100644 --- a/README.md +++ b/README.md @@ -60,15 +60,17 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ### Components - **ESP32 Development Board:** Any ESP32 variant. -[Amazon Link](https://amzn.eu/d/aXThslf) +[Amazon Link](https://amzn.to/3FHea6D) - **HX711 5kg Load Cell Amplifier:** For weight measurement. -[Amazon Link](https://amzn.eu/d/06A0DLb) +[Amazon Link](https://amzn.to/4ja1KTe) - **OLED 0.96 Zoll I2C white/yellow Display:** 128x64 SSD1306. -[Amazon Link](https://amzn.eu/d/0AuBp2c) +[Amazon Link](https://amzn.to/445aaa9) - **PN532 NFC NXP RFID-Modul V3:** For NFC tag operations. -[Amazon Link](https://amzn.eu/d/jfIuQXb) +[Amazon Link](https://amzn.to/4iO6CO4) - **NFC Tags NTAG213 NTAG215:** RFID Tag -[Amazon Link](https://amzn.eu/d/9Z6mXc1) +[Amazon Link](https://amzn.to/3E071xO) +- **TTP223 Touch Sensor (optional):** For reTARE per Button/Touch +[Amazon Link](https://amzn.to/4hTChMK) ### Pin Configuration @@ -82,8 +84,10 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | PN532 RESET | 33 | | PN532 SDA | 21 | | PN532 SCL | 22 | +| TTP223 I/O | 25 | -**Make sure that the DIP switches on the PN532 are set to I2C** +**!! Make sure that the DIP switches on the PN532 are set to I2C** +**Use the 3V pin from the ESP for the touch sensor** ![Wiring](./img/Schaltplan.png) diff --git a/src/config.cpp b/src/config.cpp index 669456e..dd601c6 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -21,7 +21,7 @@ uint16_t defaultScaleCalibrationValue = 430; // ***** TTP223 (Touch Sensor) // TTP223 circuit wiring -const uint8_t TTP223_PIN = 15; +const uint8_t TTP223_PIN = 25; // ***** TTP223 diff --git a/src/main.cpp b/src/main.cpp index 4098ca6..a8bf275 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,7 +100,7 @@ void loop() { unsigned long currentMillis = millis(); // Überprüfe den Status des Touch Sensors - if (digitalRead(TTP223_PIN) == LOW && currentMillis - lastButtonPress > debounceDelay) + if (digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay) { lastButtonPress = currentMillis; scaleTareRequest = true; From 696efc4d7945abf3a847272334ab8f2128eeb7bc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:19:25 +0200 Subject: [PATCH 098/366] docs: update platformio.ini for version v1.4.10 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 7bad263..1c8af81 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.9" +version = "1.4.10" to_old_version = "1.4.0" ## From fad84e12c8d4a5a5a6100039413ea5452d741e29 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:19:25 +0200 Subject: [PATCH 099/366] docs: update changelog and header for version v1.4.10 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e400fe0..253b054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [1.4.10] - 2025-03-30 +### Added +- add manual tare functionality for scale +- add debounce handling for TTP223 touch sensor +- add TTP223 touch sensor support and wiring configuration + +### Changed +- update platformio.ini for version v1.4.10 + +### Fixed +- update TTP223 pin configuration and adjust touch sensor logic + + ## [1.4.9] - 2025-03-29 ### Changed - update platformio.ini for version v1.4.9 From bb751b6289808e4bea104b2ada73893b758de5d5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:21:57 +0200 Subject: [PATCH 100/366] docs: update platformio.ini for version v1.4.11 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1c8af81..bde34b3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.10" +version = "1.4.11" to_old_version = "1.4.0" ## From 3c294a135f9431c842c7c3b2bf54a48b911da5d1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:21:57 +0200 Subject: [PATCH 101/366] docs: update changelog and header for version v1.4.11 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 253b054..c0d9d83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [1.4.11] - 2025-03-30 +### Added +- Renamed states of NFC state machine and introduced new state machine for spoolman API + +### Changed +- update platformio.ini for version v1.4.11 +- Merge branch 'main' of github.com:ManuelW77/Filaman +- Merge pull request #31 from janecker/nfc_rework +- Introducing enum for handling the NFC state to improve code readability + + ## [1.4.10] - 2025-03-30 ### Added - add manual tare functionality for scale From 476d3e82e2e11c5ddf2c25dbc0ff02a0a70ce3a6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:35:50 +0200 Subject: [PATCH 102/366] docs: update README files to clarify PN532 DIP switch settings --- README.de.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.de.md b/README.de.md index 20bb23a..3dada72 100644 --- a/README.de.md +++ b/README.de.md @@ -82,7 +82,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | PN532 SCL | 22 | | TTP223 I/O | 25 | -**!! Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** +**!! Achte darauf, dass am PN532 die DIP-Schalter auf I2C gestellt sind** **Nutze den 3V Pin vom ESP für den Touch Sensor** ![Wiring](./img/Schaltplan.png) diff --git a/README.md b/README.md index cae3237..d9e80ba 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) | PN532 SCL | 22 | | TTP223 I/O | 25 | -**!! Make sure that the DIP switches on the PN532 are set to I2C** +**!! Make sure that the DIP switches on the PN532 are set to I2C** **Use the 3V pin from the ESP for the touch sensor** ![Wiring](./img/Schaltplan.png) From 8c7fc159d327fcf01cc61ebf134fa721411f4bb1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:55:26 +0200 Subject: [PATCH 103/366] fix: add touch sensor connection check and update logic --- src/main.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 1db296a..9c4b62f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ bool mainTaskWasPaused = 0; uint8_t scaleTareCounter = 0; +bool touchSensorConnected = false; // ##### SETUP ##### void setup() { @@ -59,6 +60,16 @@ void setup() { // Touch Sensor pinMode(TTP223_PIN, INPUT_PULLUP); + if (digitalRead(TTP223_PIN) == HIGH) + { + Serial.println("Touch Sensor is not connected"); + touchSensorConnected = false; + } + else + { + Serial.println("Touch Sensor is connected"); + touchSensorConnected + } } @@ -100,7 +111,7 @@ void loop() { unsigned long currentMillis = millis(); // Überprüfe den Status des Touch Sensors - if (digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay) + if (touchSensorConnected && digitalRead(TTP223_PIN) == HIGH && currentMillis - lastButtonPress > debounceDelay) { lastButtonPress = currentMillis; scaleTareRequest = true; From d81acb2b615b04c9b6625c17b45048a2ac3bbb52 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:55:33 +0200 Subject: [PATCH 104/366] docs: update platformio.ini for version v1.4.12 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index bde34b3..1a78076 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.11" +version = "1.4.12" to_old_version = "1.4.0" ## From 7b18266534c71b025446340c78182cfa0adae89a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:55:33 +0200 Subject: [PATCH 105/366] docs: update changelog and header for version v1.4.12 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d9d83..ab9291e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [1.4.12] - 2025-03-30 +### Added +- add touch sensor connection check and update logic + +### Changed +- update platformio.ini for version v1.4.12 +- update README files to clarify PN532 DIP switch settings + + ## [1.4.11] - 2025-03-30 ### Added - Renamed states of NFC state machine and introduced new state machine for spoolman API From 4a55620d39092ba4884238e717bc9e5b9cb0a2cb Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:59:51 +0200 Subject: [PATCH 106/366] fix: update touch sensor connection logic to correctly identify connection status --- src/main.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9c4b62f..24da9f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,15 +60,10 @@ void setup() { // Touch Sensor pinMode(TTP223_PIN, INPUT_PULLUP); - if (digitalRead(TTP223_PIN) == HIGH) - { - Serial.println("Touch Sensor is not connected"); - touchSensorConnected = false; - } - else + if (digitalRead(TTP223_PIN) == LOW) { Serial.println("Touch Sensor is connected"); - touchSensorConnected + touchSensorConnected = true; } } From aba28422bd4a02bdaf1010b7595fef77e9a3d0ee Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:59:57 +0200 Subject: [PATCH 107/366] docs: update platformio.ini for version v1.4.13 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1a78076..2206425 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.12" +version = "1.4.13" to_old_version = "1.4.0" ## From e9d32ee060113cd336a50cbe00cf0070b0c6b888 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 12:59:57 +0200 Subject: [PATCH 108/366] docs: update changelog and header for version v1.4.13 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab9291e..4b8b37a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.4.13] - 2025-03-30 +### Changed +- update platformio.ini for version v1.4.13 + +### Fixed +- update touch sensor connection logic to correctly identify connection status + + ## [1.4.12] - 2025-03-30 ### Added - add touch sensor connection check and update logic From 32bb85f897556b335bec8c14e71489924ac49ebc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 16:01:17 +0200 Subject: [PATCH 109/366] feat: add auto-tare functionality and update scale handling based on touch sensor connection --- html/waage.html | 10 ++++++++++ scripts/gzip_files.py | 2 +- src/main.cpp | 30 ++++++++++++++++++++---------- src/scale.cpp | 33 ++++++++++++++++++++++++++++++++- src/scale.h | 6 ++++-- src/website.cpp | 16 ++++++++++++---- 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/html/waage.html b/html/waage.html index 7f28ca4..40ffa5c 100644 --- a/html/waage.html +++ b/html/waage.html @@ -55,6 +55,7 @@
Sacle Calibration
+    Enable Auto-TARE
@@ -140,6 +141,15 @@ })); }); + // Add auto-tare function + function setAutoTare(enabled) { + ws.send(JSON.stringify({ + type: 'scale', + payload: 'setAutoTare', + enabled: enabled + })); + } + // WebSocket-Verbindung beim Laden der Seite initiieren connectWebSocket(); diff --git a/scripts/gzip_files.py b/scripts/gzip_files.py index c863edb..b67c70a 100644 --- a/scripts/gzip_files.py +++ b/scripts/gzip_files.py @@ -14,7 +14,7 @@ def copy_file(input_file, output_file): def should_compress(file): # Skip compression for spoolman.html - if file == 'spoolman.html': + if file == 'spoolman.html' or file == 'waage.html': return False # Komprimiere nur bestimmte Dateitypen return file.endswith(('.js', '.png', '.css', '.html')) diff --git a/src/main.cpp b/src/main.cpp index 24da9f0..3135fcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,16 +48,6 @@ void setup() { // NFC Reader startNfc(); - // Scale - start_scale(); - - // WDT initialisieren mit 10 Sekunden Timeout - bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus - esp_task_wdt_init(10, panic); - - // Aktuellen Task (loopTask) zum Watchdog hinzufügen - esp_task_wdt_add(NULL); - // Touch Sensor pinMode(TTP223_PIN, INPUT_PULLUP); if (digitalRead(TTP223_PIN) == LOW) @@ -65,6 +55,16 @@ void setup() { Serial.println("Touch Sensor is connected"); touchSensorConnected = true; } + + // Scale + start_scale(touchSensorConnected); + + // WDT initialisieren mit 10 Sekunden Timeout + bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus + esp_task_wdt_init(10, panic); + + // Aktuellen Task (loopTask) zum Watchdog hinzufügen + esp_task_wdt_add(NULL); } @@ -179,6 +179,16 @@ void loop() { { lastWeightReadTime = currentMillis; + // Prüfen ob die Waage korrekt genullt ist + if (autoTare && (weight > 0 && weight < 5) || weight < 0) + { + scale_tare_counter++; + } + else + { + scale_tare_counter = 0; + } + // Prüfen ob das Gewicht gleich bleibt und dann senden if (weight == lastWeight && weight > 5) { diff --git a/src/scale.cpp b/src/scale.cpp index 92476f4..5808829 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -14,6 +14,7 @@ TaskHandle_t ScaleTask; int16_t weight = 0; uint8_t weigthCouterToApi = 0; +uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; uint8_t pauseMainTask = 0; uint8_t scaleCalibrated = 1; @@ -21,8 +22,23 @@ uint8_t scaleCalibrated = 1; Preferences preferences; const char* NVS_NAMESPACE = "scale"; const char* NVS_KEY_CALIBRATION = "cal_value"; +const char* NVS_KEY_AUTOTARE = "auto_tare"; +bool autoTare = true; // ##### Funktionen für Waage ##### +uint8_t setAutoTare(bool autoTareValue) { + Serial.print("Set AutoTare to "); + Serial.println(autoTareValue); + autoTare = autoTareValue; + + // Speichern mit NVS + preferences.begin(NVS_NAMESPACE, false); // false = readwrite + preferences.putBool(NVS_KEY_AUTOTARE, autoTare); + preferences.end(); + + return 1; +} + uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); @@ -38,6 +54,14 @@ void scale_loop(void * parameter) { for(;;) { if (scale.is_ready()) { + // Waage automatisch Taren, wenn zu lange Abweichung + if (autoTare && scale_tare_counter >= 5) + { + Serial.println("Auto Tare scale"); + scale.tare(); + scale_tare_counter = 0; + } + // Waage manuell Taren if (scaleTareRequest == true) { @@ -57,13 +81,20 @@ void scale_loop(void * parameter) { } } -void start_scale() { +void start_scale(bool touchSensorConnected) { Serial.println("Prüfe Calibration Value"); float calibrationValue; // NVS lesen preferences.begin(NVS_NAMESPACE, true); // true = readonly calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue); + + // auto Tare + // Wenn Touch Sensor verbunden, dann autoTare auf false setzen + // Danach prüfen was in NVS gespeichert ist + autoTare = (touchSensorConnected) ? false : true; + autoTare = preferences.getBool(NVS_KEY_AUTOTARE, autoTare); + preferences.end(); Serial.print("Read Scale Calibration Value "); diff --git a/src/scale.h b/src/scale.h index 4f99b7c..96f59a4 100644 --- a/src/scale.h +++ b/src/scale.h @@ -4,17 +4,19 @@ #include #include "HX711.h" - -uint8_t start_scale(); +uint8_t setAutoTare(bool autoTareValue); +uint8_t start_scale(bool touchSensorConnected); uint8_t calibrate_scale(); uint8_t tareScale(); extern HX711 scale; extern int16_t weight; extern uint8_t weigthCouterToApi; +extern uint8_t scale_tare_counter; extern uint8_t scaleTareRequest; extern uint8_t pauseMainTask; extern uint8_t scaleCalibrated; +extern bool autoTare; extern TaskHandle_t ScaleTask; diff --git a/src/website.cpp b/src/website.cpp index bf9e0fb..0ff02db 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -75,6 +75,10 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp success = calibrate_scale(); } + if (doc["payload"] == "setAutoTare") { + success = setAutoTare(doc["enabled"].as()); + } + if (success) { ws.textAll("{\"type\":\"scale\",\"payload\":\"success\"}"); } else { @@ -203,10 +207,14 @@ void setupWebserver(AsyncWebServer &server) { // Route für Waage server.on("/waage", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("Anfrage für /waage erhalten"); - AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html"); - response->addHeader("Content-Encoding", "gzip"); - response->addHeader("Cache-Control", CACHE_CONTROL); - request->send(response); + //AsyncWebServerResponse *response = request->beginResponse(LittleFS, "/waage.html.gz", "text/html"); + //response->addHeader("Content-Encoding", "gzip"); + //response->addHeader("Cache-Control", CACHE_CONTROL); + + String html = loadHtmlWithHeader("/waage.html"); + html.replace("{{autoTare}}", (autoTare) ? "checked" : ""); + + request->send(200, "text/html", html); }); // Route für RFID From d48d994c00bbfc5ba7c3cf1d7de1f4d853cd7946 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 16:01:45 +0200 Subject: [PATCH 110/366] docs: update platformio.ini for version v1.4.14 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2206425..eb58b7b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.13" +version = "1.4.14" to_old_version = "1.4.0" ## From a450d4bd1adb26d0c9e14d1830ce88d9d6c6332c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 16:01:45 +0200 Subject: [PATCH 111/366] docs: update changelog and header for version v1.4.14 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8b37a..78d0810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.4.14] - 2025-03-30 +### Added +- add auto-tare functionality and update scale handling based on touch sensor connection + +### Changed +- update platformio.ini for version v1.4.14 + + ## [1.4.13] - 2025-03-30 ### Changed - update platformio.ini for version v1.4.13 From f73306f0b9da4bdf0e48eb31d0b5db03f8e10db4 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 16:38:23 +0200 Subject: [PATCH 112/366] chore: update version to 1.5.1 and improve OTA update handling with task management --- platformio.ini | 4 ++-- src/ota.cpp | 33 ++++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index eb58b7b..3acfce9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,8 +9,8 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.4.14" -to_old_version = "1.4.0" +version = "1.5.1" +to_old_version = "1.5.0" ## [env:esp32dev] diff --git a/src/ota.cpp b/src/ota.cpp index ed6fc52..d22bc6a 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -1,6 +1,10 @@ #include #include #include +#include "scale.h" +#include "bambu.h" +#include "nfc.h" + // Globale Variablen für Config Backups hinzufügen String bambuCredentialsBackup; @@ -151,6 +155,25 @@ void handleUpdate(AsyncWebServer &server) { updateHandler->onUpload([](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { + + // Disable all Tasks + if (BambuMqttTask != NULL) + { + Serial.println("Delete BambuMqttTask"); + vTaskDelete(BambuMqttTask); + BambuMqttTask = NULL; + } + if (ScaleTask) { + Serial.println("Delete ScaleTask"); + vTaskDelete(ScaleTask); + ScaleTask = NULL; + } + if (RfidReaderTask) { + Serial.println("Delete RfidReaderTask"); + vTaskDelete(RfidReaderTask); + RfidReaderTask = NULL; + } + if (!index) { updateTotalSize = request->contentLength(); updateWritten = 0; @@ -159,9 +182,9 @@ void handleUpdate(AsyncWebServer &server) { if (isSpiffsUpdate) { // Backup vor dem Update sendUpdateProgress(0, "backup", "Backing up configurations..."); - delay(200); + vTaskDelay(200 / portTICK_PERIOD_MS); backupJsonConfigs(); - delay(200); + vTaskDelay(200 / portTICK_PERIOD_MS); const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); if (!partition || !Update.begin(partition->size, U_SPIFFS)) { @@ -169,14 +192,14 @@ void handleUpdate(AsyncWebServer &server) { return; } sendUpdateProgress(5, "starting", "Starting SPIFFS update..."); - delay(200); + vTaskDelay(200 / portTICK_PERIOD_MS); } else { if (!Update.begin(updateTotalSize)) { request->send(400, "application/json", "{\"success\":false,\"message\":\"Update initialization failed\"}"); return; } sendUpdateProgress(0, "starting", "Starting firmware update..."); - delay(200); + vTaskDelay(200 / portTICK_PERIOD_MS); } } @@ -202,7 +225,7 @@ void handleUpdate(AsyncWebServer &server) { if (currentProgress != lastProgress && (currentProgress % 10 == 0 || final)) { sendUpdateProgress(currentProgress, "uploading"); oledShowMessage("Update: " + String(currentProgress) + "%"); - delay(50); + vTaskDelay(50 / portTICK_PERIOD_MS); lastProgress = currentProgress; } } From e23f3a2151cf1d1724fe1f26c731e40c8531c7f2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 30 Mar 2025 16:38:38 +0200 Subject: [PATCH 113/366] docs: update changelog and header for version v1.5.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d0810..04cfdc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.5.1] - 2025-03-30 +### Changed +- update version to 1.5.1 and improve OTA update handling with task management + + ## [1.4.14] - 2025-03-30 ### Added - add auto-tare functionality and update scale handling based on touch sensor connection From 9ed3c70c013e4855fee5fe6cbd0ecb94545855f8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 31 Mar 2025 10:08:26 +0200 Subject: [PATCH 114/366] fix: improve weight stability check before sending to API --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 3135fcc..d30d032 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -190,7 +190,7 @@ void loop() { } // Prüfen ob das Gewicht gleich bleibt und dann senden - if (weight == lastWeight && weight > 5) + if (abs(weight - lastWeight) <= 2 && weight > 5) { weigthCouterToApi++; } From 012f91851ebb331c972247190687b4b202d2f0e2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 31 Mar 2025 10:59:54 +0200 Subject: [PATCH 115/366] fix: adjust tare weight tolerance to ignore deviations of 2g --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index d30d032..01763d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -180,7 +180,8 @@ void loop() { lastWeightReadTime = currentMillis; // Prüfen ob die Waage korrekt genullt ist - if (autoTare && (weight > 0 && weight < 5) || weight < 0) + // Abweichung von 2g ignorieren + if (autoTare && (weight > 2 && weight < 7) || weight < -2) { scale_tare_counter++; } From 01f1e123ace0de73bc8d9e574e88df418a8bf393 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 15 Apr 2025 16:38:16 +0200 Subject: [PATCH 116/366] fix: increase stack size for sendToApi task to improve stability --- src/api.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index d4c8749..33b9f2e 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -166,7 +166,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion "SendToApiTask", // Task-Name - 4096, // Stackgröße in Bytes + 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität NULL // Task-Handle (nicht benötigt) @@ -204,7 +204,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion "SendToApiTask", // Task-Name - 4096, // Stackgröße in Bytes + 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität NULL // Task-Handle (nicht benötigt) @@ -243,7 +243,7 @@ bool updateSpoolOcto(int spoolId) { BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion "SendToApiTask", // Task-Name - 4096, // Stackgröße in Bytes + 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität NULL // Task-Handle (nicht benötigt) @@ -291,7 +291,7 @@ bool updateSpoolBambuData(String payload) { BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion "SendToApiTask", // Task-Name - 4096, // Stackgröße in Bytes + 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität NULL // Task-Handle (nicht benötigt) From 0b356609d1362bd4f31b79ce2d0484b3dde714ba Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 11:07:30 +0200 Subject: [PATCH 117/366] fix: add weight field to update payload in updateSpoolTagId function --- src/api.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api.cpp b/src/api.cpp index 33b9f2e..38d9549 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -147,6 +147,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { // Update Payload erstellen JsonDocument updateDoc; updateDoc["extra"]["nfc_id"] = "\""+uidString+"\""; + updateDoc["weight"] = weight; String updatePayload; serializeJson(updateDoc, updatePayload); From cf8cce72a5946f2cbbb6d6b47f4028986b3c3408 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 11:08:32 +0200 Subject: [PATCH 118/366] fix: update weight field in update payload to only include values greater than 10 --- src/api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.cpp b/src/api.cpp index 38d9549..87dd579 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -147,7 +147,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { // Update Payload erstellen JsonDocument updateDoc; updateDoc["extra"]["nfc_id"] = "\""+uidString+"\""; - updateDoc["weight"] = weight; + if (weight > 10) updateDoc["weight"] = weight; String updatePayload; serializeJson(updateDoc, updatePayload); From e79c522e46a21a66df6f057ce55e79352ae1ee93 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 11:33:07 +0200 Subject: [PATCH 119/366] fix: add remaining weight logging and display after successful spool update --- src/api.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/api.cpp b/src/api.cpp index 87dd579..b7ba678 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -109,6 +109,24 @@ void sendToApi(void *parameter) { if (httpCode == HTTP_CODE_OK) { Serial.println("Spoolman erfolgreich aktualisiert"); + + // Restgewicht der Spule auslesen + String payload = http.getString(); + JsonDocument doc; + DeserializationError error = deserializeJson(doc, payload); + if (error) { + Serial.print("Fehler beim Parsen der JSON-Antwort: "); + Serial.println(error.c_str()); + } else { + float remaining_weight = doc["remaining_weight"].as(); + Serial.print("Aktuelles Gewicht: "); + Serial.println(remaining_weight); + + oledShowMessage("Remaining: " + String(remaining_weight) + "g"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + doc.clear(); + } + } else { Serial.println("Fehler beim Senden an Spoolman!"); oledShowMessage("Spoolman update failed"); From c78c20979d105ff572bc3b2fa71ddb66b9c8cfc6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 14:51:31 +0200 Subject: [PATCH 120/366] fix: add remaining weight logging for PUT requests and improve error reporting in sendToApi function --- src/api.cpp | 16 +++++++++------- src/bambu.cpp | 3 +++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index b7ba678..ff8db3a 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -118,17 +118,19 @@ void sendToApi(void *parameter) { Serial.print("Fehler beim Parsen der JSON-Antwort: "); Serial.println(error.c_str()); } else { - float remaining_weight = doc["remaining_weight"].as(); - Serial.print("Aktuelles Gewicht: "); - Serial.println(remaining_weight); - - oledShowMessage("Remaining: " + String(remaining_weight) + "g"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + if (httpType == "PUT") { + uint16_t remaining_weight = doc["remaining_weight"].as(); + Serial.print("Aktuelles Gewicht: "); + Serial.println(remaining_weight); + oledShowMessage("Remaining: " + String(remaining_weight) + "g"); + } + + vTaskDelay(3000 / portTICK_PERIOD_MS); doc.clear(); } } else { - Serial.println("Fehler beim Senden an Spoolman!"); + Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); oledShowMessage("Spoolman update failed"); vTaskDelay(2000 / portTICK_PERIOD_MS); } diff --git a/src/bambu.cpp b/src/bambu.cpp index 818f92d..0225dae 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -674,6 +674,7 @@ bool setupMqtt() { vTaskDelay(2000 / portTICK_PERIOD_MS); connected = false; oledShowTopRow(); + autoSetToBambuSpoolId = 0; } if (!connected) return false; @@ -687,6 +688,8 @@ bool setupMqtt() { } void bambu_restart() { + Serial.println("Bambu restart"); + if (BambuMqttTask) { vTaskDelete(BambuMqttTask); delay(10); From b1f79237704b395bdcda2a90a09b913155bb8f8d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 17:47:02 +0200 Subject: [PATCH 121/366] feat: implement multi-color filament display and styles for dropdown options --- html/rfid.js | 14 ------------- html/spoolman.js | 51 +++++++++++++++++++++++++++++++++++++++++++++--- html/style.css | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/html/rfid.js b/html/rfid.js index 826adc2..3761f51 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -215,20 +215,6 @@ document.addEventListener('filamentSelected', function (event) { updateSpoolButtons(selectedText !== "Please choose..."); }); -// Hilfsfunktion für kontrastreiche Textfarbe -function getContrastColor(hexcolor) { - // Konvertiere Hex zu RGB - const r = parseInt(hexcolor.substr(0,2),16); - const g = parseInt(hexcolor.substr(2,2),16); - const b = parseInt(hexcolor.substr(4,2),16); - - // Berechne Helligkeit (YIQ Formel) - const yiq = ((r*299)+(g*587)+(b*114))/1000; - - // Return schwarz oder weiß basierend auf Helligkeit - return (yiq >= 128) ? '#000000' : '#FFFFFF'; -} - function updateNfcInfo() { const selectedText = document.getElementById("selected-filament").textContent; const nfcInfo = document.getElementById("nfcInfo"); diff --git a/html/spoolman.js b/html/spoolman.js index 5cc2f91..8193984 100644 --- a/html/spoolman.js +++ b/html/spoolman.js @@ -169,9 +169,32 @@ function updateFilamentDropdown(selectedSmId = null) { option.setAttribute("data-value", spool.filament.id); option.setAttribute("data-nfc-id", spool.extra.nfc_id || ""); - const colorHex = spool.filament.color_hex || 'FFFFFF'; + + // Generate color representation based on filament type (single or multi color) + let colorHTML = ''; + + // Check if this is a multicolor filament + if (spool.filament.multi_color_hexes) { + // Parse multi color hexes from comma-separated string + const colors = spool.filament.multi_color_hexes.replace(/#/g, '').split(','); + + // Determine the display style based on direction + const direction = spool.filament.multi_color_direction || 'coaxial'; + + // Generate color circles for each color + colorHTML = '
'; + colors.forEach(color => { + colorHTML += `
`; + }); + colorHTML += '
'; + } else { + // Single color filament + const colorHex = spool.filament.color_hex || 'FFFFFF'; + colorHTML = `
`; + } + option.innerHTML = ` -
+ ${colorHTML} ${spool.id} | ${spool.filament.name} (${spool.filament.material}) `; @@ -190,7 +213,29 @@ function selectFilament(spool) { const selectedText = document.getElementById("selected-filament"); const dropdownContent = document.getElementById("filament-dropdown-content"); - selectedColor.style.backgroundColor = `#${spool.filament.color_hex || 'FFFFFF'}`; + // Update the selected color display + if (spool.filament.multi_color_hexes) { + // Handle multicolor filament display in the selection header + const colors = spool.filament.multi_color_hexes.replace(/#/g, '').split(','); + const direction = spool.filament.multi_color_direction || 'coaxial'; + + // Replace the single color div with multiple color divs + selectedColor.innerHTML = ''; + colors.forEach(color => { + const colorDiv = document.createElement('div'); + colorDiv.className = `color-segment multi-color ${direction}`; + colorDiv.style.backgroundColor = `#${color}`; + selectedColor.appendChild(colorDiv); + }); + // Add multiple color class to the container + selectedColor.classList.add('multi-color-container'); + } else { + // Single color filament - reset to default display + selectedColor.innerHTML = ''; + selectedColor.classList.remove('multi-color-container'); + selectedColor.style.backgroundColor = `#${spool.filament.color_hex || 'FFFFFF'}`; + } + selectedText.textContent = `${spool.id} | ${spool.filament.name} (${spool.filament.material})`; dropdownContent.classList.remove("show"); diff --git a/html/style.css b/html/style.css index e2c12ac..e0f37aa 100644 --- a/html/style.css +++ b/html/style.css @@ -759,6 +759,50 @@ a:hover { flex-shrink: 0; } +/* Multi-color filament styles */ +.option-colors { + display: flex; + flex-shrink: 0; + gap: 2px; +} + +.multi-color { + width: 14px; + height: 14px; + border-radius: 50%; + border: 1px solid #333; +} + +/* Coaxial pattern (horizontal stripes) */ +.multi-color.coaxial { + border-radius: 50%; + position: relative; +} + +/* Longitudinal pattern (vertical stripes) */ +.multi-color.longitudinal { + border-radius: 50%; + position: relative; +} + +/* Container for multiple colors in selected display */ +.multi-color-container { + display: flex !important; + background: none !important; + border: none !important; + gap: 2px; + align-items: center; + justify-content: flex-start; + width: auto !important; +} + +.color-segment { + width: 16px; + height: 16px; + border-radius: 50%; + border: 1px solid #333; +} + .notification { position: fixed; top: 20px; From 599cc47443dad46dc8ab05a36d299b49e706ea7a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 17:47:40 +0200 Subject: [PATCH 122/366] docs: update platformio.ini for version v1.5.2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3acfce9..17af0ea 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.1" +version = "1.5.2" to_old_version = "1.5.0" ## From 3d31833f5001e90d465402bac80f662c1adaaedf Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 23 Apr 2025 17:47:40 +0200 Subject: [PATCH 123/366] docs: update changelog and header for version v1.5.2 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04cfdc0..c3912ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.5.2] - 2025-04-23 +### Added +- 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 + +### Changed +- update platformio.ini for version v1.5.2 + +### Fixed +- 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 + + ## [1.5.1] - 2025-03-30 ### Changed - update version to 1.5.1 and improve OTA update handling with task management From 0becae7ed6d43ac07f1fdb6bc7643fd9f5c21ffd Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 25 Apr 2025 09:41:02 +0200 Subject: [PATCH 124/366] Affiliate Links --- README.de.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.de.md b/README.de.md index 3dada72..8e42465 100644 --- a/README.de.md +++ b/README.de.md @@ -54,7 +54,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ## Hardware-Anforderungen -### Komponenten +### Komponenten (Affiliate Links) - **ESP32 Development Board:** Any ESP32 variant. [Amazon Link](https://amzn.to/3FHea6D) - **HX711 5kg Load Cell Amplifier:** For weight measurement. diff --git a/README.md b/README.md index d9e80ba..44d6a4f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ## Hardware Requirements -### Components +### Components (Affiliate Links) - **ESP32 Development Board:** Any ESP32 variant. [Amazon Link](https://amzn.to/3FHea6D) - **HX711 5kg Load Cell Amplifier:** For weight measurement. From 6dc26ca51ff79ea5471069f4af2ea7841bd805e0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 25 Apr 2025 15:52:38 +0200 Subject: [PATCH 125/366] fix: update spool weight conditionally based on NFC ID --- src/api.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api.cpp b/src/api.cpp index ff8db3a..a8b3e2d 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -167,7 +167,6 @@ bool updateSpoolTagId(String uidString, const char* payload) { // Update Payload erstellen JsonDocument updateDoc; updateDoc["extra"]["nfc_id"] = "\""+uidString+"\""; - if (weight > 10) updateDoc["weight"] = weight; String updatePayload; serializeJson(updateDoc, updatePayload); @@ -195,6 +194,9 @@ bool updateSpoolTagId(String uidString, const char* payload) { updateDoc.clear(); + // Update Spool weight + if (weight > 10) updateSpoolWeight(doc["sm_id"].as(), weight); + return true; } From 859e89431e4cc797a3ae5278d09ce8edb618e3ba Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 25 Apr 2025 15:52:56 +0200 Subject: [PATCH 126/366] docs: update platformio.ini for version v1.5.3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 17af0ea..78dc2f5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.2" +version = "1.5.3" to_old_version = "1.5.0" ## From 2e19bccfa9015b09418edc11dc4a020680927cb7 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 25 Apr 2025 15:52:56 +0200 Subject: [PATCH 127/366] docs: update changelog and header for version v1.5.3 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3912ed..8c432ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [1.5.3] - 2025-04-25 +### Changed +- update platformio.ini for version v1.5.3 +- Affiliate Links + +### Fixed +- update spool weight conditionally based on NFC ID + + ## [1.5.2] - 2025-04-23 ### Added - implement multi-color filament display and styles for dropdown options From 2920159f32db01f8de1d576a12993888850aa170 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 2 May 2025 16:44:57 +0200 Subject: [PATCH 128/366] add loadcell desc. --- README.de.md | 6 ++++++ README.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/README.de.md b/README.de.md index 8e42465..ab970ab 100644 --- a/README.de.md +++ b/README.de.md @@ -90,6 +90,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ![myWiring](./img/IMG_2589.jpeg) ![myWiring](./img/IMG_2590.jpeg) +*Die Wägezelle wird bei den meisten HX711 Modulen folgendermaßen verkabelt: +E+ rot +E- schwarz +A- weiß +A+ grün* + ## Software-Abhängigkeiten ### ESP32-Bibliotheken diff --git a/README.md b/README.md index 44d6a4f..a1238f1 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,12 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ![myWiring](./img/IMG_2589.jpeg) ![myWiring](./img/IMG_2590.jpeg) +*The load cell is connected to most HX711 modules as follows: +E+ red +E- black +A- white +A+ green* + ## Software Dependencies ### ESP32 Libraries From 27ef8399e48a99ef51116480212aa6f0241daeff Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Thu, 19 Jun 2025 10:08:15 +0200 Subject: [PATCH 129/366] Adds slight debouncing to the scale loop weight logic Adds slight debouncing to the scale loop to prevent jitter of the weight displayed on the screen. --- src/scale.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scale.cpp b/src/scale.cpp index 5808829..83edeeb 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -74,7 +74,11 @@ void scale_loop(void * parameter) { scaleTareRequest = false; } - weight = round(scale.get_units()); + // Only update weight if median changed more than 1 + int16_t newWeight = round(scale.get_units()); + if(abs(weight-newWeight) > 1){ + weight = newWeight; + } } vTaskDelay(pdMS_TO_TICKS(100)); From eab937d6cacaa3a5e796772da82a773cabe72bc8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Mon, 21 Jul 2025 21:03:55 +0200 Subject: [PATCH 130/366] Adds new feature to write and read location tags Location tags can be written via the website. If a location tag is read after reading a spool tag, the location of the spool will be updated in spoolman to the location from the tag. --- html/rfid.html | 12 +++++++++ html/rfid.js | 64 ++++++++++++++++++++++++++++++++++++--------- html/spoolman.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++- html/style.css | 14 ++++++---- src/api.cpp | 52 ++++++++++++++++++++++++++++++++++++- src/api.h | 9 +++++++ src/nfc.cpp | 18 +++++++++++-- 7 files changed, 215 insertions(+), 21 deletions(-) diff --git a/html/rfid.html b/html/rfid.html index a481c04..cfffff8 100644 --- a/html/rfid.html +++ b/html/rfid.html @@ -139,6 +139,18 @@

+ +
+

Spoolman Locations

+ +
+ +
+

+ +
diff --git a/html/rfid.js b/html/rfid.js index 3761f51..6bdcea2 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -626,11 +626,11 @@ function writeNfcTag() { // Erstelle das NFC-Datenpaket mit korrekten Datentypen const nfcData = { - color_hex: selectedSpool.filament.color_hex || "FFFFFF", - type: selectedSpool.filament.material, - min_temp: minTemp, - max_temp: maxTemp, - brand: selectedSpool.filament.vendor.name, + //color_hex: selectedSpool.filament.color_hex || "FFFFFF", + //type: selectedSpool.filament.material, + //min_temp: minTemp, + //max_temp: maxTemp, + //brand: selectedSpool.filament.vendor.name, sm_id: String(selectedSpool.id) // Konvertiere zu String }; @@ -647,16 +647,56 @@ function writeNfcTag() { } } +function writeLocationNfcTag() { + const selectedText = document.getElementById("locationSelect").value; + if (selectedText === "Please choose...") { + alert('Please select a location first.'); + return; + } + // Erstelle das NFC-Datenpaket mit korrekten Datentypen + const nfcData = { + location: String(selectedText) + }; + + if (socket?.readyState === WebSocket.OPEN) { + const writeButton = document.getElementById("writeLocationNfcButton"); + writeButton.classList.add("writing"); + writeButton.textContent = "Writing"; + socket.send(JSON.stringify({ + type: 'writeNfcTag', + payload: nfcData + })); + } else { + alert('Not connected to Server. Please check connection.'); + } +} + function handleWriteNfcTagResponse(success) { const writeButton = document.getElementById("writeNfcButton"); - writeButton.classList.remove("writing"); - writeButton.classList.add(success ? "success" : "error"); - writeButton.textContent = success ? "Write success" : "Write failed"; + const writeLocationButton = document.getElementById("writeLocationNfcButton"); + if(writeButton.classList.contains("writing")){ + writeButton.classList.remove("writing"); + writeButton.classList.add(success ? "success" : "error"); + writeButton.textContent = success ? "Write success" : "Write failed"; - setTimeout(() => { - writeButton.classList.remove("success", "error"); - writeButton.textContent = "Write Tag"; - }, 5000); + setTimeout(() => { + writeButton.classList.remove("success", "error"); + writeButton.textContent = "Write Tag"; + }, 5000); + } + + if(writeLocationButton.classList.contains("writing")){ + writeLocationButton.classList.remove("writing"); + writeLocationButton.classList.add(success ? "success" : "error"); + writeLocationButton.textContent = success ? "Write success" : "Write failed"; + + setTimeout(() => { + writeLocationButton.classList.remove("success", "error"); + writeLocationButton.textContent = "Write Location Tag"; + }, 5000); + } + + } function showNotification(message, isSuccess) { diff --git a/html/spoolman.js b/html/spoolman.js index 8193984..aba63f0 100644 --- a/html/spoolman.js +++ b/html/spoolman.js @@ -1,6 +1,7 @@ // Globale Variablen let spoolmanUrl = ''; let spoolsData = []; +let locationData = []; // Hilfsfunktionen für Datenmanipulation function processSpoolData(data) { @@ -133,6 +134,26 @@ function populateVendorDropdown(data, selectedSmId = null) { } } +// Dropdown-Funktionen +function populateLocationDropdown(data) { + const locationSelect = document.getElementById("locationSelect"); + if (!locationSelect) { + console.error('locationSelect Element nicht gefunden'); + return; + } + + locationSelect.innerHTML = ''; + // Dropdown mit gefilterten Herstellern befüllen - alphabetisch sortiert + Object.entries(data) + .sort(([, nameA], [, nameB]) => nameA.localeCompare(nameB)) // Sort vendors alphabetically by name + .forEach(([id, name]) => { + const option = document.createElement("option"); + option.value = name; + option.textContent = name; + locationSelect.appendChild(option); + }); +} + function updateFilamentDropdown(selectedSmId = null) { const vendorId = document.getElementById("vendorSelect").value; const dropdownContentInner = document.getElementById("filament-dropdown-content"); @@ -208,6 +229,13 @@ function updateFilamentDropdown(selectedSmId = null) { } } +function updateLocationSelect(){ + const writeLocationNfcButton = document.getElementById('writeLocationNfcButton'); + if(writeLocationNfcButton){ + writeLocationNfcButton.classList.remove("hidden"); + } +} + function selectFilament(spool) { const selectedColor = document.getElementById("selected-color"); const selectedText = document.getElementById("selected-filament"); @@ -261,10 +289,18 @@ async function initSpoolman() { const fetchedData = await fetchSpoolData(); spoolsData = processSpoolData(fetchedData); - + document.dispatchEvent(new CustomEvent('spoolDataLoaded', { detail: spoolsData })); + + locationData = await fetchLocationData(); + + document.dispatchEvent(new CustomEvent('locationDataLoaded', { + detail: locationData + })); + + } catch (error) { console.error('Fehler beim Initialisieren von Spoolman:', error); document.dispatchEvent(new CustomEvent('spoolmanError', { @@ -292,6 +328,25 @@ async function fetchSpoolData() { } } +async function fetchLocationData() { + try { + if (!spoolmanUrl) { + throw new Error('Spoolman URL ist nicht initialisiert'); + } + + const response = await fetch(`${spoolmanUrl}/api/v1/location`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error('Fehler beim Abrufen der Location-Daten:', error); + return []; + } +} + // Event Listener document.addEventListener('DOMContentLoaded', () => { initSpoolman(); @@ -300,6 +355,11 @@ document.addEventListener('DOMContentLoaded', () => { if (vendorSelect) { vendorSelect.addEventListener('change', () => updateFilamentDropdown()); } + + const locationSelect = document.getElementById('locationSelect'); + if (locationSelect) { + locationSelect.addEventListener('change', () => updateLocationSelect()); + } const onlyWithoutSmId = document.getElementById('onlyWithoutSmId'); if (onlyWithoutSmId) { @@ -312,6 +372,10 @@ document.addEventListener('DOMContentLoaded', () => { document.addEventListener('spoolDataLoaded', (event) => { populateVendorDropdown(event.detail); }); + + document.addEventListener('locationDataLoaded', (event) => { + populateLocationDropdown(event.detail); + }); window.onclick = function(event) { if (!event.target.closest('.custom-dropdown')) { @@ -342,6 +406,7 @@ window.getSpoolData = () => spoolsData; window.setSpoolData = (data) => { spoolsData = data; }; window.reloadSpoolData = initSpoolman; window.populateVendorDropdown = populateVendorDropdown; +window.populateLocationDropdown = populateLocationDropdown; window.updateFilamentDropdown = updateFilamentDropdown; window.toggleFilamentDropdown = () => { const content = document.getElementById("filament-dropdown-content"); diff --git a/html/style.css b/html/style.css index e0f37aa..d51700c 100644 --- a/html/style.css +++ b/html/style.css @@ -971,31 +971,35 @@ input[type="submit"]:disabled, } /* Schreib-Button */ -#writeNfcButton { +#writeNfcButton, #writeLocationNfcButton { background-color: #007bff; color: white; transition: background-color 0.3s, color 0.3s; width: 160px; } -#writeNfcButton.writing { +#writeNfcButton.writing, #writeLocationNfcButton.writing { background-color: #ffc107; color: black; width: 160px; } -#writeNfcButton.success { +#writeNfcButton.success, #writeLocationNfcButton.success { background-color: #28a745; color: white; width: 160px; } -#writeNfcButton.error { +#writeNfcButton.error, #writeLocationNfcButton.error { background-color: #dc3545; color: white; width: 160px; } +#writeLocationNfcButton{ + width: 250px; +} + @keyframes dots { 0% { content: ""; } 33% { content: "."; } @@ -1003,7 +1007,7 @@ input[type="submit"]:disabled, 100% { content: "..."; } } -#writeNfcButton.writing::after { +#writeNfcButton.writing::after, #writeLocationNfcButton.writing::after { content: "..."; animation: dots 1s steps(3, end) infinite; } diff --git a/src/api.cpp b/src/api.cpp index a8b3e2d..a100239 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -11,6 +11,7 @@ String octoUrl = ""; String octoToken = ""; struct SendToApiParams { + SpoolmanApiRequestType requestType; String httpType; String spoolsUrl; String updatePayload; @@ -90,6 +91,7 @@ void sendToApi(void *parameter) { SendToApiParams* params = (SendToApiParams*)parameter; // Extrahiere die Werte + SpoolmanApiRequestType requestType = params->requestType; String httpType = params->httpType; String spoolsUrl = params->spoolsUrl; String updatePayload = params->updatePayload; @@ -118,12 +120,15 @@ void sendToApi(void *parameter) { Serial.print("Fehler beim Parsen der JSON-Antwort: "); Serial.println(error.c_str()); } else { - if (httpType == "PUT") { + if (requestType == API_REQUEST_SPOOL_WEIGHT_UPDATE) { uint16_t remaining_weight = doc["remaining_weight"].as(); Serial.print("Aktuelles Gewicht: "); Serial.println(remaining_weight); oledShowMessage("Remaining: " + String(remaining_weight) + "g"); } + else if ( requestType == API_REQUEST_SPOOL_LOCATION_UPDATE) { + oledShowMessage("Location updated!"); + } vTaskDelay(3000 / portTICK_PERIOD_MS); doc.clear(); @@ -178,6 +183,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return false; } + params->requestType = API_REQUEST_SPOOL_TAG_ID_UPDATE; params->httpType = "PATCH"; params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; @@ -219,6 +225,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return 0; } + params->requestType = API_REQUEST_SPOOL_WEIGHT_UPDATE; params->httpType = "PUT"; params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; @@ -238,6 +245,45 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { return 1; } +uint8_t updateSpoolLocation(String spoolId, String location){ + String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId; + Serial.print("Update Spule mit URL: "); + Serial.println(spoolsUrl); + + // Update Payload erstellen + JsonDocument updateDoc; + updateDoc["location"] = location; + + String updatePayload; + serializeJson(updateDoc, updatePayload); + Serial.print("Update Payload: "); + Serial.println(updatePayload); + + SendToApiParams* params = new SendToApiParams(); + if (params == nullptr) { + Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); + return 0; + } + params->requestType = API_REQUEST_SPOOL_LOCATION_UPDATE; + params->httpType = "PATCH"; + params->spoolsUrl = spoolsUrl; + params->updatePayload = updatePayload; + + // 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) + ); + + updateDoc.clear(); + + return 1; +} + bool updateSpoolOcto(int spoolId) { String spoolsUrl = octoUrl + "/plugin/Spoolman/selectSpool"; Serial.print("Update Spule in Octoprint mit URL: "); @@ -257,6 +303,7 @@ bool updateSpoolOcto(int spoolId) { Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return false; } + params->requestType = API_REQUEST_OCTO_SPOOL_UPDATE; params->httpType = "POST"; params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; @@ -306,6 +353,7 @@ bool updateSpoolBambuData(String payload) { Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return false; } + params->requestType = API_REQUEST_BAMBU_UPDATE; params->httpType = "PATCH"; params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; @@ -510,6 +558,8 @@ bool checkSpoolmanInstance(const String& url) { return strcmp(status, "healthy") == 0; } } + } else { + Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); } http.end(); return false; diff --git a/src/api.h b/src/api.h index 88853c8..5311dfc 100644 --- a/src/api.h +++ b/src/api.h @@ -12,6 +12,14 @@ typedef enum { API_TRANSMITTING } spoolmanApiStateType; +typedef enum { + API_REQUEST_OCTO_SPOOL_UPDATE, + API_REQUEST_BAMBU_UPDATE, + API_REQUEST_SPOOL_TAG_ID_UPDATE, + API_REQUEST_SPOOL_WEIGHT_UPDATE, + API_REQUEST_SPOOL_LOCATION_UPDATE +} SpoolmanApiRequestType; + extern volatile spoolmanApiStateType spoolmanApiState; extern bool spoolman_connected; extern String spoolmanUrl; @@ -26,6 +34,7 @@ bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafeld JsonDocument fetchSingleSpoolInfo(int spoolId); // API-Funktion für die Webseite bool updateSpoolTagId(String uidString, const char* payload); // Neue Funktion zum Aktualisieren eines Spools uint8_t updateSpoolWeight(String spoolId, uint16_t weight); // Neue Funktion zum Aktualisieren des Gewichts +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 diff --git a/src/nfc.cpp b/src/nfc.cpp index 855405f..ea10267 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -218,11 +218,25 @@ 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"] != "") + if (doc.containsKey("sm_id") && doc["sm_id"] != "") { Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); spoolId = doc["sm_id"].as(); - } + } + else if(doc.containsKey("location") && doc["location"] != "") + { + Serial.println("Location Tag found!"); + String location = doc["location"].as(); + if(spoolId != ""){ + updateSpoolLocation(spoolId, location); + } + else + { + Serial.println("Location update tag scanned without scanning spool before!"); + oledShowMessage("No spool scanned before!"); + } + + } else { Serial.println("Keine SPOOL-ID gefunden."); From 6c9f290bac050eb416ae8945389066a491d9e2b8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 22 Jul 2025 06:31:51 +0200 Subject: [PATCH 131/366] fix: uncomment monitor_port configuration in platformio.ini --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 78dc2f5..161be14 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,6 +18,7 @@ platform = espressif32 board = esp32dev framework = arduino monitor_speed = 115200 +#monitor_port = /dev/cu.usbmodem01 lib_deps = tzapu/WiFiManager @ ^2.0.17 From 5bc6192b6ffcc14309e589abf21b648921e8d0ef Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 22 Jul 2025 06:36:16 +0200 Subject: [PATCH 132/366] docs: update platformio.ini for version v1.5.4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 161be14..61fa59f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.3" +version = "1.5.4" to_old_version = "1.5.0" ## From d490b116b9ed11a24994311c55835c89e17937ba Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 22 Jul 2025 06:36:16 +0200 Subject: [PATCH 133/366] docs: update changelog and header for version v1.5.4 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c432ce..4e17fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [1.5.4] - 2025-07-22 +### Added +- Adds new feature to write and read location tags +- Adds slight debouncing to the scale loop weight logic +- add loadcell desc. + +### Changed +- 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 + +### Fixed +- uncomment monitor_port configuration in platformio.ini + + ## [1.5.3] - 2025-04-25 ### Changed - update platformio.ini for version v1.5.3 From fd7b4c25b31f1d5cf090ad7f5d82d9b867e9b743 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Tue, 22 Jul 2025 10:47:47 +0200 Subject: [PATCH 134/366] Fixes some issues with the new location tags Fixes an issue where the location dropdown is not visible if the Bambu integration is active. Adds support for the "NFC-Tag" view on the webpage, it now also shows info about the location tags. Revers a change that was not supposed to go into main where the amount of data written to the spool tag is reduced to only the sm_id. --- html/rfid.js | 38 +++++++++++++++++++++++++++++--------- html/rfid_bambu.html | 12 ++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/html/rfid.js b/html/rfid.js index 6bdcea2..d3a54a5 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -555,7 +555,10 @@ function updateNfcData(data) { } // HTML für die Datenanzeige erstellen - let html = ` + let html = ""; + + if(data.sm_id){ + html = `

Brand: ${data.brand || 'N/A'}

Type: ${data.type || 'N/A'} ${data.color_hex ? `` : ''}

- `; + `; - // Spoolman ID anzeigen - html += `

Spoolman ID: ${data.sm_id || 'No Spoolman ID'}

`; + // Spoolman ID anzeigen + html += `

Spoolman ID: ${data.sm_id || 'No Spoolman ID'}

`; + } + else if(data.location) + { + html = ` +
+

Location: ${data.location || 'N/A'}

+ `; + } + else + { + html = ` +
+

Unknown tag

+ `; + } + + // Nur wenn eine sm_id vorhanden ist, aktualisiere die Dropdowns if (data.sm_id) { @@ -626,11 +646,11 @@ function writeNfcTag() { // Erstelle das NFC-Datenpaket mit korrekten Datentypen const nfcData = { - //color_hex: selectedSpool.filament.color_hex || "FFFFFF", - //type: selectedSpool.filament.material, - //min_temp: minTemp, - //max_temp: maxTemp, - //brand: selectedSpool.filament.vendor.name, + color_hex: selectedSpool.filament.color_hex || "FFFFFF", + type: selectedSpool.filament.material, + min_temp: minTemp, + max_temp: maxTemp, + brand: selectedSpool.filament.vendor.name, sm_id: String(selectedSpool.id) // Konvertiere zu String }; diff --git a/html/rfid_bambu.html b/html/rfid_bambu.html index b3b2527..9fc3210 100644 --- a/html/rfid_bambu.html +++ b/html/rfid_bambu.html @@ -139,6 +139,18 @@

+ +
+

Spoolman Locations

+ +
+ +
+

+ +
From 37df07f102fb657f8e3da0a566da2026f5cc4b91 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 22 Jul 2025 17:36:45 +0200 Subject: [PATCH 135/366] docs: update platformio.ini for version v1.5.5 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 61fa59f..dc7cd21 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.4" +version = "1.5.5" to_old_version = "1.5.0" ## From 3bb6c1caf505b0ca487de01691957da875b9ace8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 22 Jul 2025 17:36:45 +0200 Subject: [PATCH 136/366] docs: update changelog and header for version v1.5.5 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e17fc3..91d61d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [1.5.5] - 2025-07-22 +### Added +- Fixes some issues with the new location tags + +### Changed +- update platformio.ini for version v1.5.5 + +### Fixed +- Merge pull request #40 from janecker/location_bambu_fix + + ## [1.5.4] - 2025-07-22 ### Added - Adds new feature to write and read location tags From 8343fe887b6230ea74ee48ae0a5bf505a0307af8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:14:58 +0200 Subject: [PATCH 137/366] Introduces new heap debugging feature and fixes some memory leaks in website feature Introduces a new define HEAP_DEBUG_MESSAGE(location) that can be used to instrument the code to get heap information output on the Serial output. It can be enabled via the define ENABLE_HEAP_DEBUGGING. Also fixes some memory leaks in the website part of the project. --- src/debug.h | 12 ++++++++++++ src/website.cpp | 10 ++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/debug.h diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..8cc1efc --- /dev/null +++ b/src/debug.h @@ -0,0 +1,12 @@ +#include + + +#ifdef ENABLE_HEAP_DEBUGGING + #define HEAP_DEBUG_MESSAGE(location) printHeapDebugData(location); +#else + #define HEAP_DEBUG_MESSAGE(location) +#endif + +inline void printHeapDebugData(String location){ + Serial.println("Heap: " + String(ESP.getMinFreeHeap()/1024) + "\t" + String(ESP.getFreeHeap()/1024) + "\t" + String(ESP.getMaxAllocHeap()/1024) + "\t" + location); +} \ No newline at end of file diff --git a/src/website.cpp b/src/website.cpp index 0ff02db..56ddf78 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -10,6 +10,7 @@ #include #include "display.h" #include "ota.h" +#include "debug.h" #ifndef VERSION #define VERSION "1.1.0" @@ -26,6 +27,7 @@ nfcReaderStateType lastnfcReaderState = NFC_IDLE; void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { + HEAP_DEBUG_MESSAGE("onWsEvent begin"); if (type == WS_EVT_CONNECT) { Serial.println("Neuer Client verbunden!"); // Sende die AMS-Daten an den neuen Client @@ -33,6 +35,10 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp sendNfcData(client); foundNfcTag(client, 0); sendWriteResult(client, 3); + + // Clean up dead connections + (*server).cleanupClients(); + Serial.println("Currently connected number of clients: " + String((*server).getClients().size())); } else if (type == WS_EVT_DISCONNECT) { Serial.println("Client getrennt."); } else if (type == WS_EVT_ERROR) { @@ -113,7 +119,9 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp else { Serial.println("Unbekannter WebSocket-Typ: " + doc["type"].as()); } + doc.clear(); } + HEAP_DEBUG_MESSAGE("onWsEvent end"); } // Funktion zum Laden und Ersetzen des Headers in einer HTML-Datei @@ -280,6 +288,8 @@ void setupWebserver(AsyncWebServer &server) { html.replace("{{autoSendTime}}", String(autoSetBambuAmsCounter)); } + doc.clear(); + request->send(200, "text/html", html); }); From f038020042ee306748c0a4dd9b96784e1b2205d8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:36:04 +0200 Subject: [PATCH 138/366] Memory leak fixes in api and nfc, location tag fix Fixes multiple potential memory leaks in API and NFC. Also fixes an issue in the new locaiton tag feature that could lead to multiple parallel API requests. This could cause memory leak issues but also result in wrong weights being registered for a spool. --- src/api.cpp | 26 ++++++++++++++++++++++++-- src/main.cpp | 6 +++--- src/nfc.cpp | 17 ++++++++++++----- src/nfc.h | 3 ++- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index a100239..5d86c6e 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -2,6 +2,7 @@ #include #include #include "commonFS.h" +#include "debug.h" volatile spoolmanApiStateType spoolmanApiState = API_INIT; //bool spoolman_connected = false; @@ -87,6 +88,8 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) { } void sendToApi(void *parameter) { + HEAP_DEBUG_MESSAGE("sendToApi begin"); + spoolmanApiState = API_TRANSMITTING; SendToApiParams* params = (SendToApiParams*)parameter; @@ -131,8 +134,8 @@ void sendToApi(void *parameter) { } vTaskDelay(3000 / portTICK_PERIOD_MS); - doc.clear(); } + doc.clear(); } else { Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); @@ -145,8 +148,9 @@ void sendToApi(void *parameter) { // Speicher freigeben delete params; - vTaskDelete(NULL); + HEAP_DEBUG_MESSAGE("sendToApi end"); spoolmanApiState = API_IDLE; + vTaskDelete(NULL); } bool updateSpoolTagId(String uidString, const char* payload) { @@ -169,6 +173,8 @@ bool updateSpoolTagId(String uidString, const char* payload) { Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); + doc.clear(); + // Update Payload erstellen JsonDocument updateDoc; updateDoc["extra"]["nfc_id"] = "\""+uidString+"\""; @@ -207,6 +213,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { } uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { + HEAP_DEBUG_MESSAGE("updateSpoolWeight begin"); String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId + "/measure"; Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); @@ -241,11 +248,14 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { ); updateDoc.clear(); + HEAP_DEBUG_MESSAGE("updateSpoolWeight end"); return 1; } uint8_t updateSpoolLocation(String spoolId, String location){ + HEAP_DEBUG_MESSAGE("updateSpoolLocation begin"); + String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId; Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); @@ -281,6 +291,7 @@ uint8_t updateSpoolLocation(String spoolId, String location){ updateDoc.clear(); + HEAP_DEBUG_MESSAGE("updateSpoolLocation end"); return 1; } @@ -345,6 +356,10 @@ bool updateSpoolBambuData(String payload) { String updatePayload; serializeJson(updateDoc, updatePayload); + + doc.clear(); + updateDoc.clear(); + Serial.print("Update Payload: "); Serial.println(updatePayload); @@ -511,6 +526,7 @@ bool checkSpoolmanExtraFields() { vTaskDelay(100 / portTICK_PERIOD_MS); } } + doc.clear(); } } @@ -557,6 +573,8 @@ bool checkSpoolmanInstance(const String& url) { oledShowTopRow(); return strcmp(status, "healthy") == 0; } + + doc.clear(); } } else { Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); @@ -584,6 +602,8 @@ bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const octoUrl = octoWh; octoToken = octoTk; + doc.clear(); + return true; } @@ -600,6 +620,8 @@ String loadSpoolmanUrl() { return doc["url"].as(); } Serial.println("Keine gültige Spoolman-URL gefunden."); + + doc.clear(); return ""; } diff --git a/src/main.cpp b/src/main.cpp index 01763d4..9980cbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -212,14 +212,14 @@ void loop() { lastWeight = weight; // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden - if (spoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS) { + if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS) { oledShowIcon("loading"); - if (updateSpoolWeight(spoolId, weight)) + if (updateSpoolWeight(activeSpoolId, weight)) { oledShowIcon("success"); vTaskDelay(2000 / portTICK_PERIOD_MS); weightSend = 1; - autoSetToBambuSpoolId = spoolId.toInt(); + autoSetToBambuSpoolId = activeSpoolId.toInt(); if (octoEnabled) { diff --git a/src/nfc.cpp b/src/nfc.cpp index ea10267..47dbab4 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -14,7 +14,8 @@ Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); TaskHandle_t RfidReaderTask; JsonDocument rfidData; -String spoolId = ""; +String activeSpoolId = ""; +String lastSpoolId = ""; String nfcJsonData = ""; volatile bool pauseBambuMqttTask = false; @@ -64,6 +65,8 @@ void payloadToJson(uint8_t *data) { Serial.print("deserializeJson() failed: "); Serial.println(error.f_str()); } + + doc.clear(); } else { Serial.println("Kein gültiger JSON-Inhalt gefunden oder fehlerhafte Formatierung."); //writeJsonToTag("{\"version\":\"1.0\",\"protocol\":\"NFC\",\"color_hex\":\"#FFFFFF\",\"type\":\"Example\",\"min_temp\":10,\"max_temp\":30,\"brand\":\"BrandName\"}"); @@ -221,14 +224,15 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { if (doc.containsKey("sm_id") && doc["sm_id"] != "") { Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); - spoolId = doc["sm_id"].as(); + activeSpoolId = doc["sm_id"].as(); + lastSpoolId = activeSpoolId; } else if(doc.containsKey("location") && doc["location"] != "") { Serial.println("Location Tag found!"); String location = doc["location"].as(); - if(spoolId != ""){ - updateSpoolLocation(spoolId, location); + if(lastSpoolId != ""){ + updateSpoolLocation(lastSpoolId, location); } else { @@ -240,12 +244,14 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { else { Serial.println("Keine SPOOL-ID gefunden."); - spoolId = ""; + activeSpoolId = ""; oledShowMessage("Unknown Spool"); vTaskDelay(2000 / portTICK_PERIOD_MS); } } + doc.clear(); + return true; } @@ -446,6 +452,7 @@ void scanRfidTask(void * parameter) { nfcReaderState = NFC_IDLE; //uidString = ""; nfcJsonData = ""; + activeSpoolId = ""; Serial.println("Tag entfernt"); if (!autoSendToBambu) oledShowWeight(weight); } diff --git a/src/nfc.h b/src/nfc.h index 0d964f2..8f8cf5a 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -19,7 +19,8 @@ void startWriteJsonToTag(const char* payload); extern TaskHandle_t RfidReaderTask; extern String nfcJsonData; -extern String spoolId; +extern String activeSpoolId; +extern String lastSpoolId; extern volatile nfcReaderStateType nfcReaderState; extern volatile bool pauseBambuMqttTask; From 7e76612bb4d3cf6adaec7636cc42394b9b8eaba7 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:39:37 +0200 Subject: [PATCH 139/366] Adds data directory and further .vscode files to to .gitignore Adds the whole data folder that is created during build of the project and further visual studio code related files to the .gitignore file. --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f5d62f --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +.vscode/extensions.json +.vscode/settings.json +data \ No newline at end of file From 5d2d5e9ee188c4c5f0f0bea4db01669bef968b03 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:50:08 +0200 Subject: [PATCH 140/366] Adds ENABLE_HEAP_DEBUGGING define as comment to the build flags Adds the new ENABLE_HEAP_DEBUGGING define to the build falgs. The option is commented out, but it makes it easier to quickly enable it --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index dc7cd21..c1ba693 100644 --- a/platformio.ini +++ b/platformio.ini @@ -52,6 +52,7 @@ build_flags = -mtext-section-literals -DVERSION=\"${common.version}\" -DTOOLDVERSION=\"${common.to_old_version}\" + #-DENABLE_HEAP_DEBUGGING -DASYNCWEBSERVER_REGEX #-DCORE_DEBUG_LEVEL=3 -DCONFIG_ARDUHAL_LOG_COLORS=1 From bf48c6d4e1183f018ca42b225b55fa62d9f94508 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:52:10 +0200 Subject: [PATCH 141/366] Fixes compiler warnings in nfc Replaces the depricated function call containsKey() with is() of JsonDocument. --- src/nfc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 47dbab4..1003835 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -221,13 +221,13 @@ 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.containsKey("sm_id") && doc["sm_id"] != "") + if (doc["sm_id"].is() && doc["sm_id"] != "") { Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); activeSpoolId = doc["sm_id"].as(); lastSpoolId = activeSpoolId; } - else if(doc.containsKey("location") && doc["location"] != "") + else if(doc["location"].is() && doc["location"] != "") { Serial.println("Location Tag found!"); String location = doc["location"].as(); From cb5d8ac10aecf700add55cdded442b181721da7e Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sun, 27 Jul 2025 17:33:09 +0200 Subject: [PATCH 142/366] Changes configuration storage of spoolman and bambu values Change that moves configuration values of spoolman and bambu credentials to use NVS storage. Also fixes some typos and missing translation. --- .gitignore | 5 ++ html/spoolman.html | 16 ++--- src/api.cpp | 47 +++++++------- src/bambu.cpp | 148 +++++++++++++++++++++------------------------ src/bambu.h | 11 +++- src/config.cpp | 2 - src/config.h | 25 +++++++- src/main.cpp | 8 +-- src/nfc.cpp | 3 +- src/scale.cpp | 16 +++-- src/website.cpp | 34 +++-------- 11 files changed, 158 insertions(+), 157 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/html/spoolman.html b/html/spoolman.html index 912948d..49abe55 100644 --- a/html/spoolman.html +++ b/html/spoolman.html @@ -146,20 +146,20 @@
-
Set URL/IP to your Spoolman-Instanz
- -
If you want to enable sending Spool to Spoolman Octoprint Plugin:
+
Set URL/IP to your Spoolman instance
+ +
If you want to enable sending the spool to the Spoolman Octoprint plugin:

Send to Octo-Plugin

- +

@@ -169,16 +169,16 @@
Bambu Lab Printer Credentials
- +
- +
- +

If activated, FilaMan will automatically update the next filled tray with the last scanned and weighed spool.

diff --git a/src/api.cpp b/src/api.cpp index a100239..12a96d8 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -2,6 +2,7 @@ #include #include #include "commonFS.h" +#include volatile spoolmanApiStateType spoolmanApiState = API_INIT; //bool spoolman_connected = false; @@ -565,42 +566,36 @@ bool checkSpoolmanInstance(const String& url) { return false; } -bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk) { - if (!checkSpoolmanInstance(url)) return false; +bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, const String& octoTk) { + Preferences preferences; + preferences.begin(NVS_NAMESPACE_API, false); // false = readwrite + preferences.putString(NVS_KEY_SPOOLMAN_URL, url); + preferences.putBool(NVS_KEY_OCTOPRINT_ENABLED, octoOn); + preferences.putString(NVS_KEY_OCTOPRINT_URL, octo_url); + preferences.putString(NVS_KEY_OCTOPRINT_TOKEN, octoTk); + preferences.end(); - JsonDocument doc; - doc["url"] = url; - doc["octoEnabled"] = octoOn; - doc["octoUrl"] = octoWh; - doc["octoToken"] = octoTk; - Serial.print("Speichere Spoolman Data in Datei: "); - Serial.println(doc.as()); - if (!saveJsonValue("/spoolman_url.json", doc)) { - Serial.println("Fehler beim Speichern der Spoolman-URL."); - return false; - } + //TBD: This could be handled nicer in the future spoolmanUrl = url; octoEnabled = octoOn; - octoUrl = octoWh; + octoUrl = octo_url; octoToken = octoTk; return true; } String loadSpoolmanUrl() { - JsonDocument doc; - if (loadJsonValue("/spoolman_url.json", doc) && doc["url"].is()) { - octoEnabled = (doc["octoEnabled"].is()) ? doc["octoEnabled"].as() : false; - if (octoEnabled && doc["octoToken"].is() && doc["octoUrl"].is()) - { - octoUrl = doc["octoUrl"].as(); - octoToken = doc["octoToken"].as(); - } - - return doc["url"].as(); + Preferences preferences; + preferences.begin(NVS_NAMESPACE_API, true); + String spoolmanUrl = preferences.getString(NVS_KEY_SPOOLMAN_URL, ""); + octoEnabled = preferences.getBool(NVS_KEY_OCTOPRINT_ENABLED, false); + if(octoEnabled) + { + octoUrl = preferences.getString(NVS_KEY_OCTOPRINT_URL, ""); + octoToken = preferences.getString(NVS_KEY_OCTOPRINT_TOKEN, ""); } - Serial.println("Keine gültige Spoolman-URL gefunden."); - return ""; + preferences.end(); + return spoolmanUrl; } bool initSpoolman() { diff --git a/src/bambu.cpp b/src/bambu.cpp index 0225dae..c738ec8 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -10,6 +10,7 @@ #include "esp_task_wdt.h" #include "config.h" #include "display.h" +#include WiFiClient espClient; SSLClient sslClient(&espClient); @@ -17,22 +18,13 @@ PubSubClient client(sslClient); TaskHandle_t BambuMqttTask; -String topic = ""; -//String request_topic = ""; -const char* bambu_username = "bblp"; -const char* bambu_ip = nullptr; -const char* bambu_accesscode = nullptr; -const char* bambu_serialnr = nullptr; - -String g_bambu_ip = ""; -String g_bambu_accesscode = ""; -String g_bambu_serialnr = ""; bool bambuDisabled = false; bool bambu_connected = false; -bool autoSendToBambu = false; int autoSetToBambuSpoolId = 0; +BambuCredentials bambuCredentials; + // Globale Variablen für AMS-Daten int ams_count = 0; String amsJsonData; // Speichert das fertige JSON für WebSocket-Clients @@ -43,18 +35,22 @@ bool removeBambuCredentials() { vTaskDelete(BambuMqttTask); } - if (!removeJsonValue("/bambu_credentials.json")) { - Serial.println("Fehler beim Löschen der Bambu-Credentials."); - return false; - } + Preferences preferences; + preferences.begin(NVS_NAMESPACE_BAMBU, false); // false = readwrite + preferences.remove(NVS_KEY_BAMBU_IP); + preferences.remove(NVS_KEY_BAMBU_SERIAL); + preferences.remove(NVS_KEY_BAMBU_ACCESSCODE); + preferences.remove(NVS_KEY_BAMBU_AUTOSEND_ENABLE); + preferences.remove(NVS_KEY_BAMBU_AUTOSEND_TIME); + preferences.end(); + // Löschen der globalen Variablen - g_bambu_ip = ""; - g_bambu_accesscode = ""; - g_bambu_serialnr = ""; - bambu_ip = nullptr; - bambu_accesscode = nullptr; - bambu_serialnr = nullptr; - autoSendToBambu = false; + bambuCredentials.ip = ""; + bambuCredentials.serial = ""; + bambuCredentials.accesscode = ""; + bambuCredentials.autosend_enable = false; + bambuCredentials.autosend_time = BAMBU_DEFAULT_AUTOSEND_TIME; + autoSetToBambuSpoolId = 0; ams_count = 0; amsJsonData = ""; @@ -68,25 +64,21 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String if (BambuMqttTask) { vTaskDelete(BambuMqttTask); } - - JsonDocument doc; - doc["bambu_ip"] = ip; - doc["bambu_accesscode"] = accesscode; - doc["bambu_serialnr"] = serialnr; - doc["autoSendToBambu"] = autoSend; - doc["autoSendTime"] = (autoSendTime != "") ? autoSendTime.toInt() : autoSetBambuAmsCounter; - if (!saveJsonValue("/bambu_credentials.json", doc)) { - Serial.println("Fehler beim Speichern der Bambu-Credentials."); - return false; - } + bambuCredentials.ip = ip.c_str(); + bambuCredentials.serial = serialnr.c_str(); + bambuCredentials.accesscode = accesscode.c_str(); + bambuCredentials.autosend_enable = autoSend; + bambuCredentials.autosend_time = autoSendTime.toInt(); - // Dynamische Speicherallokation für die globalen Pointer - bambu_ip = ip.c_str(); - bambu_accesscode = accesscode.c_str(); - bambu_serialnr = serialnr.c_str(); - autoSendToBambu = autoSend; - autoSetBambuAmsCounter = autoSendTime.toInt(); + Preferences preferences; + preferences.begin(NVS_NAMESPACE_BAMBU, false); // false = readwrite + preferences.putString(NVS_KEY_BAMBU_IP, bambuCredentials.ip); + preferences.putString(NVS_KEY_BAMBU_SERIAL, bambuCredentials.serial); + preferences.putString(NVS_KEY_BAMBU_ACCESSCODE, bambuCredentials.accesscode); + preferences.putBool(NVS_KEY_BAMBU_AUTOSEND_ENABLE, bambuCredentials.autosend_enable); + preferences.putInt(NVS_KEY_BAMBU_AUTOSEND_TIME, bambuCredentials.autosend_time); + preferences.end(); vTaskDelay(100 / portTICK_PERIOD_MS); if (!setupMqtt()) return false; @@ -95,35 +87,36 @@ bool saveBambuCredentials(const String& ip, const String& serialnr, const String } bool loadBambuCredentials() { - JsonDocument doc; - if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is()) { - // Temporäre Strings für die Werte - String ip = doc["bambu_ip"].as(); - String code = doc["bambu_accesscode"].as(); - String serial = doc["bambu_serialnr"].as(); + Preferences preferences; + preferences.begin(NVS_NAMESPACE_BAMBU, true); + String ip = preferences.getString(NVS_KEY_BAMBU_IP, ""); + String serial = preferences.getString(NVS_KEY_BAMBU_SERIAL, ""); + String code = preferences.getString(NVS_KEY_BAMBU_ACCESSCODE, ""); + bool autosendEnable = preferences.getBool(NVS_KEY_BAMBU_AUTOSEND_ENABLE, false); + int autosendTime = preferences.getInt(NVS_KEY_BAMBU_AUTOSEND_TIME, BAMBU_DEFAULT_AUTOSEND_TIME); + preferences.end(); - g_bambu_ip = ip; - g_bambu_accesscode = code; - g_bambu_serialnr = serial; + if(ip != ""){ + bambuCredentials.ip = ip.c_str(); + bambuCredentials.serial = serial.c_str(); + bambuCredentials.accesscode = code.c_str(); + bambuCredentials.autosend_enable = autosendEnable; + bambuCredentials.autosend_time = autosendTime; - if (doc["autoSendToBambu"].is()) autoSendToBambu = doc["autoSendToBambu"].as(); - if (doc["autoSendTime"].is()) autoSetBambuAmsCounter = doc["autoSendTime"].as(); + Serial.println("credentials loaded loadCredentials!"); + Serial.println(bambuCredentials.ip); + Serial.println(bambuCredentials.serial); + Serial.println(bambuCredentials.accesscode); + Serial.println(String(bambuCredentials.autosend_enable)); + Serial.println(String(bambuCredentials.autosend_time)); - ip.trim(); - code.trim(); - serial.trim(); - - // Dynamische Speicherallokation für die globalen Pointer - bambu_ip = g_bambu_ip.c_str(); - bambu_accesscode = g_bambu_accesscode.c_str(); - bambu_serialnr = g_bambu_serialnr.c_str(); - - topic = "device/" + String(bambu_serialnr); - //request_topic = "device/" + String(bambu_serialnr) + "/request"; return true; } - Serial.println("Keine gültigen Bambu-Credentials gefunden."); - return false; + else + { + Serial.println("Keine gültigen Bambu-Credentials gefunden."); + return false; + } } struct FilamentResult { @@ -226,7 +219,7 @@ FilamentResult findFilamentIdx(String brand, String type) { bool sendMqttMessage(const String& payload) { Serial.println("Sending MQTT message"); Serial.println(payload); - if (client.publish((String(topic) + "/request").c_str(), payload.c_str())) + if (client.publish(("device/"+bambuCredentials.serial+"/request").c_str(), payload.c_str())) { return true; } @@ -499,7 +492,7 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) { trayObj["cali_idx"].as() != ams_data[storedIndex].trays[j].cali_idx) { hasChanges = true; - if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges) + if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0 && hasChanges) { autoSetSpool(autoSetToBambuSpoolId, ams_data[storedIndex].trays[j].id); } @@ -523,7 +516,7 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) { (vtTray["tray_type"].as() != "" && vtTray["cali_idx"].as() != ams_data[i].trays[0].cali_idx)) { hasChanges = true; - if (autoSendToBambu && autoSetToBambuSpoolId > 0 && hasChanges) + if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0 && hasChanges) { autoSetSpool(autoSetToBambuSpoolId, 254); } @@ -580,11 +573,11 @@ void reconnect() { oledShowTopRow(); // Attempt to connect - String clientId = String(bambu_serialnr) + "_" + String(random(0, 100)); - if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode)) { + String clientId = bambuCredentials.serial + "_" + String(random(0, 100)); + if (client.connect(clientId.c_str(), BAMBU_USERNAME, bambuCredentials.accesscode.c_str())) { Serial.println("MQTT re/connected"); - client.subscribe((String(topic) + "/report").c_str()); + client.subscribe(("device/"+bambuCredentials.serial+"/report").c_str()); bambu_connected = true; oledShowTopRow(); } else { @@ -630,28 +623,23 @@ void mqtt_loop(void * parameter) { bool setupMqtt() { // Wenn Bambu Daten vorhanden - bool success = loadBambuCredentials(); + //bool success = loadBambuCredentials(); - if (!success) { - bambuDisabled = true; - return false; - } - - if (success && bambu_ip != "" && bambu_accesscode != "" && bambu_serialnr != "") + if (bambuCredentials.ip != "" && bambuCredentials.accesscode != "" && bambuCredentials.serial != "") { bambuDisabled = false; sslClient.setCACert(root_ca); sslClient.setInsecure(); - client.setServer(bambu_ip, 8883); + client.setServer(bambuCredentials.ip.c_str(), 8883); // Verbinden mit dem MQTT-Server bool connected = true; - String clientId = String(bambu_serialnr) + "_" + String(random(0, 100)); - if (client.connect(clientId.c_str(), bambu_username, bambu_accesscode)) + String clientId = String(bambuCredentials.serial) + "_" + String(random(0, 100)); + if (client.connect(bambuCredentials.ip.c_str(), BAMBU_USERNAME, bambuCredentials.accesscode.c_str())) { client.setCallback(mqtt_callback); client.setBufferSize(15488); - client.subscribe((String(topic) + "/report").c_str()); + client.subscribe(("device/"+bambuCredentials.serial+"/report").c_str()); Serial.println("MQTT-Client initialisiert"); oledShowMessage("Bambu Connected"); diff --git a/src/bambu.h b/src/bambu.h index aef6c3b..bf8836e 100644 --- a/src/bambu.h +++ b/src/bambu.h @@ -16,6 +16,14 @@ struct TrayData { String cali_idx; }; +struct BambuCredentials { + String ip; + String serial; + String accesscode; + bool autosend_enable; + int autosend_time; +}; + #define MAX_AMS 17 // 16 normale AMS + 1 externe Spule extern String amsJsonData; // Für die vorbereiteten JSON-Daten @@ -28,9 +36,10 @@ extern bool bambu_connected; extern int ams_count; extern AMSData ams_data[MAX_AMS]; -extern bool autoSendToBambu; +//extern bool autoSendToBambu; extern int autoSetToBambuSpoolId; extern bool bambuDisabled; +extern BambuCredentials bambuCredentials; bool removeBambuCredentials(); bool loadBambuCredentials(); diff --git a/src/config.cpp b/src/config.cpp index dd601c6..644177e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -46,8 +46,6 @@ const uint8_t webserverPort = 80; const char* apiUrl = "/api/v1"; // ***** API -// ***** Bambu Auto Set Spool -uint8_t autoSetBambuAmsCounter = 60; // ***** Bambu Auto Set Spool // ***** Task Prios diff --git a/src/config.h b/src/config.h index dd6cb20..ecccd51 100644 --- a/src/config.h +++ b/src/config.h @@ -3,6 +3,29 @@ #include +#define BAMBU_DEFAULT_AUTOSEND_TIME 60 + + +#define NVS_NAMESPACE_API "api" +#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl" +#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled" +#define NVS_KEY_OCTOPRINT_URL "octoUrl" +#define NVS_KEY_OCTOPRINT_TOKEN "octoToken" + +#define NVS_NAMESPACE_BAMBU "bambu" +#define NVS_KEY_BAMBU_IP "bambuIp" +#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode" +#define NVS_KEY_BAMBU_SERIAL "bambuSerial" +#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable" +#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime" + +#define NVS_NAMESPACE_SCALE "scale" +#define NVS_KEY_CALIBRATION "cal_value" +#define NVS_KEY_AUTOTARE "auto_tare" + +#define BAMBU_USERNAME "bblp" + + extern const uint8_t PN532_IRQ; extern const uint8_t PN532_RESET; @@ -25,7 +48,7 @@ extern const uint8_t OLED_DATA_END; extern const char* apiUrl; extern const uint8_t webserverPort; -extern uint8_t autoSetBambuAmsCounter; + extern const unsigned char wifi_on[]; extern const unsigned char wifi_off[]; diff --git a/src/main.cpp b/src/main.cpp index 01763d4..76de6f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,7 +119,7 @@ void loop() { } // Wenn Bambu auto set Spool aktiv - if (autoSendToBambu && autoSetToBambuSpoolId > 0) + if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0) { if (!bambuDisabled && !bambu_connected) { @@ -131,10 +131,10 @@ void loop() { if (nfcReaderState == NFC_IDLE) { lastAutoSetBambuAmsTime = currentMillis; - oledShowMessage("Auto Set " + String(autoSetBambuAmsCounter - autoAmsCounter) + "s"); + oledShowMessage("Auto Set " + String(bambuCredentials.autosend_time - autoAmsCounter) + "s"); autoAmsCounter++; - if (autoAmsCounter >= autoSetBambuAmsCounter) + if (autoAmsCounter >= bambuCredentials.autosend_time) { autoSetToBambuSpoolId = 0; autoAmsCounter = 0; @@ -162,7 +162,7 @@ void loop() { // Ausgabe der Waage auf Display if(pauseMainTask == 0) { - if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!autoSendToBambu || autoSetToBambuSpoolId == 0))) + if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0))) { (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); } diff --git a/src/nfc.cpp b/src/nfc.cpp index ea10267..83bfe7c 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -7,6 +7,7 @@ #include "api.h" #include "esp_task_wdt.h" #include "scale.h" +#include "bambu.h" //Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); @@ -447,7 +448,7 @@ void scanRfidTask(void * parameter) { //uidString = ""; nfcJsonData = ""; Serial.println("Tag entfernt"); - if (!autoSendToBambu) oledShowWeight(weight); + if (!bambuCredentials.autosend_enable) oledShowWeight(weight); } // aktualisieren der Website wenn sich der Status ändert diff --git a/src/scale.cpp b/src/scale.cpp index 83edeeb..8172d9f 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -18,11 +18,6 @@ uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; uint8_t pauseMainTask = 0; uint8_t scaleCalibrated = 1; - -Preferences preferences; -const char* NVS_NAMESPACE = "scale"; -const char* NVS_KEY_CALIBRATION = "cal_value"; -const char* NVS_KEY_AUTOTARE = "auto_tare"; bool autoTare = true; // ##### Funktionen für Waage ##### @@ -32,7 +27,8 @@ uint8_t setAutoTare(bool autoTareValue) { autoTare = autoTareValue; // Speichern mit NVS - preferences.begin(NVS_NAMESPACE, false); // false = readwrite + Preferences preferences; + preferences.begin(NVS_NAMESPACE_SCALE, false); // false = readwrite preferences.putBool(NVS_KEY_AUTOTARE, autoTare); preferences.end(); @@ -90,7 +86,8 @@ void start_scale(bool touchSensorConnected) { float calibrationValue; // NVS lesen - preferences.begin(NVS_NAMESPACE, true); // true = readonly + Preferences preferences; + preferences.begin(NVS_NAMESPACE_SCALE, true); // true = readonly calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue); // auto Tare @@ -197,12 +194,13 @@ uint8_t calibrate_scale() { Serial.println(newCalibrationValue); // Speichern mit NVS - preferences.begin(NVS_NAMESPACE, false); // false = readwrite + Preferences preferences; + preferences.begin(NVS_NAMESPACE_SCALE, false); // false = readwrite preferences.putFloat(NVS_KEY_CALIBRATION, newCalibrationValue); preferences.end(); // Verifizieren - preferences.begin(NVS_NAMESPACE, true); + preferences.begin(NVS_NAMESPACE_SCALE, true); float verifyValue = preferences.getFloat(NVS_KEY_CALIBRATION, 0); preferences.end(); diff --git a/src/website.cpp b/src/website.cpp index 0ff02db..d554235 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -10,6 +10,7 @@ #include #include "display.h" #include "ota.h" +#include "config.h" #ifndef VERSION #define VERSION "1.1.0" @@ -195,6 +196,9 @@ void setupWebserver(AsyncWebServer &server) { Serial.print("Geladene Spoolman-URL: "); Serial.println(spoolmanUrl); + // Load Bamb credentials: + loadBambuCredentials(); + // Route für about server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("Anfrage für /about erhalten"); @@ -254,31 +258,11 @@ void setupWebserver(AsyncWebServer &server) { html.replace("{{spoolmanOctoUrl}}", (octoUrl != "") ? octoUrl : ""); html.replace("{{spoolmanOctoToken}}", (octoToken != "") ? octoToken : ""); - JsonDocument doc; - if (loadJsonValue("/bambu_credentials.json", doc) && doc["bambu_ip"].is()) - { - String bambuIp = doc["bambu_ip"].as(); - String bambuSerial = doc["bambu_serialnr"].as(); - String bambuCode = doc["bambu_accesscode"].as(); - autoSendToBambu = doc["autoSendToBambu"].as(); - bambuIp.trim(); - bambuSerial.trim(); - bambuCode.trim(); - - html.replace("{{bambuIp}}", bambuIp ? bambuIp : ""); - html.replace("{{bambuSerial}}", bambuSerial ? bambuSerial : ""); - html.replace("{{bambuCode}}", bambuCode ? bambuCode : ""); - html.replace("{{autoSendToBambu}}", autoSendToBambu ? "checked" : ""); - html.replace("{{autoSendTime}}", String(autoSetBambuAmsCounter)); - } - else - { - html.replace("{{bambuIp}}", ""); - html.replace("{{bambuSerial}}", ""); - html.replace("{{bambuCode}}", ""); - html.replace("{{autoSendToBambu}}", ""); - html.replace("{{autoSendTime}}", String(autoSetBambuAmsCounter)); - } + html.replace("{{bambuIp}}", bambuCredentials.ip); + html.replace("{{bambuSerial}}", bambuCredentials.serial); + html.replace("{{bambuCode}}", bambuCredentials.accesscode ? bambuCredentials.accesscode : ""); + html.replace("{{autoSendToBambu}}", bambuCredentials.autosend_enable ? "checked" : ""); + html.replace("{{autoSendTime}}", (bambuCredentials.autosend_time != 0) ? String(bambuCredentials.autosend_time) : String(BAMBU_DEFAULT_AUTOSEND_TIME)); request->send(200, "text/html", html); }); From c919eeb8481875a4f05d1195cbc3eeb00f146e88 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 28 Jul 2025 09:32:30 +0200 Subject: [PATCH 143/366] docs: update platformio.ini for version v1.5.6 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c1ba693..611ed51 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.5" +version = "1.5.6" to_old_version = "1.5.0" ## From 5f8953a19d89ea15fab3db426be62eee9c35632d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 28 Jul 2025 09:32:35 +0200 Subject: [PATCH 144/366] docs: update webpages for version v1.5.6 --- html/.DS_Store | Bin 0 -> 6148 bytes html/bambu_credentials.json | 1 + html/spoolman_url.json | 1 + 3 files changed, 2 insertions(+) create mode 100644 html/.DS_Store create mode 100644 html/bambu_credentials.json create mode 100644 html/spoolman_url.json diff --git a/html/.DS_Store b/html/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..68ead1702758a26b6df9c1f25d3977e3b2071d37 GIT binary patch literal 6148 zcmeHKJxc>Y5Pcg{L~K%6SneKIU)DOg_^l**wOa?c=;2U#^z*f-&b9VT~nfX1qd%Tl!70V!xy{L%|hmYK9w* zODxn{(K4e~N#6_;;u~?ueWskb(%DQ`nBxqmoO|Lbm3sf|oY(1`-@e-}Cdbd@3^)VM zz%Mbtnk~{hF!a_La0Z-#4FmFhh*ZHmVPmMD4mSD(Aa-e1VPD=75)%{V2^&MsP=bXL zEi|MjMzC<&WAe)rHij0CpgVJ&v~x%=l%TuQ9@QNoH}uvSa0a#+*t20@>i@;p@Bi%} zA2|cgz`tT3bc<0j;FVHsZCy@kZKU2&MZ~W$+=Q^BrI@}_ijSx&v`6U>^Ms8dEfoI| MP#U~(2L6 Date: Mon, 28 Jul 2025 09:32:35 +0200 Subject: [PATCH 145/366] docs: update changelog and header for version v1.5.6 --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d61d5..3403aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.5.6] - 2025-07-28 +### Added +- 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 + +### Changed +- 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 + +### Fixed +- Merge pull request #41 from janecker/memory_leak_fixes +- Fixes compiler warnings in nfc +- Memory leak fixes in api and nfc, location tag fix + + ## [1.5.5] - 2025-07-22 ### Added - Fixes some issues with the new location tags From 3286b6483638216298ad562911b0151d38121555 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 28 Jul 2025 09:51:46 +0200 Subject: [PATCH 146/366] refactor: clean up unused variables and improve .gitignore entries --- .gitignore | 39 ++++++++++++++++++++++++++++++++++++--- src/api.cpp | 2 -- src/website.cpp | 2 -- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index b18cbdd..b9774e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,41 @@ .pio -.vscode/.browse.c_cpp.db* +.vscode/ +.aider* +.DS_Store +._* +**/.DS_Store +**/.Spotlight-V100 +**/.Trashes +**/.fseventsd +.AppleDouble +**/.DS_Store +**/.Spotlight-V100 +**/.Trashes +**/.fseventsd +.AppleDouble +.aider.chat.history.md +.aider.input.history +.DS_Store +.gitignore +.aider.tags.cache.v3/cache.db +.aider.tags.cache.v3/cache.db-shm +.aider.tags.cache.v3/cache.db-wal .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch .vscode/extensions.json -.vscode/settings.json -data +.vscode/launch.json +include/README +lib/README +test/README +.aider* +data/* +!data/ +!data/.gitkeep +html/bambu_credentials.json +html/spoolman_url.json +_local/* +website/* +release.sh +.github/copilot-instructions.md +data \ No newline at end of file diff --git a/src/api.cpp b/src/api.cpp index cb42bdc..e19fb9a 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -599,8 +599,6 @@ bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, con octoUrl = octo_url; octoToken = octoTk; - doc.clear(); - return true; } diff --git a/src/website.cpp b/src/website.cpp index f87dba2..6723a0c 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -273,8 +273,6 @@ void setupWebserver(AsyncWebServer &server) { html.replace("{{autoSendToBambu}}", bambuCredentials.autosend_enable ? "checked" : ""); html.replace("{{autoSendTime}}", (bambuCredentials.autosend_time != 0) ? String(bambuCredentials.autosend_time) : String(BAMBU_DEFAULT_AUTOSEND_TIME)); - doc.clear(); - request->send(200, "text/html", html); }); From f022bee57878cc91f4cd8e2e61e622f3a84e04c3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 28 Jul 2025 09:51:55 +0200 Subject: [PATCH 147/366] docs: update platformio.ini for version v1.5.7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 611ed51..f1d49c8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.6" +version = "1.5.7" to_old_version = "1.5.0" ## From b0cd731c5a100f183278e5f85d5abea0fe82a8bc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 28 Jul 2025 09:51:55 +0200 Subject: [PATCH 148/366] docs: update changelog and header for version v1.5.7 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3403aed..59dcbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.5.7] - 2025-07-28 +### Changed +- update platformio.ini for version v1.5.7 +- clean up unused variables and improve .gitignore entries + + ## [1.5.6] - 2025-07-28 ### Added - Adds ENABLE_HEAP_DEBUGGING define as comment to the build flags From 722ef421cb5d1d52cf31788f52c5a3da1af14b57 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 2 Aug 2025 22:52:19 +0200 Subject: [PATCH 149/366] Reworks startup graphics and timings Reworks the graphics during the startup. Introduces a progress bar to visualize how much of the boot is completed. Also changes the the optics of the bambu, spoolman and wifi icons. They are now always displayed but they will be striked out if not working and they will start blinking. Also removes some unnessesary waits. --- src/api.cpp | 4 +-- src/bambu.cpp | 1 + src/config.cpp | 7 +----- src/config.h | 12 ++++++--- src/display.cpp | 65 +++++++++++++++++++++++++++++++++++++------------ src/display.h | 8 +++--- src/main.cpp | 6 +++++ src/nfc.cpp | 1 + src/scale.cpp | 2 +- src/website.cpp | 1 + src/wlan.cpp | 6 +---- 11 files changed, 75 insertions(+), 38 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index e19fb9a..4020d67 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -551,9 +551,6 @@ bool checkSpoolmanInstance(const String& url) { if (httpCode > 0) { if (httpCode == HTTP_CODE_OK) { - oledShowMessage("Spoolman available"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - String payload = http.getString(); JsonDocument doc; DeserializationError error = deserializeJson(doc, payload); @@ -617,6 +614,7 @@ String loadSpoolmanUrl() { } bool initSpoolman() { + oledShowProgressBar(3, 7, DISPLAY_BOOT_TEXT, "Spoolman init"); spoolmanUrl = loadSpoolmanUrl(); spoolmanUrl.trim(); if (spoolmanUrl == "") { diff --git a/src/bambu.cpp b/src/bambu.cpp index c738ec8..21fc6fa 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -627,6 +627,7 @@ bool setupMqtt() { if (bambuCredentials.ip != "" && bambuCredentials.accesscode != "" && bambuCredentials.serial != "") { + oledShowProgressBar(4, 7, DISPLAY_BOOT_TEXT, "Bambu init"); bambuDisabled = false; sslClient.setCACert(root_ca); sslClient.setInsecure(); diff --git a/src/config.cpp b/src/config.cpp index 644177e..359031a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -26,16 +26,11 @@ const uint8_t TTP223_PIN = 25; // ***** Display -// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) -// On an ESP32: 21(SDA), 22(SCL) -const int8_t OLED_RESET = -1; // Reset pin # (or -1 if sharing Arduino reset pin) -const uint8_t SCREEN_ADDRESS = 0x3C; ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 -const uint8_t SCREEN_WIDTH = 128; // OLED display width, in pixels -const uint8_t SCREEN_HEIGHT = 64; // OLED display height, in pixels const uint8_t OLED_TOP_START = 0; const uint8_t OLED_TOP_END = 16; const uint8_t OLED_DATA_START = 17; const uint8_t OLED_DATA_END = SCREEN_HEIGHT; + // ***** Display // ***** Webserver diff --git a/src/config.h b/src/config.h index ecccd51..88c57c0 100644 --- a/src/config.h +++ b/src/config.h @@ -25,6 +25,14 @@ #define BAMBU_USERNAME "bblp" +#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +#define SCREEN_ADDRESS 0x3CU // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 +#define SCREEN_WIDTH 128U +#define SCREEN_HEIGHT 64U +#define SCREEN_TOP_BAR_HEIGHT 16U +#define SCREEN_PROGRESS_BAR_HEIGHT 12U +#define DISPLAY_BOOT_TEXT "FilaMan" + extern const uint8_t PN532_IRQ; extern const uint8_t PN532_RESET; @@ -36,10 +44,6 @@ extern const uint16_t SCALE_LEVEL_WEIGHT; extern const uint8_t TTP223_PIN; -extern const int8_t OLED_RESET; -extern const uint8_t SCREEN_ADDRESS; -extern const uint8_t SCREEN_WIDTH; -extern const uint8_t SCREEN_HEIGHT; extern const uint8_t OLED_TOP_START; extern const uint8_t OLED_TOP_END; extern const uint8_t OLED_DATA_START; diff --git a/src/display.cpp b/src/display.cpp index dab0ccf..a15aa47 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -6,6 +6,7 @@ Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); bool wifiOn = false; +bool iconToggle = false; void setupDisplay() { if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { @@ -15,14 +16,6 @@ void setupDisplay() { display.setTextColor(WHITE); display.clearDisplay(); display.display(); - - // Show initial display buffer contents on the screen -- - // the library initializes this with an Adafruit splash screen. - display.setTextColor(WHITE); - display.display(); - oledShowTopRow(); - oledShowMessage("FilaMan v" + String(VERSION)); - vTaskDelay(2000 / portTICK_PERIOD_MS); } void oledclearline() { @@ -45,14 +38,14 @@ void oledcleardata() { //display.display(); } -int oled_center_h(String text) { +int oled_center_h(const String &text) { int16_t x1, y1; uint16_t w, h; display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h); return (SCREEN_WIDTH - w) / 2; } -int oled_center_v(String text) { +int oled_center_v(const String &text) { int16_t x1, y1; uint16_t w, h; display.getTextBounds(text, 0, OLED_DATA_START, &x1, &y1, &w, &h); @@ -60,7 +53,7 @@ int oled_center_v(String text) { return OLED_DATA_START + ((OLED_DATA_END - OLED_DATA_START - h) / 2); } -std::vector splitTextIntoLines(String text, uint8_t textSize) { +std::vector splitTextIntoLines(const String &text, uint8_t textSize) { std::vector lines; display.setTextSize(textSize); @@ -120,7 +113,7 @@ std::vector splitTextIntoLines(String text, uint8_t textSize) { return lines; } -void oledShowMultilineMessage(String message, uint8_t size) { +void oledShowMultilineMessage(const String &message, uint8_t size) { std::vector lines; int maxLines = 3; // Maximale Anzahl Zeilen für size 2 @@ -148,7 +141,7 @@ void oledShowMultilineMessage(String message, uint8_t size) { display.display(); } -void oledShowMessage(String message, uint8_t size) { +void oledShowMessage(const String &message, uint8_t size) { oledcleardata(); display.setTextSize(size); display.setTextWrap(false); @@ -171,22 +164,41 @@ void oledShowMessage(String message, uint8_t size) { void oledShowTopRow() { oledclearline(); + display.setTextSize(1); + display.setCursor(0, 4); + display.print("v"); + display.print(VERSION); + + iconToggle = !iconToggle; + if (bambu_connected == 1) { display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); } else { - display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE); + if(iconToggle){ + display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); + display.drawLine(50, 15, 66, 0, WHITE); + display.drawLine(51, 15, 67, 0, WHITE); + } } if (spoolmanApiState != API_INIT) { display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); } else { - display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE); + if(iconToggle){ + display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); + display.drawLine(80, 15, 96, 0, WHITE); + display.drawLine(81, 15, 97, 0, WHITE); + } } if (wifiOn == 1) { display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); } else { - display.drawBitmap(107, 0, wifi_off , 16, 16, WHITE); + if(iconToggle){ + display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); + display.drawLine(107, 15, 123, 0, WHITE); + display.drawLine(108, 15, 124, 0, WHITE); + } } display.display(); @@ -214,6 +226,27 @@ void oledShowIcon(const char* icon) { display.display(); } +void oledShowProgressBar(const uint8_t step, const uint8_t numSteps, const char* largeText, const char* statusMessage){ + assert(step <= numSteps); + + // clear data and bar area + display.fillRect(0, OLED_DATA_START, SCREEN_WIDTH, SCREEN_HEIGHT-16, BLACK); + + + display.setTextWrap(false); + display.setTextSize(2); + display.setCursor(0, OLED_DATA_START+4); + display.print(largeText); + display.setTextSize(1); + display.setCursor(0, OLED_DATA_END-SCREEN_PROGRESS_BAR_HEIGHT-10); + display.print(statusMessage); + + const int barLength = ((SCREEN_WIDTH-2)*step)/numSteps; + display.drawRoundRect(0, SCREEN_HEIGHT-SCREEN_PROGRESS_BAR_HEIGHT, SCREEN_WIDTH, 12, 6, WHITE); + display.fillRoundRect(1, SCREEN_HEIGHT-SCREEN_PROGRESS_BAR_HEIGHT+1, barLength, 10, 6, WHITE); + display.display(); +} + void oledShowWeight(uint16_t weight) { // Display Gewicht oledcleardata(); diff --git a/src/display.h b/src/display.h index 173c48e..c4cdb08 100644 --- a/src/display.h +++ b/src/display.h @@ -13,11 +13,13 @@ extern bool wifiOn; void setupDisplay(); void oledclearline(); void oledcleardata(); -int oled_center_h(String text); -int oled_center_v(String text); +int oled_center_h(const String &text); +int oled_center_v(const String &text); + +void oledShowProgressBar(const uint8_t step, const uint8_t numSteps, const char* largeText, const char* statusMessage); void oledShowWeight(uint16_t weight); -void oledShowMessage(String message, uint8_t size = 2); +void oledShowMessage(const String &message, uint8_t size = 2); void oledShowTopRow(); void oledShowIcon(const char* icon); diff --git a/src/main.cpp b/src/main.cpp index 96fa2f0..eb590f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,6 +118,12 @@ void loop() { checkWiFiConnection(); } + // Periodic display update + if (intervalElapsed(currentMillis, lastWifiCheckTime, 1000)) + { + oledShowTopRow(); + } + // Wenn Bambu auto set Spool aktiv if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0) { diff --git a/src/nfc.cpp b/src/nfc.cpp index e7aec4b..e223ef3 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -466,6 +466,7 @@ void scanRfidTask(void * parameter) { } void startNfc() { + oledShowProgressBar(5, 7, DISPLAY_BOOT_TEXT, "NFC init"); nfc.begin(); // Beginne Kommunikation mit RFID Leser delay(1000); unsigned long versiondata = nfc.getFirmwareVersion(); // Lese Versionsnummer der Firmware aus diff --git a/src/scale.cpp b/src/scale.cpp index 8172d9f..6856874 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -115,7 +115,7 @@ void start_scale(bool touchSensorConnected) { } } - oledShowMessage("Scale Tare Please remove all"); + oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Tare scale"); for (uint16_t i = 0; i < 2000; i++) { yield(); vTaskDelay(pdMS_TO_TICKS(1)); diff --git a/src/website.cpp b/src/website.cpp index 6723a0c..d5d5f7e 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -189,6 +189,7 @@ void sendAmsData(AsyncWebSocketClient *client) { } void setupWebserver(AsyncWebServer &server) { + oledShowProgressBar(2, 7, DISPLAY_BOOT_TEXT, "Webserver init"); // Deaktiviere alle Debug-Ausgaben Serial.setDebugOutput(false); diff --git a/src/wlan.cpp b/src/wlan.cpp index cbbba38..8756d7b 100644 --- a/src/wlan.cpp +++ b/src/wlan.cpp @@ -61,8 +61,7 @@ void initWiFi() { wm.setWiFiAutoReconnect(true); wm.setConnectTimeout(10); - oledShowTopRow(); - oledShowMessage("WiFi Setup"); + oledShowProgressBar(0, 7, DISPLAY_BOOT_TEXT, "WiFi Setup"); //bool res = wm.autoConnect("FilaMan"); // anonymous ap if(!wm.autoConnect("FilaMan")) { @@ -80,9 +79,6 @@ void initWiFi() { Serial.println(WiFi.localIP()); oledShowTopRow(); - display.display(); - - vTaskDelay(500 / portTICK_PERIOD_MS); // mDNS startMDNS(); From c450df59aaf1a5fb190887a894d1db90b7dedd48 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 2 Aug 2025 22:53:38 +0200 Subject: [PATCH 150/366] Replaces usage of String with const char* in heap debug function Replaces String with const char* in printHeapDebugData to reduce heap fragmentation. --- src/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.h b/src/debug.h index 8cc1efc..65f19e1 100644 --- a/src/debug.h +++ b/src/debug.h @@ -7,6 +7,6 @@ #define HEAP_DEBUG_MESSAGE(location) #endif -inline void printHeapDebugData(String location){ +inline void printHeapDebugData(const char *location){ Serial.println("Heap: " + String(ESP.getMinFreeHeap()/1024) + "\t" + String(ESP.getFreeHeap()/1024) + "\t" + String(ESP.getMaxAllocHeap()/1024) + "\t" + location); } \ No newline at end of file From 85a9bcf8bd698b504835bef89c2a1989c21afdd9 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 2 Aug 2025 23:05:56 +0200 Subject: [PATCH 151/366] Remove unused parameter of sendNfcData() Removes unused client parameter of the sendNfcData function. --- src/nfc.cpp | 8 ++++---- src/website.cpp | 6 +++--- src/website.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index e223ef3..48a162d 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -269,7 +269,7 @@ void writeJsonToTag(void *parameter) { //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert - sendNfcData(nullptr); + sendNfcData(); vTaskDelay(100 / portTICK_PERIOD_MS); oledShowMessage("Waiting for NFC-Tag"); @@ -311,7 +311,7 @@ void writeJsonToTag(void *parameter) { vTaskDelay(1000 / portTICK_PERIOD_MS); nfcReaderState = NFC_WRITE_SUCCESS; // aktualisieren der Website wenn sich der Status ändert - sendNfcData(nullptr); + sendNfcData(); pauseBambuMqttTask = false; if (updateSpoolTagId(uidString, payload)) { @@ -343,7 +343,7 @@ void writeJsonToTag(void *parameter) { } sendWriteResult(nullptr, success); - sendNfcData(nullptr); + sendNfcData(); vTaskResume(RfidReaderTask); pauseBambuMqttTask = false; @@ -459,7 +459,7 @@ void scanRfidTask(void * parameter) { } // aktualisieren der Website wenn sich der Status ändert - sendNfcData(nullptr); + sendNfcData(); } yield(); } diff --git a/src/website.cpp b/src/website.cpp index d5d5f7e..e2a9531 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -34,7 +34,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp Serial.println("Neuer Client verbunden!"); // Sende die AMS-Daten an den neuen Client if (!bambuDisabled) sendAmsData(client); - sendNfcData(client); + sendNfcData(); foundNfcTag(client, 0); sendWriteResult(client, 3); @@ -150,11 +150,11 @@ void sendWriteResult(AsyncWebSocketClient *client, uint8_t success) { void foundNfcTag(AsyncWebSocketClient *client, uint8_t success) { if (success == lastSuccess) return; ws.textAll("{\"type\":\"nfcTag\", \"payload\":{\"found\": " + String(success) + "}}"); - sendNfcData(nullptr); + sendNfcData(); lastSuccess = success; } -void sendNfcData(AsyncWebSocketClient *client) { +void sendNfcData() { if (lastnfcReaderState == nfcReaderState) return; // TBD: Why is there no status for reading the tag? switch(nfcReaderState){ diff --git a/src/website.h b/src/website.h index ad4a16e..b69f819 100644 --- a/src/website.h +++ b/src/website.h @@ -24,7 +24,7 @@ void setupWebserver(AsyncWebServer &server); // WebSocket-Funktionen void sendAmsData(AsyncWebSocketClient *client); -void sendNfcData(AsyncWebSocketClient *client); +void sendNfcData(); void foundNfcTag(AsyncWebSocketClient *client, uint8_t success); void sendWriteResult(AsyncWebSocketClient *client, uint8_t success); From 97a13687475ec5ce271b9739cdf1d453a3983b8b Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sun, 3 Aug 2025 16:51:09 +0200 Subject: [PATCH 152/366] Reworks graphics of tag reading and some api fixes Reworks the graphics of the NFC-Tag reading process of spool and location tags. Introduces progress bar for reading process. Also first re-work of the spoolman availability (not fixed completly yet). Also fixes an issue where the API request to spoolman and octoprint was sent in parallel. This now happens sequentially to reduce heap load. --- src/api.cpp | 69 +++++++++++++++++++++++++++++++++++------ src/api.h | 2 ++ src/display.cpp | 16 +++++----- src/main.cpp | 25 +++++++++------ src/nfc.cpp | 81 ++++++++++++++++++++++++++++++------------------- src/nfc.h | 1 + src/scale.cpp | 27 +++++++---------- src/website.cpp | 2 -- 8 files changed, 147 insertions(+), 76 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 4020d67..54c17bf 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -9,8 +9,11 @@ volatile spoolmanApiStateType spoolmanApiState = API_INIT; //bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; +bool sendOctoUpdate = false; String octoUrl = ""; String octoToken = ""; +uint16_t remainingWeight = 0; +bool spoolmanConnected = false; struct SendToApiParams { SpoolmanApiRequestType requestType; @@ -124,23 +127,58 @@ void sendToApi(void *parameter) { Serial.print("Fehler beim Parsen der JSON-Antwort: "); Serial.println(error.c_str()); } else { - if (requestType == API_REQUEST_SPOOL_WEIGHT_UPDATE) { - uint16_t remaining_weight = doc["remaining_weight"].as(); + switch(requestType){ + case API_REQUEST_SPOOL_WEIGHT_UPDATE: + remainingWeight = doc["remaining_weight"].as(); Serial.print("Aktuelles Gewicht: "); - Serial.println(remaining_weight); - oledShowMessage("Remaining: " + String(remaining_weight) + "g"); - } - else if ( requestType == API_REQUEST_SPOOL_LOCATION_UPDATE) { - oledShowMessage("Location updated!"); + Serial.println(remainingWeight); + //oledShowMessage("Remaining: " + String(remaining_weight) + "g"); + if(!octoEnabled){ + // TBD: Do not use Strings... + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + remainingWeight = 0; + }else{ + // ocoto is enabled, trigger octo update + sendOctoUpdate = true; + } + break; + case API_REQUEST_SPOOL_LOCATION_UPDATE: + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Loc. Tag", "Done!"); + break; + case API_REQUEST_OCTO_SPOOL_UPDATE: + // TBD: Do not use Strings... + oledShowProgressBar(5, 5, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + remainingWeight = 0; + break; } + // TBD: really required? vTaskDelay(3000 / portTICK_PERIOD_MS); } doc.clear(); - } else { + switch(requestType){ + case API_REQUEST_SPOOL_WEIGHT_UPDATE: + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman update"); + break; + case API_REQUEST_SPOOL_LOCATION_UPDATE: + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman update"); + break; + case API_REQUEST_OCTO_SPOOL_UPDATE: + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Octoprint update"); + break; + case API_REQUEST_BAMBU_UPDATE: + // TBD: rework error + oledShowMessage("Spoolman update failed"); + break; + case API_REQUEST_SPOOL_TAG_ID_UPDATE: + // TBD: rework error + oledShowMessage("Spoolman update failed"); + break; + } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); - oledShowMessage("Spoolman update failed"); + + // TBD: really required? vTaskDelay(2000 / portTICK_PERIOD_MS); } @@ -215,6 +253,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { HEAP_DEBUG_MESSAGE("updateSpoolWeight begin"); + oledShowProgressBar(3, octoEnabled?5:4, "Spool Tag", "Spoolman update"); String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId + "/measure"; Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); @@ -230,6 +269,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { SendToApiParams* params = new SendToApiParams(); if (params == nullptr) { + // TBD: reset ESP instead of showing a message Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return 0; } @@ -257,6 +297,8 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { uint8_t updateSpoolLocation(String spoolId, String location){ HEAP_DEBUG_MESSAGE("updateSpoolLocation begin"); + oledShowProgressBar(3, octoEnabled?5:4, "Loc. Tag", "Spoolman update"); + String spoolsUrl = spoolmanUrl + apiUrl + "/spool/" + spoolId; Serial.print("Update Spule mit URL: "); Serial.println(spoolsUrl); @@ -280,6 +322,7 @@ uint8_t updateSpoolLocation(String spoolId, String location){ params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; + if(spoolmanApiState == API_IDLE){ // Erstelle die Task BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion @@ -290,6 +333,10 @@ uint8_t updateSpoolLocation(String spoolId, String location){ NULL // Task-Handle (nicht benötigt) ); + }else{ + Serial.println("Not spawning new task, API still active!"); + } + updateDoc.clear(); HEAP_DEBUG_MESSAGE("updateSpoolLocation end"); @@ -297,6 +344,8 @@ uint8_t updateSpoolLocation(String spoolId, String location){ } bool updateSpoolOcto(int spoolId) { + oledShowProgressBar(4, octoEnabled?5:4, "Spool Tag", "Octoprint update"); + String spoolsUrl = octoUrl + "/plugin/Spoolman/selectSpool"; Serial.print("Update Spule in Octoprint mit URL: "); Serial.println(spoolsUrl); @@ -561,6 +610,7 @@ bool checkSpoolmanInstance(const String& url) { if (!checkSpoolmanExtraFields()) { Serial.println("Fehler beim Überprüfen der Extrafelder."); + // TBD oledShowMessage("Spoolman Error creating Extrafields"); vTaskDelay(2000 / portTICK_PERIOD_MS); @@ -569,6 +619,7 @@ bool checkSpoolmanInstance(const String& url) { spoolmanApiState = API_IDLE; oledShowTopRow(); + spoolmanConnected = true; return strcmp(status, "healthy") == 0; } diff --git a/src/api.h b/src/api.h index 5311dfc..23fb6d8 100644 --- a/src/api.h +++ b/src/api.h @@ -24,8 +24,10 @@ extern volatile spoolmanApiStateType spoolmanApiState; extern bool spoolman_connected; extern String spoolmanUrl; extern bool octoEnabled; +extern bool sendOctoUpdate; extern String octoUrl; extern String octoToken; +extern bool spoolmanConnected; bool checkSpoolmanInstance(const String& url); bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk); diff --git a/src/display.cpp b/src/display.cpp index a15aa47..2fd91ef 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -171,17 +171,19 @@ void oledShowTopRow() { iconToggle = !iconToggle; - if (bambu_connected == 1) { - display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); - } else { - if(iconToggle){ + if(bambuDisabled == false) { + if (bambu_connected == 1) { display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); - display.drawLine(50, 15, 66, 0, WHITE); - display.drawLine(51, 15, 67, 0, WHITE); + } else { + if(iconToggle){ + display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); + display.drawLine(50, 15, 66, 0, WHITE); + display.drawLine(51, 15, 67, 0, WHITE); + } } } - if (spoolmanApiState != API_INIT) { + if (spoolmanConnected) { display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); } else { if(iconToggle){ diff --git a/src/main.cpp b/src/main.cpp index eb590f2..422551a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -218,19 +218,14 @@ 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) { - oledShowIcon("loading"); + 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; + if (updateSpoolWeight(activeSpoolId, weight)) { - oledShowIcon("success"); - vTaskDelay(2000 / portTICK_PERIOD_MS); weightSend = 1; - autoSetToBambuSpoolId = activeSpoolId.toInt(); - - if (octoEnabled) - { - updateSpoolOcto(autoSetToBambuSpoolId); - } + } else { @@ -238,6 +233,16 @@ void loop() { vTaskDelay(2000 / portTICK_PERIOD_MS); } } + + if(sendOctoUpdate && spoolmanApiState == API_IDLE){ + autoSetToBambuSpoolId = activeSpoolId.toInt(); + + if(octoEnabled) + { + updateSpoolOcto(autoSetToBambuSpoolId); + } + sendOctoUpdate = false; + } esp_task_wdt_reset(); } diff --git a/src/nfc.cpp b/src/nfc.cpp index 48a162d..35a56a1 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -18,6 +18,7 @@ JsonDocument rfidData; String activeSpoolId = ""; String lastSpoolId = ""; String nfcJsonData = ""; +bool tagProcessed = false; volatile bool pauseBambuMqttTask = false; volatile nfcReaderStateType nfcReaderState = NFC_IDLE; @@ -196,6 +197,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { } bool decodeNdefAndReturnJson(const byte* encodedMessage) { + oledShowProgressBar(1, octoEnabled?5:4, "Reading", "Decoding data"); + byte typeLength = encodedMessage[3]; byte payloadLength = encodedMessage[4]; @@ -219,35 +222,43 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { } else { - // 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"] != "") - { - Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); - activeSpoolId = doc["sm_id"].as(); - lastSpoolId = activeSpoolId; - } - else if(doc["location"].is() && doc["location"] != "") - { - Serial.println("Location Tag found!"); - String location = doc["location"].as(); - if(lastSpoolId != ""){ - updateSpoolLocation(lastSpoolId, location); - } - else + // If spoolman is unavailable, there is no point in continuing + if(spoolmanConnected){ + // 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"] != "") { - Serial.println("Location update tag scanned without scanning spool before!"); - oledShowMessage("No spool scanned before!"); - } + oledShowProgressBar(2, octoEnabled?5:4, "Spool Tag", "Weighing"); + Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); + activeSpoolId = doc["sm_id"].as(); + lastSpoolId = activeSpoolId; - } - else - { - Serial.println("Keine SPOOL-ID gefunden."); - activeSpoolId = ""; - oledShowMessage("Unknown Spool"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + Serial.println("Api state: " + String(spoolmanApiState)); + } + else if(doc["location"].is() && doc["location"] != "") + { + Serial.println("Location Tag found!"); + String location = doc["location"].as(); + if(lastSpoolId != ""){ + updateSpoolLocation(lastSpoolId, location); + } + else + { + Serial.println("Location update tag scanned without scanning spool before!"); + oledShowProgressBar(1, 1, "Failure", "Scan spool first"); + } + } + else + { + Serial.println("Keine SPOOL-ID gefunden."); + activeSpoolId = ""; + // TBD: this path has not been tested! + oledShowMessage("Unknown Spool"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } + }else{ + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman unavailable"); } } @@ -384,14 +395,19 @@ void scanRfidTask(void * parameter) { foundNfcTag(nullptr, success); - if (success && nfcReaderState != NFC_READ_SUCCESS) + // As long as there is still a tag on the reader, do not try to read it again + if (success && nfcReaderState != NFC_READ_SUCCESS && nfcReaderState != NFC_READ_ERROR) { + // Set the current tag as not processed + tagProcessed = false; + // Display some basic information about the card Serial.println("Found an ISO14443A card"); nfcReaderState = NFC_READING; - oledShowIcon("transfer"); + oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); + vTaskDelay(500 / portTICK_PERIOD_MS); if (uidLength == 7) @@ -425,8 +441,7 @@ void scanRfidTask(void * parameter) { if (!decodeNdefAndReturnJson(data)) { - oledShowMessage("NFC-Tag unknown"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + oledShowProgressBar(1, 1, "Failure", "Unkown Tag"); nfcReaderState = NFC_READ_ERROR; } else @@ -438,12 +453,13 @@ void scanRfidTask(void * parameter) { } else { - oledShowMessage("NFC-Tag read error"); + oledShowProgressBar(1, 1, "Failure", "Tag Read Error"); nfcReaderState = NFC_READ_ERROR; } } else { + //TBD: Show error here?! Serial.println("This doesn't seem to be an NTAG2xx tag (UUID length != 7 bytes)!"); } } @@ -474,6 +490,7 @@ void startNfc() { Serial.println("Kann kein RFID Board finden !"); // Sende Text "Kann kein..." an seriellen Monitor //delay(5000); //ESP.restart(); + //TBD: rework this oledShowMessage("No RFID Board found"); delay(2000); } diff --git a/src/nfc.h b/src/nfc.h index 8f8cf5a..cd36d83 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -23,6 +23,7 @@ extern String activeSpoolId; extern String lastSpoolId; extern volatile nfcReaderStateType nfcReaderState; extern volatile bool pauseBambuMqttTask; +extern bool tagProcessed; diff --git a/src/scale.cpp b/src/scale.cpp index 6856874..994601f 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -162,7 +162,7 @@ uint8_t calibrate_scale() { { scale.set_scale(); - oledShowMessage("Step 1 empty Scale"); + oledShowProgressBar(0, 3, "Scale Cal.", "Empty Scale"); for (uint16_t i = 0; i < 5000; i++) { yield(); @@ -174,7 +174,7 @@ uint8_t calibrate_scale() { Serial.println("Tare done..."); Serial.print("Place a known weight on the scale..."); - oledShowMessage("Step 2 Place the weight"); + oledShowProgressBar(1, 3, "Scale Cal.", "Place the weight"); for (uint16_t i = 0; i < 5000; i++) { yield(); @@ -207,9 +207,7 @@ uint8_t calibrate_scale() { Serial.print("Verified stored value: "); Serial.println(verifyValue); - Serial.println("End calibration, remove weight"); - - oledShowMessage("Remove weight"); + oledShowProgressBar(2, 3, "Scale Cal.", "Remove weight"); scale.set_scale(newCalibrationValue); for (uint16_t i = 0; i < 2000; i++) { @@ -218,7 +216,7 @@ uint8_t calibrate_scale() { esp_task_wdt_reset(); } - oledShowMessage("Scale calibrated"); + oledShowProgressBar(3, 3, "Scale Cal.", "Completed"); // For some reason it is not possible to re-tare the scale here, it will result in a wdt timeout. Instead let the scale loop do the taring //scale.tare(); @@ -232,21 +230,18 @@ uint8_t calibrate_scale() { returnState = 1; } - else { - { - Serial.println("Calibration value is invalid. Please recalibrate."); + Serial.println("Calibration value is invalid. Please recalibrate."); - oledShowMessage("Calibration ERROR Try again"); + oledShowMessage("Calibration ERROR Try again"); - for (uint16_t i = 0; i < 50000; i++) { - yield(); - vTaskDelay(pdMS_TO_TICKS(1)); - esp_task_wdt_reset(); - } - returnState = 0; + for (uint16_t i = 0; i < 50000; i++) { + yield(); + vTaskDelay(pdMS_TO_TICKS(1)); + esp_task_wdt_reset(); } + returnState = 0; } } else diff --git a/src/website.cpp b/src/website.cpp index e2a9531..4ae0966 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -52,8 +52,6 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp JsonDocument doc; deserializeJson(doc, message); - bool spoolmanConnected = (spoolmanApiState != API_INIT); - if (doc["type"] == "heartbeat") { // Sende Heartbeat-Antwort ws.text(client->id(), "{" From b6d82c8afe4a3a5cd02e3315b4b02b2647428ca8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Tue, 5 Aug 2025 17:44:59 +0200 Subject: [PATCH 153/366] Graphic rework of the NFC writing process Introduces the new graphics for the NFC writing process. Also fixes some minor display bugs. Hides the service status icons during boot time. Fixes bugs in NFC write process where mutliple parallel API calls a created. Fixes a bug where spoolman is updated if a location tag is written (which is not required or correct). --- html/rfid.js | 2 ++ src/api.cpp | 25 +++++++++-------- src/display.cpp | 51 +++++++++++++++++++--------------- src/main.cpp | 2 ++ src/main.h | 9 ++++++ src/nfc.cpp | 73 +++++++++++++++++++++++++++++++++---------------- src/nfc.h | 2 +- src/website.cpp | 3 +- src/wlan.cpp | 2 +- 9 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 src/main.h diff --git a/html/rfid.js b/html/rfid.js index d3a54a5..52866ea 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -660,6 +660,7 @@ function writeNfcTag() { writeButton.textContent = "Writing"; socket.send(JSON.stringify({ type: 'writeNfcTag', + tagType: 'spool', payload: nfcData })); } else { @@ -684,6 +685,7 @@ function writeLocationNfcTag() { writeButton.textContent = "Writing"; socket.send(JSON.stringify({ type: 'writeNfcTag', + tagType: 'location', payload: nfcData })); } else { diff --git a/src/api.cpp b/src/api.cpp index 54c17bf..9bba672 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -135,7 +135,7 @@ void sendToApi(void *parameter) { //oledShowMessage("Remaining: " + String(remaining_weight) + "g"); if(!octoEnabled){ // TBD: Do not use Strings... - oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + oledShowProgressBar(1, 1, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); remainingWeight = 0; }else{ // ocoto is enabled, trigger octo update @@ -143,7 +143,10 @@ void sendToApi(void *parameter) { } break; case API_REQUEST_SPOOL_LOCATION_UPDATE: - oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Loc. Tag", "Done!"); + oledShowProgressBar(1, 1, "Loc. Tag", "Done!"); + break; + case API_REQUEST_SPOOL_TAG_ID_UPDATE: + oledShowProgressBar(1, 1, "Write Tag", "Done!"); break; case API_REQUEST_OCTO_SPOOL_UPDATE: // TBD: Do not use Strings... @@ -159,22 +162,17 @@ void sendToApi(void *parameter) { } else { switch(requestType){ case API_REQUEST_SPOOL_WEIGHT_UPDATE: - oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman update"); - break; case API_REQUEST_SPOOL_LOCATION_UPDATE: - oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman update"); + case API_REQUEST_SPOOL_TAG_ID_UPDATE: + oledShowProgressBar(1, 1, "Failure!", "Spoolman update"); break; case API_REQUEST_OCTO_SPOOL_UPDATE: - oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Octoprint update"); + oledShowProgressBar(1, 1, "Failure!", "Octoprint update"); break; case API_REQUEST_BAMBU_UPDATE: // TBD: rework error oledShowMessage("Spoolman update failed"); break; - case API_REQUEST_SPOOL_TAG_ID_UPDATE: - // TBD: rework error - oledShowMessage("Spoolman update failed"); - break; } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); @@ -193,6 +191,8 @@ void sendToApi(void *parameter) { } bool updateSpoolTagId(String uidString, const char* payload) { + oledShowProgressBar(2, 3, "Write Tag", "Update Spoolman"); + JsonDocument doc; DeserializationError error = deserializeJson(doc, payload); @@ -223,7 +223,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { Serial.print("Update Payload: "); Serial.println(updatePayload); - SendToApiParams* params = new SendToApiParams(); + SendToApiParams* params = new SendToApiParams(); if (params == nullptr) { Serial.println("Fehler: Kann Speicher für Task-Parameter nicht allokieren."); return false; @@ -246,7 +246,8 @@ bool updateSpoolTagId(String uidString, const char* payload) { updateDoc.clear(); // Update Spool weight - if (weight > 10) updateSpoolWeight(doc["sm_id"].as(), 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); return true; } diff --git a/src/display.cpp b/src/display.cpp index 2fd91ef..0ccaa5f 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2,6 +2,7 @@ #include "api.h" #include #include "icons.h" +#include "main.h" Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); @@ -15,7 +16,10 @@ void setupDisplay() { } display.setTextColor(WHITE); display.clearDisplay(); - display.display(); + + + oledShowTopRow(); + oledShowProgressBar(0, 7, DISPLAY_BOOT_TEXT, "Display init"); } void oledclearline() { @@ -171,35 +175,38 @@ void oledShowTopRow() { iconToggle = !iconToggle; - if(bambuDisabled == false) { - if (bambu_connected == 1) { - display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); - } else { - if(iconToggle){ + // Do not show status indicators during boot + if(!booting){ + if(bambuDisabled == false) { + if (bambu_connected == 1) { display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); - display.drawLine(50, 15, 66, 0, WHITE); - display.drawLine(51, 15, 67, 0, WHITE); + } else { + if(iconToggle){ + display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); + display.drawLine(50, 15, 66, 0, WHITE); + display.drawLine(51, 15, 67, 0, WHITE); + } } } - } - if (spoolmanConnected) { - display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); - } else { - if(iconToggle){ + if (spoolmanConnected) { display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); - display.drawLine(80, 15, 96, 0, WHITE); - display.drawLine(81, 15, 97, 0, WHITE); + } else { + if(iconToggle){ + display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); + display.drawLine(80, 15, 96, 0, WHITE); + display.drawLine(81, 15, 97, 0, WHITE); + } } - } - if (wifiOn == 1) { - display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); - } else { - if(iconToggle){ + if (wifiOn == 1) { display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); - display.drawLine(107, 15, 123, 0, WHITE); - display.drawLine(108, 15, 124, 0, WHITE); + } else { + if(iconToggle){ + display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); + display.drawLine(107, 15, 123, 0, WHITE); + display.drawLine(108, 15, 124, 0, WHITE); + } } } diff --git a/src/main.cpp b/src/main.cpp index 422551a..f160e95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ bool mainTaskWasPaused = 0; uint8_t scaleTareCounter = 0; bool touchSensorConnected = false; +bool booting = true; // ##### SETUP ##### void setup() { @@ -63,6 +64,7 @@ void setup() { bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus esp_task_wdt_init(10, panic); + booting = false; // Aktuellen Task (loopTask) zum Watchdog hinzufügen esp_task_wdt_add(NULL); } diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..27c479b --- /dev/null +++ b/src/main.h @@ -0,0 +1,9 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + + +extern bool booting; + +#endif \ No newline at end of file diff --git a/src/nfc.cpp b/src/nfc.cpp index 35a56a1..1638328 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -21,6 +21,11 @@ String nfcJsonData = ""; bool tagProcessed = false; volatile bool pauseBambuMqttTask = false; +struct NfcWriteParameterType { + bool tagType; + char* payload; +}; + volatile nfcReaderStateType nfcReaderState = NFC_IDLE; // 0 = nicht gelesen // 1 = erfolgreich gelesen @@ -268,11 +273,11 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { } void writeJsonToTag(void *parameter) { - const char* payload = (const char*)parameter; + NfcWriteParameterType* params = (NfcWriteParameterType*)parameter; // Gib die erstellte NDEF-Message aus Serial.println("Erstelle NDEF-Message..."); - Serial.println(payload); + Serial.println(params->payload); nfcReaderState = NFC_WRITING; vTaskSuspend(RfidReaderTask); @@ -282,17 +287,22 @@ void writeJsonToTag(void *parameter) { // aktualisieren der Website wenn sich der Status ändert sendNfcData(); vTaskDelay(100 / portTICK_PERIOD_MS); - oledShowMessage("Waiting for NFC-Tag"); - + Serial.println("CP 1"); // Wait 10sec for tag uint8_t success = 0; String uidString = ""; for (uint16_t i = 0; i < 20; i++) { + Serial.println("CP 2"); 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); + // yield before potentially waiting for 400ms + yield(); + esp_task_wdt_reset(); + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400); if (success) { + Serial.println("CP 3.1"); 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 @@ -300,9 +310,12 @@ void writeJsonToTag(void *parameter) { } foundNfcTag(nullptr, success); break; + }else{ + Serial.println("CP 3.2"); } - if (i == 0) oledShowMessage("Waiting for NFC-Tag"); + //TBD: Is this required? + //if (i == 0) oledShowMessage("Waiting for NFC-Tag"); yield(); esp_task_wdt_reset(); @@ -311,29 +324,37 @@ void writeJsonToTag(void *parameter) { if (success) { - oledShowIcon("transfer"); + oledShowProgressBar(1, 3, "Write Tag", "Writing"); + // Schreibe die NDEF-Message auf den Tag - success = ntag2xx_WriteNDEF(payload); + success = ntag2xx_WriteNDEF(params->payload); if (success) { Serial.println("NDEF-Message erfolgreich auf den Tag geschrieben"); //oledShowMessage("NFC-Tag written"); - oledShowIcon("success"); - vTaskDelay(1000 / portTICK_PERIOD_MS); + //vTaskDelay(1000 / portTICK_PERIOD_MS); nfcReaderState = NFC_WRITE_SUCCESS; // aktualisieren der Website wenn sich der Status ändert sendNfcData(); pauseBambuMqttTask = false; - if (updateSpoolTagId(uidString, payload)) { - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID - uint8_t uidLength; - oledShowIcon("success"); - while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) { - yield(); + if(params->tagType){ + // TBD: should this be simplified? + if (updateSpoolTagId(uidString, params->payload) && params->tagType) { + + }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 + uint8_t uidLength; + yield(); + esp_task_wdt_reset(); + while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400)) { + yield(); + } vTaskResume(RfidReaderTask); vTaskDelay(500 / portTICK_PERIOD_MS); } @@ -348,7 +369,7 @@ void writeJsonToTag(void *parameter) { else { Serial.println("Fehler: Kein Tag zu schreiben gefunden."); - oledShowMessage("No NFC-Tag found"); + oledShowProgressBar(1, 1, "Failure!", "No tag found"); vTaskDelay(2000 / portTICK_PERIOD_MS); nfcReaderState = NFC_IDLE; } @@ -362,20 +383,26 @@ void writeJsonToTag(void *parameter) { vTaskDelete(NULL); } -void startWriteJsonToTag(const char* payload) { - char* payloadCopy = strdup(payload); +void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { + NfcWriteParameterType* parameters = new NfcWriteParameterType(); + parameters->tagType = isSpoolTag; + parameters->payload = strdup(payload); // Task nicht mehrfach starten - if (nfcReaderState != NFC_WRITING) { + if (nfcReaderState == NFC_IDLE) { + oledShowProgressBar(0, 1, "Write Tag", "Place tag now"); // Erstelle die Task xTaskCreate( writeJsonToTag, // Task-Funktion "WriteJsonToTagTask", // Task-Name 5115, // Stackgröße in Bytes - (void*)payloadCopy, // Parameter + (void*)parameters, // Parameter rfidWriteTaskPrio, // Priorität NULL // Task-Handle (nicht benötigt) ); + }else{ + oledShowProgressBar(0, 1, "FAILURE", "NFC busy!"); + // TBD: Add proper error handling (website) } } @@ -396,7 +423,7 @@ void scanRfidTask(void * parameter) { foundNfcTag(nullptr, success); // As long as there is still a tag on the reader, do not try to read it again - if (success && nfcReaderState != NFC_READ_SUCCESS && nfcReaderState != NFC_READ_ERROR) + if (success && nfcReaderState == NFC_IDLE) { // Set the current tag as not processed tagProcessed = false; diff --git a/src/nfc.h b/src/nfc.h index cd36d83..2c3d5f3 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -15,7 +15,7 @@ typedef enum{ void startNfc(); void scanRfidTask(void * parameter); -void startWriteJsonToTag(const char* payload); +void startWriteJsonToTag(const bool isSpoolTag, const char* payload); extern TaskHandle_t RfidReaderTask; extern String nfcJsonData; diff --git a/src/website.cpp b/src/website.cpp index 4ae0966..7c40fc7 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -67,7 +67,8 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp // Versuche NFC-Daten zu schreiben String payloadString; serializeJson(doc["payload"], payloadString); - startWriteJsonToTag(payloadString.c_str()); + + startWriteJsonToTag((doc["tagType"] == "spool") ? true : false, payloadString.c_str()); } } diff --git a/src/wlan.cpp b/src/wlan.cpp index 8756d7b..92081bc 100644 --- a/src/wlan.cpp +++ b/src/wlan.cpp @@ -61,7 +61,7 @@ void initWiFi() { wm.setWiFiAutoReconnect(true); wm.setConnectTimeout(10); - oledShowProgressBar(0, 7, DISPLAY_BOOT_TEXT, "WiFi Setup"); + oledShowProgressBar(1, 7, DISPLAY_BOOT_TEXT, "WiFi init"); //bool res = wm.autoConnect("FilaMan"); // anonymous ap if(!wm.autoConnect("FilaMan")) { From ec0e544f30fdcdf3c5159819e01ccba694b13fd2 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Tue, 5 Aug 2025 19:41:06 +0200 Subject: [PATCH 154/366] Fixes typos in upgrade page Fixes names of binary files on the upgrade page. --- html/upgrade.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html/upgrade.html b/html/upgrade.html index 48c2b33..70d82ee 100644 --- a/html/upgrade.html +++ b/html/upgrade.html @@ -57,7 +57,7 @@

Firmware Update

-

Upload a new firmware file (filaman_*.bin)

+

Upload a new firmware file (upgrade_filaman_firmware_*.bin)

@@ -68,7 +68,7 @@

Webpage Update

-

Upload a new webpage file (webpage_*.bin)

+

Upload a new webpage file (upgrade_filaman_website_*.bin)

From 09f4c43f8941421344a7821295087696304fbf83 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Tue, 5 Aug 2025 19:43:05 +0200 Subject: [PATCH 155/366] Fixes types and some issues in the new graphics Fixes further issues with the new graphics. Fixes some typos. Adds progress bar for upgrade process. --- src/api.cpp | 6 +----- src/nfc.cpp | 17 +++++------------ src/ota.cpp | 2 +- src/scale.cpp | 2 +- 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 9bba672..4b65f4b 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -154,9 +154,6 @@ void sendToApi(void *parameter) { remainingWeight = 0; break; } - - // TBD: really required? - vTaskDelay(3000 / portTICK_PERIOD_MS); } doc.clear(); } else { @@ -170,8 +167,7 @@ void sendToApi(void *parameter) { oledShowProgressBar(1, 1, "Failure!", "Octoprint update"); break; case API_REQUEST_BAMBU_UPDATE: - // TBD: rework error - oledShowMessage("Spoolman update failed"); + oledShowProgressBar(1, 1, "Failure!", "Bambu update"); break; } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); diff --git a/src/nfc.cpp b/src/nfc.cpp index 1638328..fe1a486 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -258,9 +258,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { { Serial.println("Keine SPOOL-ID gefunden."); activeSpoolId = ""; - // TBD: this path has not been tested! - oledShowMessage("Unknown Spool"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + oledShowProgressBar(1, 1, "Failure", "Unkown tag"); } }else{ oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman unavailable"); @@ -314,9 +312,6 @@ void writeJsonToTag(void *parameter) { Serial.println("CP 3.2"); } - //TBD: Is this required? - //if (i == 0) oledShowMessage("Waiting for NFC-Tag"); - yield(); esp_task_wdt_reset(); vTaskDelay(pdMS_TO_TICKS(1)); @@ -468,7 +463,7 @@ void scanRfidTask(void * parameter) { if (!decodeNdefAndReturnJson(data)) { - oledShowProgressBar(1, 1, "Failure", "Unkown Tag"); + oledShowProgressBar(1, 1, "Failure", "Unknown tag"); nfcReaderState = NFC_READ_ERROR; } else @@ -480,13 +475,14 @@ void scanRfidTask(void * parameter) { } else { - oledShowProgressBar(1, 1, "Failure", "Tag Read Error"); + oledShowProgressBar(1, 1, "Failure", "Tag read error"); nfcReaderState = NFC_READ_ERROR; } } else { //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)!"); } } @@ -515,11 +511,8 @@ void startNfc() { unsigned long versiondata = nfc.getFirmwareVersion(); // Lese Versionsnummer der Firmware aus if (! versiondata) { // Wenn keine Antwort kommt Serial.println("Kann kein RFID Board finden !"); // Sende Text "Kann kein..." an seriellen Monitor - //delay(5000); - //ESP.restart(); - //TBD: rework this oledShowMessage("No RFID Board found"); - delay(2000); + vTaskDelay(2000 / portTICK_PERIOD_MS); } else { Serial.print("Chip PN5 gefunden"); Serial.println((versiondata >> 24) & 0xFF, HEX); // Sende Text und Versionsinfos an seriellen diff --git a/src/ota.cpp b/src/ota.cpp index d22bc6a..a98b949 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -224,7 +224,7 @@ void handleUpdate(AsyncWebServer &server) { static int lastProgress = -1; if (currentProgress != lastProgress && (currentProgress % 10 == 0 || final)) { sendUpdateProgress(currentProgress, "uploading"); - oledShowMessage("Update: " + String(currentProgress) + "%"); + oledShowProgressBar(currentProgress, 100, "Update", "Download"); vTaskDelay(50 / portTICK_PERIOD_MS); lastProgress = currentProgress; } diff --git a/src/scale.cpp b/src/scale.cpp index 994601f..4be30c7 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -234,7 +234,7 @@ uint8_t calibrate_scale() { { Serial.println("Calibration value is invalid. Please recalibrate."); - oledShowMessage("Calibration ERROR Try again"); + oledShowProgressBar(3, 3, "Failure", "Calibration error"); for (uint16_t i = 0; i < 50000; i++) { yield(); From 765cb5319d06f620baa034e2bfb867e0c8ea5262 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 6 Aug 2025 17:27:11 +0200 Subject: [PATCH 156/366] Add vendor and filament management to API; implement recycling factory handling in NFC --- src/api.cpp | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/api.h | 15 +++- src/nfc.cpp | 24 ++++- 3 files changed, 288 insertions(+), 4 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 4b65f4b..5a052e7 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -13,6 +13,9 @@ 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 bool spoolmanConnected = false; struct SendToApiParams { @@ -114,6 +117,7 @@ void sendToApi(void *parameter) { int httpCode; 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); if (httpCode == HTTP_CODE_OK) { @@ -153,6 +157,58 @@ void sendToApi(void *parameter) { oledShowProgressBar(5, 5, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); 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; + } + } + doc.clear(); + } else if (httpCode == HTTP_CODE_CREATED) { + Serial.println("Spoolman erfolgreich erstellt"); + + // Parse response for created resources + String payload = http.getString(); + JsonDocument doc; + DeserializationError error = deserializeJson(doc, payload); + 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; + default: + // Handle other create operations if needed + break; } } doc.clear(); @@ -169,6 +225,9 @@ void sendToApi(void *parameter) { case API_REQUEST_BAMBU_UPDATE: oledShowProgressBar(1, 1, "Failure!", "Bambu update"); break; + case API_REQUEST_VENDOR_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Vendor create"); + break; } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); @@ -433,6 +492,200 @@ bool updateSpoolBambuData(String payload) { return true; } +// #### Filament Fabrik +uint16_t checkVendor(String vendor) { + // Check if vendor exists using task system + foundVendorId = 0; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendor; + 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 + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + delete params; + return 0; + } + + // Wait for task completion + while(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // Check if vendor was found + if (foundVendorId == 0) { + Serial.println("Vendor not found, creating new vendor..."); + uint16_t vendorId = createVendor(vendor); + 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)); + checkFilament(vendorId); + return vendorId; + } + } else { + Serial.println("Vendor found: " + vendor); + Serial.print("Vendor ID: "); + Serial.println(foundVendorId); + return foundVendorId; + } +} + +uint16_t createVendor(String vendor) { + // Create new vendor in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdVendorId global variable + createdVendorId = 0; // 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"] = vendor; + vendorDoc["comment"] = "automatically generated"; + vendorDoc["empty_spool_weight"] = 180; + vendorDoc["external_id"] = vendor; + + 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; + + // Check if API is idle before creating task + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + delete params; + vendorDoc.clear(); + return 0; + } + + vendorDoc.clear(); + + // Wait for task completion and return the created vendor ID + // Note: createdVendorId will be set by sendToApi when response is received + while(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + return createdVendorId; +} + +uint16_t checkFilament(uint16_t vendorId) { + // Check if filament exists using task system + foundFilamentId = 0; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/filament?vendor.id=" + String(vendorId); + 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 + + // Check if API is idle before creating task + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + delete params; + return 0; + } + + // Wait for task completion + while(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // Check if filament was found + if (foundFilamentId == 0) { + Serial.println("Filament not found, creating new filament..."); + uint16_t filamentId = createFilament(); + 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)); + checkSpool(); + return filamentId; + } + } else { + Serial.println("Filament found for vendor ID: " + String(vendorId)); + Serial.print("Filament ID: "); + Serial.println(foundFilamentId); + return foundFilamentId; + } +} + +bool createFilament() { + +} + +uint16_t checkSpool() { + +} + +bool createSpool() { + // Implement specific handling for Spool creation +} + // #### Spoolman init bool checkSpoolmanExtraFields() { HTTPClient http; diff --git a/src/api.h b/src/api.h index 23fb6d8..da92f97 100644 --- a/src/api.h +++ b/src/api.h @@ -17,7 +17,10 @@ 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 } SpoolmanApiRequestType; extern volatile spoolmanApiStateType spoolmanApiState; @@ -27,6 +30,9 @@ extern bool octoEnabled; extern bool sendOctoUpdate; extern String octoUrl; extern String octoToken; +extern uint16_t createdVendorId; // ID of newly created vendor +extern uint16_t foundVendorId; // ID of found vendor +extern uint16_t foundFilamentId; // ID of found filament extern bool spoolmanConnected; bool checkSpoolmanInstance(const String& url); @@ -40,5 +46,12 @@ 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 +uint16_t checkVendor(String vendor); // Check if vendor exists, return ID +uint16_t createVendor(String vendor); // Create vendor, return ID +uint16_t checkFilament(); // Check if filament exists, return ID +bool createFilament(); // Create filament +uint16_t checkSpool(); // Check if spool exists, return ID +bool createSpool(); // Create spool +void createFilamentFabrik(JsonDocument payload); #endif diff --git a/src/nfc.cpp b/src/nfc.cpp index fe1a486..6a8f7ea 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -37,6 +37,11 @@ volatile nfcReaderStateType nfcReaderState = NFC_IDLE; // ***** PN532 +// ##### Recycling Fabrik ##### +bool isRecyclingFabrik(const char* brand) { + return strcmp(brand, "Recycling Fabrik") == 0; +} + // ##### Funktionen für RFID ##### void payloadToJson(uint8_t *data) { const char* startJson = strchr((char*)data, '{'); @@ -57,7 +62,13 @@ void payloadToJson(uint8_t *data) { int min_temp = doc["min_temp"]; int max_temp = doc["max_temp"]; const char* brand = doc["brand"]; - + + // Recycling Fabrik + if (isRecyclingFabrik(brand)) { + // TODO: Implement specific handling for Recycling Fabrik + Serial.println("Recycling Fabrik erkannt."); + } + Serial.println(); Serial.println("-----------------"); Serial.println("JSON-Parsed Data:"); @@ -215,7 +226,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { } // JSON-Dokument verarbeiten - JsonDocument doc; // Passen Sie die Größe an den JSON-Inhalt an + JsonDocument doc; DeserializationError error = deserializeJson(doc, nfcJsonData); if (error) { @@ -232,7 +243,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()); @@ -254,6 +265,13 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { oledShowProgressBar(1, 1, "Failure", "Scan spool first"); } } + // Recycling Fabrik + else if (isRecyclingFabrik(doc["type"].as().c_str())) { + // If no sm_id is present but the brand is Recycling Fabrik then + // create a new spool, maybe brand too, in Spoolman + Serial.println("Recycling Fabrik Tag found!"); + createFilamentFabrik(doc); + } else { Serial.println("Keine SPOOL-ID gefunden."); From 876e9c62d8b5fdb875a544dc8e3f656a845795d2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 6 Aug 2025 17:38:26 +0200 Subject: [PATCH 157/366] Add JSON structure comments for filament and spool creation --- src/api.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/api.cpp b/src/api.cpp index 5a052e7..2e942b5 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -675,6 +675,27 @@ uint16_t checkFilament(uint16_t vendorId) { } bool createFilament() { + // { + // "name": "PolyTerra Charcoal Black", + // "vendor_id": 0, + // "material": "PLA", + // "price": 20, + // "density": 1.24, + // "diameter": 1.75, + // "weight": 1000, + // "spool_weight": 140, + // "article_number": "PM70820", + // "comment": "automatically generated", + // "settings_extruder_temp": 210, + // "settings_bed_temp": 60, + // "color_hex": "FF0000", + // "multi_color_hexes": "FF0000,00FF00,0000FF", + // "multi_color_direction": "coaxial", + // "external_id": "polymaker_pla_polysonicblack_1000_175", + // "extra": { + // "nozzle_temperature": "string" + // } + // } } @@ -684,6 +705,23 @@ uint16_t checkSpool() { bool createSpool() { // Implement specific handling for Spool creation + // { + // "first_used": "2019-08-24T14:15:22Z", + // "last_used": "2019-08-24T14:15:22Z", + // "filament_id": 0, + // "price": 20, + // "initial_weight": 200, + // "spool_weight": 200, + // "remaining_weight": 800, + // "used_weight": 200, + // "location": "Shelf A", + // "lot_nr": "52342", + // "comment": "", + // "archived": false, + // "extra": { + // "nfc_id": "string" + // } + // } } // #### Spoolman init From b95497aec23a76e4ceaa45badc7a1e13cf8374b9 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Thu, 7 Aug 2025 21:12:01 +0200 Subject: [PATCH 158/366] Further improvements on NFC writing Fixes some issues related to tag writing. Allos writing of tags that are already on the scale when pressing the write button, but introduces a confirmation dialog before doing so. Also first test to fix reset issue when trying to write tags. --- html/rfid.js | 133 +++++++++++++++++++++++++++------------------------ src/nfc.cpp | 28 +++++++---- 2 files changed, 90 insertions(+), 71 deletions(-) diff --git a/html/rfid.js b/html/rfid.js index 52866ea..d6dfa75 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -7,6 +7,7 @@ let heartbeatTimer = null; let lastHeartbeatResponse = Date.now(); const HEARTBEAT_TIMEOUT = 20000; let reconnectTimer = null; +let spoolDetected = false; // WebSocket Funktionen function startHeartbeat() { @@ -508,12 +509,15 @@ function updateNfcStatusIndicator(data) { if (data.found === 0) { // Kein NFC Tag gefunden indicator.className = 'status-circle'; + spoolDetected = false; } else if (data.found === 1) { // NFC Tag erfolgreich gelesen indicator.className = 'status-circle success'; + spoolDetected = true; } else { // Fehler beim Lesen indicator.className = 'status-circle error'; + spoolDetected = true; } } @@ -618,78 +622,83 @@ function updateNfcData(data) { } function writeNfcTag() { - const selectedText = document.getElementById("selected-filament").textContent; - if (selectedText === "Please choose...") { - alert('Please select a Spool first.'); - return; - } + if(!spoolDetected || confirm("Are you sure you want to overwrite the Tag?") == true){ + const selectedText = document.getElementById("selected-filament").textContent; + if (selectedText === "Please choose...") { + alert('Please select a Spool first.'); + return; + } - const spoolsData = window.getSpoolData(); - const selectedSpool = spoolsData.find(spool => - `${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText - ); + const spoolsData = window.getSpoolData(); + const selectedSpool = spoolsData.find(spool => + `${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText + ); - if (!selectedSpool) { - alert('Ausgewählte Spule konnte nicht gefunden werden.'); - return; - } + if (!selectedSpool) { + alert('Ausgewählte Spule konnte nicht gefunden werden.'); + return; + } - // Temperaturwerte korrekt extrahieren - let minTemp = "175"; - let maxTemp = "275"; - - if (Array.isArray(selectedSpool.filament.nozzle_temperature) && - selectedSpool.filament.nozzle_temperature.length >= 2) { - minTemp = String(selectedSpool.filament.nozzle_temperature[0]); - maxTemp = String(selectedSpool.filament.nozzle_temperature[1]); - } + // Temperaturwerte korrekt extrahieren + let minTemp = "175"; + let maxTemp = "275"; + + if (Array.isArray(selectedSpool.filament.nozzle_temperature) && + selectedSpool.filament.nozzle_temperature.length >= 2) { + minTemp = String(selectedSpool.filament.nozzle_temperature[0]); + maxTemp = String(selectedSpool.filament.nozzle_temperature[1]); + } - // Erstelle das NFC-Datenpaket mit korrekten Datentypen - const nfcData = { - color_hex: selectedSpool.filament.color_hex || "FFFFFF", - type: selectedSpool.filament.material, - min_temp: minTemp, - max_temp: maxTemp, - brand: selectedSpool.filament.vendor.name, - sm_id: String(selectedSpool.id) // Konvertiere zu String - }; + // Erstelle das NFC-Datenpaket mit korrekten Datentypen + const nfcData = { + color_hex: selectedSpool.filament.color_hex || "FFFFFF", + type: selectedSpool.filament.material, + min_temp: minTemp, + max_temp: maxTemp, + brand: selectedSpool.filament.vendor.name, + sm_id: String(selectedSpool.id) // Konvertiere zu String + }; - if (socket?.readyState === WebSocket.OPEN) { - const writeButton = document.getElementById("writeNfcButton"); - writeButton.classList.add("writing"); - writeButton.textContent = "Writing"; - socket.send(JSON.stringify({ - type: 'writeNfcTag', - tagType: 'spool', - payload: nfcData - })); - } else { - alert('Not connected to Server. Please check connection.'); + if (socket?.readyState === WebSocket.OPEN) { + const writeButton = document.getElementById("writeNfcButton"); + writeButton.classList.add("writing"); + writeButton.textContent = "Writing"; + socket.send(JSON.stringify({ + type: 'writeNfcTag', + tagType: 'spool', + payload: nfcData + })); + } else { + alert('Not connected to Server. Please check connection.'); + } } } function writeLocationNfcTag() { - const selectedText = document.getElementById("locationSelect").value; - if (selectedText === "Please choose...") { - alert('Please select a location first.'); - return; - } - // Erstelle das NFC-Datenpaket mit korrekten Datentypen - const nfcData = { - location: String(selectedText) - }; + if(!spoolDetected || confirm("Are you sure you want to overwrite the Tag?") == true){ + const selectedText = document.getElementById("locationSelect").value; + if (selectedText === "Please choose...") { + alert('Please select a location first.'); + return; + } + // Erstelle das NFC-Datenpaket mit korrekten Datentypen + const nfcData = { + location: String(selectedText) + }; - if (socket?.readyState === WebSocket.OPEN) { - const writeButton = document.getElementById("writeLocationNfcButton"); - writeButton.classList.add("writing"); - writeButton.textContent = "Writing"; - socket.send(JSON.stringify({ - type: 'writeNfcTag', - tagType: 'location', - payload: nfcData - })); - } else { - alert('Not connected to Server. Please check connection.'); + + if (socket?.readyState === WebSocket.OPEN) { + const writeButton = document.getElementById("writeLocationNfcButton"); + writeButton.classList.add("writing"); + writeButton.textContent = "Writing"; + socket.send(JSON.stringify({ + type: 'writeNfcTag', + tagType: 'location', + payload: nfcData + })); + } else { + alert('Not connected to Server. Please check connection.'); + } } } diff --git a/src/nfc.cpp b/src/nfc.cpp index fe1a486..a68c90a 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -20,6 +20,7 @@ String lastSpoolId = ""; String nfcJsonData = ""; bool tagProcessed = false; volatile bool pauseBambuMqttTask = false; +volatile bool suspendNfcReading = false; struct NfcWriteParameterType { bool tagType; @@ -278,8 +279,10 @@ void writeJsonToTag(void *parameter) { Serial.println(params->payload); nfcReaderState = NFC_WRITING; - vTaskSuspend(RfidReaderTask); - vTaskDelay(50 / portTICK_PERIOD_MS); + suspendNfcReading = true; + //vTaskSuspend(RfidReaderTask); + // make sure to wait 600ms, after that the reading task should be waiting + vTaskDelay(1000 / portTICK_PERIOD_MS); //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert @@ -372,7 +375,8 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - vTaskResume(RfidReaderTask); + suspendNfcReading = false; + //vTaskResume(RfidReaderTask); pauseBambuMqttTask = false; vTaskDelete(NULL); @@ -384,7 +388,7 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { parameters->payload = strdup(payload); // Task nicht mehrfach starten - if (nfcReaderState == NFC_IDLE) { + if (nfcReaderState == NFC_IDLE || nfcReaderState == NFC_READ_ERROR || nfcReaderState == NFC_READ_SUCCESS) { oledShowProgressBar(0, 1, "Write Tag", "Place tag now"); // Erstelle die Task xTaskCreate( @@ -405,7 +409,7 @@ void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != NFC_WRITING) + if (nfcReaderState != NFC_WRITING && !suspendNfcReading) { yield(); @@ -413,7 +417,7 @@ 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, 1000); + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500); foundNfcTag(nullptr, success); @@ -430,8 +434,8 @@ void scanRfidTask(void * parameter) { oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); - vTaskDelay(500 / portTICK_PERIOD_MS); - + //vTaskDelay(500 / portTICK_PERIOD_MS); + if (uidLength == 7) { uint16_t tagSize = readTagSize(); @@ -487,7 +491,7 @@ void scanRfidTask(void * parameter) { } } - if (!success && nfcReaderState != NFC_IDLE) + if (!success && nfcReaderState != NFC_IDLE && !suspendNfcReading) { nfcReaderState = NFC_IDLE; //uidString = ""; @@ -500,6 +504,12 @@ void scanRfidTask(void * parameter) { // aktualisieren der Website wenn sich der Status ändert sendNfcData(); } + else + { + // TBD: Debug only: + Serial.println("NFC Reading disabled"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } yield(); } } From 89a5728cc06c04374e883cbd41b9ff1b857b66f8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 15:33:08 +0200 Subject: [PATCH 159/366] Improves NFC writing workaround and removes debug output Improved version of the NFC writing workaround. The task is no longer suspended. There is now a suspend request and a suspend state variable that is used to communicate between the writing and the reading task. The reading is stopped gracefully to prevent resets during writing. --- src/nfc.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index a68c90a..a95f9ff 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -20,7 +20,8 @@ String lastSpoolId = ""; String nfcJsonData = ""; bool tagProcessed = false; volatile bool pauseBambuMqttTask = false; -volatile bool suspendNfcReading = false; +volatile bool nfcReadingTaskSuspendRequest = false; +volatile bool nfcReadingTaskSuspendState = false; struct NfcWriteParameterType { bool tagType; @@ -279,21 +280,21 @@ void writeJsonToTag(void *parameter) { Serial.println(params->payload); nfcReaderState = NFC_WRITING; - suspendNfcReading = true; - //vTaskSuspend(RfidReaderTask); - // make sure to wait 600ms, after that the reading task should be waiting - vTaskDelay(1000 / portTICK_PERIOD_MS); + + // First request the reading task to be suspended and than wait until it responds + nfcReadingTaskSuspendRequest = true; + while(nfcReadingTaskSuspendState == false){ + vTaskDelay(100 / portTICK_PERIOD_MS); + } //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert sendNfcData(); vTaskDelay(100 / portTICK_PERIOD_MS); - Serial.println("CP 1"); // Wait 10sec for tag uint8_t success = 0; String uidString = ""; for (uint16_t i = 0; i < 20; i++) { - Serial.println("CP 2"); uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; // yield before potentially waiting for 400ms @@ -301,7 +302,6 @@ void writeJsonToTag(void *parameter) { esp_task_wdt_reset(); success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400); if (success) { - Serial.println("CP 3.1"); for (uint8_t i = 0; i < uidLength; i++) { //TBD: Rework to remove all the string operations uidString += String(uid[i], HEX); @@ -311,8 +311,6 @@ void writeJsonToTag(void *parameter) { } foundNfcTag(nullptr, success); break; - }else{ - Serial.println("CP 3.2"); } yield(); @@ -375,8 +373,7 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - suspendNfcReading = false; - //vTaskResume(RfidReaderTask); + nfcReadingTaskSuspendRequest = false; pauseBambuMqttTask = false; vTaskDelete(NULL); @@ -409,8 +406,9 @@ void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != NFC_WRITING && !suspendNfcReading) + if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest) { + nfcReadingTaskSuspendState = false; yield(); uint8_t success; @@ -491,7 +489,7 @@ void scanRfidTask(void * parameter) { } } - if (!success && nfcReaderState != NFC_IDLE && !suspendNfcReading) + if (!success && nfcReaderState != NFC_IDLE && !nfcReadingTaskSuspendRequest) { nfcReaderState = NFC_IDLE; //uidString = ""; @@ -506,7 +504,7 @@ void scanRfidTask(void * parameter) { } else { - // TBD: Debug only: + nfcReadingTaskSuspendState = true; Serial.println("NFC Reading disabled"); vTaskDelay(1000 / portTICK_PERIOD_MS); } From a7c99d3f269b75b1d5b24480a91964008d4466c6 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 15:39:10 +0200 Subject: [PATCH 160/366] Improves init - NFC reading now only starts after boot is finished NFC tags that are on the scale during startup will only be read after the boot sequence is finished. --- src/nfc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index a95f9ff..83dfb5e 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -8,6 +8,7 @@ #include "esp_task_wdt.h" #include "scale.h" #include "bambu.h" +#include "main.h" //Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); @@ -406,7 +407,7 @@ void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest) + if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest && !booting) { nfcReadingTaskSuspendState = false; yield(); From 5509d98969e60dd5bab526a7ce6e5e9f90cbb787 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 16:16:39 +0200 Subject: [PATCH 161/366] Fixes issue that scale not calibrated message was not shown There was no warning any more if the scale is not calibrated. This change fixes that. --- src/config.cpp | 1 - src/config.h | 1 + src/main.cpp | 139 ++++++++++++++++++++++++------------------------- src/scale.cpp | 27 +++++----- src/scale.h | 3 +- 5 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 359031a..60a8803 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -16,7 +16,6 @@ const uint8_t LOADCELL_DOUT_PIN = 16; //16; const uint8_t LOADCELL_SCK_PIN = 17; //17; const uint8_t calVal_eepromAdress = 0; const uint16_t SCALE_LEVEL_WEIGHT = 500; -uint16_t defaultScaleCalibrationValue = 430; // ***** HX711 // ***** TTP223 (Touch Sensor) diff --git a/src/config.h b/src/config.h index 88c57c0..a6468a7 100644 --- a/src/config.h +++ b/src/config.h @@ -22,6 +22,7 @@ #define NVS_NAMESPACE_SCALE "scale" #define NVS_KEY_CALIBRATION "cal_value" #define NVS_KEY_AUTOTARE "auto_tare" +#define SCALE_DEFAULT_CALIBRATION_VALUE 430.0f; #define BAMBU_USERNAME "bblp" diff --git a/src/main.cpp b/src/main.cpp index f160e95..d301583 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -156,94 +156,93 @@ void loop() { } } - // Wenn Waage nicht Kalibriert - if (scaleCalibrated == 3) + // If scale is not calibrated, only show a warning + if (!scaleCalibrated) { - oledShowMessage("Scale not calibrated!"); - vTaskDelay(5000 / portTICK_PERIOD_MS); - yield(); - esp_task_wdt_reset(); - - return; - } - - // Ausgabe der Waage auf Display - if(pauseMainTask == 0) - { - if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0))) - { - (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); + // Do not show the warning if the calibratin process is onging + if(!scaleCalibrationActive){ + oledShowMessage("Scale not calibrated"); + vTaskDelay(1000 / portTICK_PERIOD_MS); } - mainTaskWasPaused = false; - } - else - { - mainTaskWasPaused = true; - } - - - // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird - if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING) - { - lastWeightReadTime = currentMillis; - - // Prüfen ob die Waage korrekt genullt ist - // Abweichung von 2g ignorieren - if (autoTare && (weight > 2 && weight < 7) || weight < -2) + }else{ + // Ausgabe der Waage auf Display + if(pauseMainTask == 0) { - scale_tare_counter++; + if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0))) + { + (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight); + } + mainTaskWasPaused = false; } else { - scale_tare_counter = 0; + mainTaskWasPaused = true; } - // Prüfen ob das Gewicht gleich bleibt und dann senden - if (abs(weight - lastWeight) <= 2 && weight > 5) + + // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird + if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING) { - weigthCouterToApi++; - } - else + 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) + { + weigthCouterToApi++; + } + else + { + weigthCouterToApi = 0; + weightSend = 0; + } + } + + // 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; - weightSend = 0; } - } + + lastWeight = weight; - // 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; - } - - 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) { + // set the current tag as processed to prevent it beeing processed again + tagProcessed = true; - // 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) { - // set the current tag as processed to prevent it beeing processed again - tagProcessed = true; - - if (updateSpoolWeight(activeSpoolId, weight)) - { - weightSend = 1; - + if (updateSpoolWeight(activeSpoolId, weight)) + { + weightSend = 1; + + } + else + { + oledShowIcon("failed"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } } - else - { - oledShowIcon("failed"); - vTaskDelay(2000 / portTICK_PERIOD_MS); - } - } - if(sendOctoUpdate && spoolmanApiState == API_IDLE){ - autoSetToBambuSpoolId = activeSpoolId.toInt(); + if(sendOctoUpdate && spoolmanApiState == API_IDLE){ + autoSetToBambuSpoolId = activeSpoolId.toInt(); - if(octoEnabled) - { - updateSpoolOcto(autoSetToBambuSpoolId); + if(octoEnabled) + { + updateSpoolOcto(autoSetToBambuSpoolId); + } + sendOctoUpdate = false; } - sendOctoUpdate = false; } esp_task_wdt_reset(); diff --git a/src/scale.cpp b/src/scale.cpp index 4be30c7..201618d 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -17,8 +17,9 @@ uint8_t weigthCouterToApi = 0; uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; uint8_t pauseMainTask = 0; -uint8_t scaleCalibrated = 1; +bool scaleCalibrated; bool autoTare = true; +bool scaleCalibrationActive = false; // ##### Funktionen für Waage ##### uint8_t setAutoTare(bool autoTareValue) { @@ -88,7 +89,13 @@ void start_scale(bool touchSensorConnected) { // NVS lesen Preferences preferences; preferences.begin(NVS_NAMESPACE_SCALE, true); // true = readonly - calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue); + if(preferences.isKey(NVS_KEY_CALIBRATION)){ + calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION); + scaleCalibrated = true; + }else{ + calibrationValue = SCALE_DEFAULT_CALIBRATION_VALUE; + scaleCalibrated = false; + } // auto Tare // Wenn Touch Sensor verbunden, dann autoTare auf false setzen @@ -103,18 +110,6 @@ void start_scale(bool touchSensorConnected) { scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); - if (isnan(calibrationValue) || calibrationValue < 1) { - calibrationValue = defaultScaleCalibrationValue; - scaleCalibrated = 0; - - oledShowMessage("Scale not calibrated!"); - for (uint16_t i = 0; i < 50000; i++) { - yield(); - vTaskDelay(pdMS_TO_TICKS(1)); - esp_task_wdt_reset(); - } - } - oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Tare scale"); for (uint16_t i = 0; i < 2000; i++) { yield(); @@ -152,6 +147,8 @@ uint8_t calibrate_scale() { uint8_t returnState = 0; float newCalibrationValue; + scaleCalibrationActive = true; + vTaskSuspend(RfidReaderTask); vTaskSuspend(ScaleTask); @@ -228,6 +225,7 @@ uint8_t calibrate_scale() { esp_task_wdt_reset(); } + scaleCalibrated = true; returnState = 1; } else @@ -262,6 +260,7 @@ uint8_t calibrate_scale() { vTaskResume(ScaleTask); pauseBambuMqttTask = false; pauseMainTask = 0; + scaleCalibrationActive = false; return returnState; } diff --git a/src/scale.h b/src/scale.h index 96f59a4..c38583a 100644 --- a/src/scale.h +++ b/src/scale.h @@ -15,8 +15,9 @@ extern uint8_t weigthCouterToApi; extern uint8_t scale_tare_counter; extern uint8_t scaleTareRequest; extern uint8_t pauseMainTask; -extern uint8_t scaleCalibrated; +extern bool scaleCalibrated; extern bool autoTare; +extern bool scaleCalibrationActive; extern TaskHandle_t ScaleTask; From 4706152022defdb2c83fc212bda7b348e7753e41 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 18:00:25 +0200 Subject: [PATCH 162/366] Introduces periodic Spoolman Healthcheck Introduces a spoolman healthcheck that is executed every 60 seconds. Also fixes a bug with the periodic wifi update. --- src/api.cpp | 395 +++++++++++++++++++++++++++------------------------ src/api.h | 2 +- src/config.h | 52 +++---- src/main.cpp | 13 +- src/nfc.cpp | 2 - 5 files changed, 249 insertions(+), 215 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 4b65f4b..8770fd2 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -5,7 +5,7 @@ #include #include "debug.h" -volatile spoolmanApiStateType spoolmanApiState = API_INIT; +volatile spoolmanApiStateType spoolmanApiState = API_IDLE; //bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; @@ -14,6 +14,8 @@ String octoUrl = ""; String octoToken = ""; uint16_t remainingWeight = 0; bool spoolmanConnected = false; +bool spoolmanExtraFieldsChecked = false; +TaskHandle_t* apiTask; struct SendToApiParams { SpoolmanApiRequestType requestType; @@ -94,6 +96,11 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) { void sendToApi(void *parameter) { HEAP_DEBUG_MESSAGE("sendToApi begin"); + // Wait until API is IDLE + while(spoolmanApiState != API_IDLE){ + Serial.println("Waiting!"); + yield(); + } spoolmanApiState = API_TRANSMITTING; SendToApiParams* params = (SendToApiParams*)parameter; @@ -236,7 +243,7 @@ bool updateSpoolTagId(String uidString, const char* payload) { 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität - NULL // Task-Handle (nicht benötigt) + apiTask // Task-Handle (nicht benötigt) ); updateDoc.clear(); @@ -282,7 +289,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) { 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität - NULL // Task-Handle (nicht benötigt) + apiTask // Task-Handle (nicht benötigt) ); updateDoc.clear(); @@ -319,17 +326,17 @@ uint8_t updateSpoolLocation(String spoolId, String location){ params->spoolsUrl = spoolsUrl; params->updatePayload = updatePayload; - if(spoolmanApiState == API_IDLE){ - // 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) - ); + if(apiTask == nullptr){ + // Erstelle die Task + BaseType_t result = xTaskCreate( + sendToApi, // Task-Funktion + "SendToApiTask", // Task-Name + 6144, // Stackgröße in Bytes + (void*)params, // Parameter + 0, // Priorität + apiTask // Task-Handle + ); }else{ Serial.println("Not spawning new task, API still active!"); } @@ -374,7 +381,7 @@ bool updateSpoolOcto(int spoolId) { 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität - NULL // Task-Handle (nicht benötigt) + apiTask // Task-Handle (nicht benötigt) ); updateDoc.clear(); @@ -427,7 +434,7 @@ bool updateSpoolBambuData(String payload) { 6144, // Stackgröße in Bytes (void*)params, // Parameter 0, // Priorität - NULL // Task-Handle (nicht benötigt) + apiTask // Task-Handle (nicht benötigt) ); return true; @@ -435,198 +442,222 @@ bool updateSpoolBambuData(String payload) { // #### Spoolman init bool checkSpoolmanExtraFields() { - HTTPClient http; - String checkUrls[] = { - spoolmanUrl + apiUrl + "/field/spool", - spoolmanUrl + apiUrl + "/field/filament" - }; + // Only check extra fields if they have not been checked before + if(!spoolmanExtraFieldsChecked){ + HTTPClient http; + String checkUrls[] = { + spoolmanUrl + apiUrl + "/field/spool", + spoolmanUrl + apiUrl + "/field/filament" + }; - String spoolExtra[] = { - "nfc_id" - }; + String spoolExtra[] = { + "nfc_id" + }; - String filamentExtra[] = { - "nozzle_temperature", - "price_meter", - "price_gramm", - "bambu_setting_id", - "bambu_cali_id", - "bambu_idx", - "bambu_k", - "bambu_flow_ratio", - "bambu_max_volspeed" - }; + String filamentExtra[] = { + "nozzle_temperature", + "price_meter", + "price_gramm", + "bambu_setting_id", + "bambu_cali_id", + "bambu_idx", + "bambu_k", + "bambu_flow_ratio", + "bambu_max_volspeed" + }; - String spoolExtraFields[] = { - "{\"name\": \"NFC ID\"," - "\"key\": \"nfc_id\"," - "\"field_type\": \"text\"}" - }; + String spoolExtraFields[] = { + "{\"name\": \"NFC ID\"," + "\"key\": \"nfc_id\"," + "\"field_type\": \"text\"}" + }; - String filamentExtraFields[] = { - "{\"name\": \"Nozzle Temp\"," - "\"unit\": \"°C\"," - "\"field_type\": \"integer_range\"," - "\"default_value\": \"[190,230]\"," - "\"key\": \"nozzle_temperature\"}", + String filamentExtraFields[] = { + "{\"name\": \"Nozzle Temp\"," + "\"unit\": \"°C\"," + "\"field_type\": \"integer_range\"," + "\"default_value\": \"[190,230]\"," + "\"key\": \"nozzle_temperature\"}", - "{\"name\": \"Price/m\"," - "\"unit\": \"€\"," - "\"field_type\": \"float\"," - "\"key\": \"price_meter\"}", + "{\"name\": \"Price/m\"," + "\"unit\": \"€\"," + "\"field_type\": \"float\"," + "\"key\": \"price_meter\"}", + + "{\"name\": \"Price/g\"," + "\"unit\": \"€\"," + "\"field_type\": \"float\"," + "\"key\": \"price_gramm\"}", + + "{\"name\": \"Bambu Setting ID\"," + "\"field_type\": \"text\"," + "\"key\": \"bambu_setting_id\"}", + + "{\"name\": \"Bambu Cali ID\"," + "\"field_type\": \"text\"," + "\"key\": \"bambu_cali_id\"}", + + "{\"name\": \"Bambu Filament IDX\"," + "\"field_type\": \"text\"," + "\"key\": \"bambu_idx\"}", + + "{\"name\": \"Bambu k\"," + "\"field_type\": \"float\"," + "\"key\": \"bambu_k\"}", + + "{\"name\": \"Bambu Flow Ratio\"," + "\"field_type\": \"float\"," + "\"key\": \"bambu_flow_ratio\"}", + + "{\"name\": \"Bambu Max Vol. Speed\"," + "\"unit\": \"mm3/s\"," + "\"field_type\": \"integer\"," + "\"default_value\": \"12\"," + "\"key\": \"bambu_max_volspeed\"}" + }; + + Serial.println("Überprüfe Extrafelder..."); + + int urlLength = sizeof(checkUrls) / sizeof(checkUrls[0]); + + for (uint8_t i = 0; i < urlLength; i++) { + Serial.println(); + Serial.println("-------- Prüfe Felder für "+checkUrls[i]+" --------"); + http.begin(checkUrls[i]); + int httpCode = http.GET(); - "{\"name\": \"Price/g\"," - "\"unit\": \"€\"," - "\"field_type\": \"float\"," - "\"key\": \"price_gramm\"}", + if (httpCode == HTTP_CODE_OK) { + String payload = http.getString(); + JsonDocument doc; + DeserializationError error = deserializeJson(doc, payload); + if (!error) { + String* extraFields; + String* extraFieldData; + u16_t extraLength; - "{\"name\": \"Bambu Setting ID\"," - "\"field_type\": \"text\"," - "\"key\": \"bambu_setting_id\"}", - - "{\"name\": \"Bambu Cali ID\"," - "\"field_type\": \"text\"," - "\"key\": \"bambu_cali_id\"}", - - "{\"name\": \"Bambu Filament IDX\"," - "\"field_type\": \"text\"," - "\"key\": \"bambu_idx\"}", - - "{\"name\": \"Bambu k\"," - "\"field_type\": \"float\"," - "\"key\": \"bambu_k\"}", - - "{\"name\": \"Bambu Flow Ratio\"," - "\"field_type\": \"float\"," - "\"key\": \"bambu_flow_ratio\"}", - - "{\"name\": \"Bambu Max Vol. Speed\"," - "\"unit\": \"mm3/s\"," - "\"field_type\": \"integer\"," - "\"default_value\": \"12\"," - "\"key\": \"bambu_max_volspeed\"}" - }; - - Serial.println("Überprüfe Extrafelder..."); - - int urlLength = sizeof(checkUrls) / sizeof(checkUrls[0]); - - for (uint8_t i = 0; i < urlLength; i++) { - Serial.println(); - Serial.println("-------- Prüfe Felder für "+checkUrls[i]+" --------"); - http.begin(checkUrls[i]); - int httpCode = http.GET(); - - if (httpCode == HTTP_CODE_OK) { - String payload = http.getString(); - JsonDocument doc; - DeserializationError error = deserializeJson(doc, payload); - if (!error) { - String* extraFields; - String* extraFieldData; - u16_t extraLength; - - if (i == 0) { - extraFields = spoolExtra; - extraFieldData = spoolExtraFields; - extraLength = sizeof(spoolExtra) / sizeof(spoolExtra[0]); - } else { - extraFields = filamentExtra; - extraFieldData = filamentExtraFields; - extraLength = sizeof(filamentExtra) / sizeof(filamentExtra[0]); - } - - for (uint8_t s = 0; s < extraLength; s++) { - bool found = false; - for (JsonObject field : doc.as()) { - if (field["key"].is() && field["key"] == extraFields[s]) { - Serial.println("Feld gefunden: " + extraFields[s]); - found = true; - break; - } + if (i == 0) { + extraFields = spoolExtra; + extraFieldData = spoolExtraFields; + extraLength = sizeof(spoolExtra) / sizeof(spoolExtra[0]); + } else { + extraFields = filamentExtra; + extraFieldData = filamentExtraFields; + extraLength = sizeof(filamentExtra) / sizeof(filamentExtra[0]); } - if (!found) { - Serial.println("Feld nicht gefunden: " + extraFields[s]); - // Extrafeld hinzufügen - http.begin(checkUrls[i] + "/" + extraFields[s]); - http.addHeader("Content-Type", "application/json"); - int httpCode = http.POST(extraFieldData[s]); + for (uint8_t s = 0; s < extraLength; s++) { + bool found = false; + for (JsonObject field : doc.as()) { + if (field["key"].is() && field["key"] == extraFields[s]) { + Serial.println("Feld gefunden: " + extraFields[s]); + found = true; + break; + } + } + if (!found) { + Serial.println("Feld nicht gefunden: " + extraFields[s]); - if (httpCode > 0) { - // Antwortscode und -nachricht abrufen - String response = http.getString(); - //Serial.println("HTTP-Code: " + String(httpCode)); - //Serial.println("Antwort: " + response); - if (httpCode != HTTP_CODE_OK) { + // Extrafeld hinzufügen + http.begin(checkUrls[i] + "/" + extraFields[s]); + http.addHeader("Content-Type", "application/json"); + int httpCode = http.POST(extraFieldData[s]); + if (httpCode > 0) { + // Antwortscode und -nachricht abrufen + String response = http.getString(); + //Serial.println("HTTP-Code: " + String(httpCode)); + //Serial.println("Antwort: " + response); + if (httpCode != HTTP_CODE_OK) { + + return false; + } + } else { + // Fehler beim Senden der Anfrage + Serial.println("Fehler beim Senden der Anfrage: " + String(http.errorToString(httpCode))); return false; } - } else { - // Fehler beim Senden der Anfrage - Serial.println("Fehler beim Senden der Anfrage: " + String(http.errorToString(httpCode))); - return false; + //http.end(); } - //http.end(); + yield(); + vTaskDelay(100 / portTICK_PERIOD_MS); } - yield(); - vTaskDelay(100 / portTICK_PERIOD_MS); } + doc.clear(); } - doc.clear(); } + + Serial.println("-------- ENDE Prüfe Felder --------"); + Serial.println(); + + http.end(); + + spoolmanExtraFieldsChecked = true; + return true; + }else{ + return true; } - - Serial.println("-------- ENDE Prüfe Felder --------"); - Serial.println(); - - http.end(); - - return true; } -bool checkSpoolmanInstance(const String& url) { +bool checkSpoolmanInstance() { HTTPClient http; - String healthUrl = url + apiUrl + "/health"; + bool returnValue = false; - Serial.print("Überprüfe Spoolman-Instanz unter: "); - Serial.println(healthUrl); + // Only do the spoolman instance check if there is no active API request going on + if(spoolmanApiState == API_IDLE){ + spoolmanApiState = API_TRANSMITTING; + String healthUrl = spoolmanUrl + apiUrl + "/health"; - http.begin(healthUrl); - int httpCode = http.GET(); + Serial.print("Checking spoolman instance: "); + Serial.println(healthUrl); - if (httpCode > 0) { - if (httpCode == HTTP_CODE_OK) { - String payload = http.getString(); - JsonDocument doc; - DeserializationError error = deserializeJson(doc, payload); - if (!error && doc["status"].is()) { - const char* status = doc["status"]; - http.end(); + http.begin(healthUrl); + int httpCode = http.GET(); - if (!checkSpoolmanExtraFields()) { - Serial.println("Fehler beim Überprüfen der Extrafelder."); + if (httpCode > 0) { + if (httpCode == HTTP_CODE_OK) { + String payload = http.getString(); + JsonDocument doc; + DeserializationError error = deserializeJson(doc, payload); + if (!error && doc["status"].is()) { + const char* status = doc["status"]; + http.end(); - // TBD - oledShowMessage("Spoolman Error creating Extrafields"); - vTaskDelay(2000 / portTICK_PERIOD_MS); - - return false; + if (!checkSpoolmanExtraFields()) { + Serial.println("Fehler beim Überprüfen der Extrafelder."); + + // TBD + oledShowMessage("Spoolman Error creating Extrafields"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + + return false; + } + + spoolmanApiState = API_IDLE; + oledShowTopRow(); + spoolmanConnected = true; + returnValue = strcmp(status, "healthy") == 0; + }else{ + spoolmanConnected = false; } - spoolmanApiState = API_IDLE; - oledShowTopRow(); - spoolmanConnected = true; - return strcmp(status, "healthy") == 0; + doc.clear(); + }else{ + spoolmanConnected = false; } - - doc.clear(); + } else { + spoolmanConnected = false; + Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); } - } else { - Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); + http.end(); + returnValue = false; + spoolmanApiState = API_IDLE; + }else{ + // If the check is skipped, return the previous status + Serial.println("Skipping spoolman healthcheck, API is active."); + returnValue = spoolmanConnected; } - http.end(); - return false; + Serial.println("Healthcheck completed!"); + return returnValue; } bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, const String& octoTk) { @@ -639,12 +670,13 @@ bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, con preferences.end(); //TBD: This could be handled nicer in the future + spoolmanExtraFieldsChecked = false; spoolmanUrl = url; octoEnabled = octoOn; octoUrl = octo_url; octoToken = octoTk; - return true; + return checkSpoolmanInstance(); } String loadSpoolmanUrl() { @@ -664,15 +696,10 @@ String loadSpoolmanUrl() { bool initSpoolman() { oledShowProgressBar(3, 7, DISPLAY_BOOT_TEXT, "Spoolman init"); spoolmanUrl = loadSpoolmanUrl(); - spoolmanUrl.trim(); - if (spoolmanUrl == "") { - Serial.println("Keine Spoolman-URL gefunden."); - return false; - } - - bool success = checkSpoolmanInstance(spoolmanUrl); + + bool success = checkSpoolmanInstance(); if (!success) { - Serial.println("Spoolman nicht erreichbar."); + Serial.println("Spoolman not available"); return false; } diff --git a/src/api.h b/src/api.h index 23fb6d8..4ad427f 100644 --- a/src/api.h +++ b/src/api.h @@ -29,7 +29,7 @@ extern String octoUrl; extern String octoToken; extern bool spoolmanConnected; -bool checkSpoolmanInstance(const String& url); +bool checkSpoolmanInstance(); bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk); String loadSpoolmanUrl(); // Neue Funktion zum Laden der URL bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafelder diff --git a/src/config.h b/src/config.h index a6468a7..cd79e38 100644 --- a/src/config.h +++ b/src/config.h @@ -3,37 +3,39 @@ #include -#define BAMBU_DEFAULT_AUTOSEND_TIME 60 +#define BAMBU_DEFAULT_AUTOSEND_TIME 60 +#define NVS_NAMESPACE_API "api" +#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl" +#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled" +#define NVS_KEY_OCTOPRINT_URL "octoUrl" +#define NVS_KEY_OCTOPRINT_TOKEN "octoToken" -#define NVS_NAMESPACE_API "api" -#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl" -#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled" -#define NVS_KEY_OCTOPRINT_URL "octoUrl" -#define NVS_KEY_OCTOPRINT_TOKEN "octoToken" +#define NVS_NAMESPACE_BAMBU "bambu" +#define NVS_KEY_BAMBU_IP "bambuIp" +#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode" +#define NVS_KEY_BAMBU_SERIAL "bambuSerial" +#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable" +#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime" -#define NVS_NAMESPACE_BAMBU "bambu" -#define NVS_KEY_BAMBU_IP "bambuIp" -#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode" -#define NVS_KEY_BAMBU_SERIAL "bambuSerial" -#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable" -#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime" +#define NVS_NAMESPACE_SCALE "scale" +#define NVS_KEY_CALIBRATION "cal_value" +#define NVS_KEY_AUTOTARE "auto_tare" +#define SCALE_DEFAULT_CALIBRATION_VALUE 430.0f; -#define NVS_NAMESPACE_SCALE "scale" -#define NVS_KEY_CALIBRATION "cal_value" -#define NVS_KEY_AUTOTARE "auto_tare" -#define SCALE_DEFAULT_CALIBRATION_VALUE 430.0f; +#define BAMBU_USERNAME "bblp" -#define BAMBU_USERNAME "bblp" - -#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) -#define SCREEN_ADDRESS 0x3CU // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 -#define SCREEN_WIDTH 128U -#define SCREEN_HEIGHT 64U -#define SCREEN_TOP_BAR_HEIGHT 16U -#define SCREEN_PROGRESS_BAR_HEIGHT 12U -#define DISPLAY_BOOT_TEXT "FilaMan" +#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +#define SCREEN_ADDRESS 0x3CU // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 +#define SCREEN_WIDTH 128U +#define SCREEN_HEIGHT 64U +#define SCREEN_TOP_BAR_HEIGHT 16U +#define SCREEN_PROGRESS_BAR_HEIGHT 12U +#define DISPLAY_BOOT_TEXT "FilaMan" +#define WIFI_CHECK_INTERVAL 60000U +#define DISPLAY_UPDATE_INTERVAL 1000U +#define SPOOLMAN_HEALTHCHECK_INTERVAL 60000U extern const uint8_t PN532_IRQ; extern const uint8_t PN532_RESET; diff --git a/src/main.cpp b/src/main.cpp index d301583..2b75b6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -97,7 +97,8 @@ int16_t lastWeight = 0; // WIFI check variables unsigned long lastWifiCheckTime = 0; -const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms) +unsigned long lastTopRowUpdateTime = 0; +unsigned long lastSpoolmanHealcheckTime = 0; // Button debounce variables unsigned long lastButtonPress = 0; @@ -115,17 +116,23 @@ void loop() { } // Überprüfe regelmäßig die WLAN-Verbindung - if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval)) + if (intervalElapsed(currentMillis, lastWifiCheckTime, WIFI_CHECK_INTERVAL)) { checkWiFiConnection(); } // Periodic display update - if (intervalElapsed(currentMillis, lastWifiCheckTime, 1000)) + if (intervalElapsed(currentMillis, lastTopRowUpdateTime, DISPLAY_UPDATE_INTERVAL)) { oledShowTopRow(); } + // Periodic spoolman health check + if (intervalElapsed(currentMillis, lastSpoolmanHealcheckTime, SPOOLMAN_HEALTHCHECK_INTERVAL)) + { + checkSpoolmanInstance(); + } + // Wenn Bambu auto set Spool aktiv if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0) { diff --git a/src/nfc.cpp b/src/nfc.cpp index 83dfb5e..5a8bdc1 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -241,8 +241,6 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as()); activeSpoolId = doc["sm_id"].as(); lastSpoolId = activeSpoolId; - - Serial.println("Api state: " + String(spoolmanApiState)); } else if(doc["location"].is() && doc["location"] != "") { From 5fa93f2695dd0bc1104379eba958c03eb4a5672b Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 18:14:26 +0200 Subject: [PATCH 163/366] Adds a link to the spool in spoolman when reading a spool tag Adds a link to the website that lets the user directly jump to the spool in spoolman that is currently scanned. --- html/rfid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/rfid.js b/html/rfid.js index d6dfa75..ae9cd68 100644 --- a/html/rfid.js +++ b/html/rfid.js @@ -578,7 +578,7 @@ function updateNfcData(data) { `; // Spoolman ID anzeigen - html += `

Spoolman ID: ${data.sm_id || 'No Spoolman ID'}

`; + html += `

Spoolman ID: ${data.sm_id} (Open in Spoolman)

`; } else if(data.location) { From f7484f635ef113054a6db6a8b531ff107f9987c3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 10 Aug 2025 14:39:44 +0200 Subject: [PATCH 164/366] docs: update platformio.ini for version v1.5.8 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index f1d49c8..1e8f441 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.7" +version = "1.5.8" to_old_version = "1.5.0" ## From fdeb6d5b6166e34279eb29adf057017c04e753c6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 10 Aug 2025 14:39:44 +0200 Subject: [PATCH 165/366] docs: update platformio.ini for version v1.5.8 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index f1d49c8..1e8f441 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.7" +version = "1.5.8" to_old_version = "1.5.0" ## From 7cbd34bc916af4ee07a3b8a90e877979461fad03 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 10 Aug 2025 14:39:44 +0200 Subject: [PATCH 166/366] docs: update changelog and header for version v1.5.8 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59dcbc0..a672d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [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 From 174c48f734ee121a7d85b3cab332e272365f11d9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sun, 10 Aug 2025 14:39:44 +0200 Subject: [PATCH 167/366] docs: update changelog and header for version v1.5.8 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59dcbc0..a672d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [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 From 377f4bc1466fa43f7d25cfeacd031a4dfbb4d4fd Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:17:57 +0200 Subject: [PATCH 168/366] Enhance API to support weight updates after successful spool tag updates --- src/api.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8770fd2..59da05e 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -4,6 +4,7 @@ #include "commonFS.h" #include #include "debug.h" +#include "scale.h" volatile spoolmanApiStateType spoolmanApiState = API_IDLE; //bool spoolman_connected = false; @@ -23,6 +24,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) { @@ -104,12 +109,15 @@ void sendToApi(void *parameter) { 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); @@ -163,6 +171,57 @@ void sendToApi(void *parameter) { } } 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 + http.begin(weightUrl); + http.addHeader("Content-Type", "application/json"); + + int weightHttpCode = http.PUT(weightPayload); + + if (weightHttpCode == HTTP_CODE_OK) { + Serial.println("Weight update successful"); + String weightResponse = http.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"); + } + + weightDoc.clear(); + } } else { switch(requestType){ case API_REQUEST_SPOOL_WEIGHT_UPDATE: @@ -211,7 +270,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 +295,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; } From 619979ab14f501b2eee3c430c7011c42d609b9c2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:17:57 +0200 Subject: [PATCH 169/366] Enhance API to support weight updates after successful spool tag updates --- src/api.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8770fd2..59da05e 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -4,6 +4,7 @@ #include "commonFS.h" #include #include "debug.h" +#include "scale.h" volatile spoolmanApiStateType spoolmanApiState = API_IDLE; //bool spoolman_connected = false; @@ -23,6 +24,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) { @@ -104,12 +109,15 @@ void sendToApi(void *parameter) { 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); @@ -163,6 +171,57 @@ void sendToApi(void *parameter) { } } 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 + http.begin(weightUrl); + http.addHeader("Content-Type", "application/json"); + + int weightHttpCode = http.PUT(weightPayload); + + if (weightHttpCode == HTTP_CODE_OK) { + Serial.println("Weight update successful"); + String weightResponse = http.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"); + } + + weightDoc.clear(); + } } else { switch(requestType){ case API_REQUEST_SPOOL_WEIGHT_UPDATE: @@ -211,7 +270,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 +295,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; } From 88598611c5d7104d63e0f2b25aa5dbd64d13715d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:18:12 +0200 Subject: [PATCH 170/366] docs: update platformio.ini for version v1.5.9 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1e8f441..9b2f1b0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.8" +version = "1.5.9" to_old_version = "1.5.0" ## From 7ccdde84895ac412b0550645b6b92c31589c9419 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:18:12 +0200 Subject: [PATCH 171/366] docs: update platformio.ini for version v1.5.9 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1e8f441..9b2f1b0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.8" +version = "1.5.9" to_old_version = "1.5.0" ## From e4d1ba6c1c2ec686596a1be340f833550d00365a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:18:12 +0200 Subject: [PATCH 172/366] docs: update changelog and header for version v1.5.9 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a672d59..9752905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 86e5f7e48a97ddc66f268c349563be85157c773f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 11 Aug 2025 14:18:12 +0200 Subject: [PATCH 173/366] docs: update changelog and header for version v1.5.9 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a672d59..9752905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 65967ca047b49739f2a8632c23edef135c8f6343 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 23 Aug 2025 19:01:07 +0200 Subject: [PATCH 174/366] Changed Amazon Link for PN532 --- README.de.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.de.md b/README.de.md index ab970ab..248e67c 100644 --- a/README.de.md +++ b/README.de.md @@ -62,7 +62,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..1988b0c 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,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 From 55200d31cdfb49a266f7712ce991e105eb417c11 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 23 Aug 2025 19:01:07 +0200 Subject: [PATCH 175/366] Changed Amazon Link for PN532 --- README.de.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.de.md b/README.de.md index ab970ab..248e67c 100644 --- a/README.de.md +++ b/README.de.md @@ -62,7 +62,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..1988b0c 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,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 From 9e58b042c82dd11810b81c6df7315fb8995b9ad3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:21:29 +0200 Subject: [PATCH 176/366] fix: improve weight processing logic and add auto-send feature for Bambu spool ID --- .gitignore | 1 + src/main.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index b9774e9..a6e7ff5 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ test/README data/* !data/ !data/.gitkeep +# important html/bambu_credentials.json html/spoolman_url.json _local/* diff --git a/src/main.cpp b/src/main.cpp index 2b75b6c..9c757c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -225,7 +225,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 +234,11 @@ void loop() { { weightSend = 1; + // Set Bambu spool ID for auto-send if enabled + if (bambuCredentials.autosend_enable) + { + autoSetToBambuSpoolId = activeSpoolId.toInt(); + } } else { @@ -241,13 +247,9 @@ void loop() { } } - if(sendOctoUpdate && spoolmanApiState == API_IDLE){ - autoSetToBambuSpoolId = activeSpoolId.toInt(); - - if(octoEnabled) - { - updateSpoolOcto(autoSetToBambuSpoolId); - } + if(octoEnabled && sendOctoUpdate && spoolmanApiState == API_IDLE) + { + updateSpoolOcto(autoSetToBambuSpoolId); sendOctoUpdate = false; } } From 9e67af7343a31547782a77237087a3772675d9ec Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:21:29 +0200 Subject: [PATCH 177/366] fix: improve weight processing logic and add auto-send feature for Bambu spool ID --- .gitignore | 1 + src/main.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index b9774e9..a6e7ff5 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ test/README data/* !data/ !data/.gitkeep +# important html/bambu_credentials.json html/spoolman_url.json _local/* diff --git a/src/main.cpp b/src/main.cpp index 2b75b6c..9c757c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -225,7 +225,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 +234,11 @@ void loop() { { weightSend = 1; + // Set Bambu spool ID for auto-send if enabled + if (bambuCredentials.autosend_enable) + { + autoSetToBambuSpoolId = activeSpoolId.toInt(); + } } else { @@ -241,13 +247,9 @@ void loop() { } } - if(sendOctoUpdate && spoolmanApiState == API_IDLE){ - autoSetToBambuSpoolId = activeSpoolId.toInt(); - - if(octoEnabled) - { - updateSpoolOcto(autoSetToBambuSpoolId); - } + if(octoEnabled && sendOctoUpdate && spoolmanApiState == API_IDLE) + { + updateSpoolOcto(autoSetToBambuSpoolId); sendOctoUpdate = false; } } From 15219fa1e407282b7a0acf02904e1a8e9843e819 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:40:40 +0200 Subject: [PATCH 178/366] docs: update platformio.ini for version v1.5.10 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 9b2f1b0..19a8651 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.9" +version = "1.5.10" to_old_version = "1.5.0" ## From cd1c93c48563cbc720efe6d3d2b9b283886ce3e5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:40:41 +0200 Subject: [PATCH 179/366] docs: update changelog and header for version v1.5.10 --- CHANGELOG.md | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9752905..c32d709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,206 @@ # Changelog +## [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 From 164c7b2af59e2c720053abeaba556753de430e7a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:46:13 +0200 Subject: [PATCH 180/366] docs: update platformio.ini for version v1.5.11 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 19a8651..d00be85 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.10" +version = "1.5.11" to_old_version = "1.5.0" ## From 5c2db22a90e64d23ff3d54c5975b2ca75a35c51d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 27 Aug 2025 17:46:13 +0200 Subject: [PATCH 181/366] docs: update changelog and header for version v1.5.11 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c32d709..68bf7bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [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 From 1eb81fad5dbc88901b4d7602aabc3dda966e724f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:29:21 +0200 Subject: [PATCH 182/366] fix: adjust spacing in loop structure and enable tare function in scale loop --- src/main.cpp | 4 +++- src/scale.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9c757c8..fd12e8c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -171,7 +171,9 @@ void loop() { oledShowMessage("Scale not calibrated"); vTaskDelay(1000 / portTICK_PERIOD_MS); } - }else{ + } + else + { // Ausgabe der Waage auf Display if(pauseMainTask == 0) { diff --git a/src/scale.cpp b/src/scale.cpp index 201618d..24d8797 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -48,6 +48,8 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); + scale.tare(); + for(;;) { if (scale.is_ready()) { @@ -120,7 +122,7 @@ void start_scale(bool touchSensorConnected) { 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(); + //scale.tare(); } // Display Gewicht From ec7386922eda7692c31539f2a8e0026aa6d98987 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:29:36 +0200 Subject: [PATCH 183/366] docs: update platformio.ini for beta version v1.5.11-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index d00be85..36dd2d5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.11" +version = "1.5.11-beta1" to_old_version = "1.5.0" ## From c17ab2c434de9a7bf330c50345ebcd2ede235d4e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:29:36 +0200 Subject: [PATCH 184/366] docs: update changelog and header for version v1.5.11-beta1 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68bf7bc..ff42847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 99babe2b4a3a8043eeefb1bb9708b36a2f9d485c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:45:16 +0200 Subject: [PATCH 185/366] fix: add logging for healthy spoolman instance check --- src/api.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api.cpp b/src/api.cpp index 59da05e..2a9cb1d 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -700,6 +700,8 @@ bool checkSpoolmanInstance() { oledShowTopRow(); spoolmanConnected = true; returnValue = strcmp(status, "healthy") == 0; + Serial.print("Spoolman instance is healthy: "); + Serial.println(returnValue); }else{ spoolmanConnected = false; } From 513e02b867b86d98b49255a65d061a5ee7f6ed6d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:45:35 +0200 Subject: [PATCH 186/366] docs: update platformio.ini for beta version v1.5.11-beta2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 36dd2d5..85e33ee 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.11-beta1" +version = "1.5.11-beta2" to_old_version = "1.5.0" ## From dca9ef8d083a91e535cd78f8e11cf093b9652dae Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:45:35 +0200 Subject: [PATCH 187/366] docs: update changelog and header for version v1.5.11-beta2 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff42847..d86000e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 83dec4c87680617dc0c396d906236d251a5800a1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:55:24 +0200 Subject: [PATCH 188/366] feat: add logging for spoolman status in checkSpoolmanInstance function --- src/api.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api.cpp b/src/api.cpp index 2a9cb1d..2adcec1 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -685,6 +685,8 @@ bool checkSpoolmanInstance() { if (!error && doc["status"].is()) { const char* status = doc["status"]; http.end(); + Serial.print("Spoolman status: "); + Serial.println(status); if (!checkSpoolmanExtraFields()) { Serial.println("Fehler beim Überprüfen der Extrafelder."); From c48003e1b2f8738a06df09b182e78bc14d00b0cb Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:55:30 +0200 Subject: [PATCH 189/366] docs: update platformio.ini for beta version v1.5.11-beta3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 85e33ee..8186f55 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.11-beta2" +version = "1.5.11-beta3" to_old_version = "1.5.0" ## From 771b0a48392ad7c3d44e8aacfc1805ea77da5fd0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 10:55:30 +0200 Subject: [PATCH 190/366] docs: update changelog and header for version v1.5.11-beta3 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d86000e..df77aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 33ea062773549b8a7bd4b7105e05c467e8ae00f0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:04:06 +0200 Subject: [PATCH 191/366] refactor: remove debug logging from checkSpoolmanInstance function --- src/api.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 2adcec1..c5e6c8c 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -685,8 +685,6 @@ bool checkSpoolmanInstance() { if (!error && doc["status"].is()) { const char* status = doc["status"]; http.end(); - Serial.print("Spoolman status: "); - Serial.println(status); if (!checkSpoolmanExtraFields()) { Serial.println("Fehler beim Überprüfen der Extrafelder."); @@ -702,8 +700,6 @@ bool checkSpoolmanInstance() { oledShowTopRow(); spoolmanConnected = true; returnValue = strcmp(status, "healthy") == 0; - Serial.print("Spoolman instance is healthy: "); - Serial.println(returnValue); }else{ spoolmanConnected = false; } @@ -717,7 +713,6 @@ bool checkSpoolmanInstance() { Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode)); } http.end(); - returnValue = false; spoolmanApiState = API_IDLE; }else{ // If the check is skipped, return the previous status From b4584364d66427f7b7ebb325f96d35158b7b1396 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:04:17 +0200 Subject: [PATCH 192/366] docs: update platformio.ini for beta version v1.5.11-beta4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 8186f55..4927f77 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.11-beta3" +version = "1.5.11-beta4" to_old_version = "1.5.0" ## From 25233f70d5785e0ab695ab51d8962754a7f33ded Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:04:17 +0200 Subject: [PATCH 193/366] docs: update changelog and header for version v1.5.11-beta4 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df77aec..894f6ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From d776956c5eaf6cc064afeaacdf4684f7d6411d84 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:10:10 +0200 Subject: [PATCH 194/366] style: add numbering to update sections in upgrade.html refactor: improve readability of checkSpoolmanInstance function --- html/upgrade.html | 4 ++-- src/api.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) 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/src/api.cpp b/src/api.cpp index c5e6c8c..c3ab4c7 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -714,7 +714,9 @@ bool checkSpoolmanInstance() { } http.end(); spoolmanApiState = API_IDLE; - }else{ + } + else + { // If the check is skipped, return the previous status Serial.println("Skipping spoolman healthcheck, API is active."); returnValue = spoolmanConnected; From 4e58407af8beff3d0f1da6c8eb40f73331a2373e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:12:25 +0200 Subject: [PATCH 195/366] refactor: clean up library dependencies in platformio.ini --- platformio.ini | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 4927f77..85ae95e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 From 2ac8effe04130f8d933c14ed8e5360ea024592ee Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:16:10 +0200 Subject: [PATCH 196/366] docs: update platformio.ini for version v1.5.12 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 85ae95e..3fee01c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.11-beta4" +version = "1.5.12" to_old_version = "1.5.0" ## From 48556b9519b1da2cf9aaceff380f7fecb9443071 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 11:16:10 +0200 Subject: [PATCH 197/366] docs: update changelog and header for version v1.5.12 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 894f6ae..1a38bfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [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 From 1f01af4da9363494de32527b4bdaaf437148c3d7 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 15:17:42 +0200 Subject: [PATCH 198/366] feat: implement filament and spool creation in Spoolman API --- src/api.cpp | 396 ++++++++++++++++++++++++++++++++++-------------- src/api.h | 15 +- src/bambu.cpp | 4 + src/nfc.cpp | 42 ++--- src/website.cpp | 10 +- 5 files changed, 323 insertions(+), 144 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8268efb..f6db794 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -5,8 +5,21 @@ #include #include "debug.h" #include "scale.h" - +#include volatile spoolmanApiStateType spoolmanApiState = API_IDLE; + +// Returns current date and time in ISO8601 format +String getCurrentDateISO8601() { + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) { + Serial.println("Failed to obtain time"); + return "1970-01-01T00:00:00Z"; + } + char timeStringBuff[25]; + strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%SZ", &timeinfo); + return String(timeStringBuff); +} + //bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; @@ -17,6 +30,8 @@ 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 bool spoolmanConnected = false; bool spoolmanExtraFieldsChecked = false; TaskHandle_t* apiTask; @@ -199,6 +214,20 @@ void sendToApi(void *parameter) { 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(); @@ -221,6 +250,20 @@ void sendToApi(void *parameter) { 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; @@ -294,6 +337,12 @@ void sendToApi(void *parameter) { case API_REQUEST_VENDOR_CREATE: oledShowProgressBar(1, 1, "Failure!", "Vendor create"); break; + case API_REQUEST_FILAMENT_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Filament create"); + break; + case API_REQUEST_SPOOL_CREATE: + oledShowProgressBar(1, 1, "Failure!", "Spool create"); + break; } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); @@ -563,67 +612,7 @@ bool updateSpoolBambuData(String payload) { return true; } -// #### Filament Fabrik -uint16_t checkVendor(String vendor) { - // Check if vendor exists using task system - foundVendorId = 0; // Reset previous value - - String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendor; - 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 - if(spoolmanApiState == API_IDLE){ - // 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) - ); - } else { - Serial.println("Not spawning new task, API still active!"); - delete params; - return 0; - } - - // Wait for task completion - while(spoolmanApiState != API_IDLE) { - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - // Check if vendor was found - if (foundVendorId == 0) { - Serial.println("Vendor not found, creating new vendor..."); - uint16_t vendorId = createVendor(vendor); - 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)); - checkFilament(vendorId); - return vendorId; - } - } else { - Serial.println("Vendor found: " + vendor); - Serial.print("Vendor ID: "); - Serial.println(foundVendorId); - return foundVendorId; - } -} - +// #### Brand Filament uint16_t createVendor(String vendor) { // Create new vendor in Spoolman database using task system // Note: Due to async nature, the ID will be stored in createdVendorId global variable @@ -685,11 +674,148 @@ uint16_t createVendor(String vendor) { return createdVendorId; } -uint16_t checkFilament(uint16_t vendorId) { +uint16_t checkVendor(String vendor) { + // Check if vendor exists using task system + foundVendorId = 0; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendor; + 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 + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + delete params; + return 0; + } + + // Wait for task completion + while(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // Check if vendor was found + if (foundVendorId == 0) { + Serial.println("Vendor not found, creating new vendor..."); + uint16_t vendorId = createVendor(vendor); + 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: " + vendor); + Serial.print("Vendor ID: "); + Serial.println(foundVendorId); + return foundVendorId; + } +} + +uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { + // Create new filament in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdFilamentId global variable + createdFilamentId = 0; // 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["name"].as(); + filamentDoc["vendor_id"] = String(vendorId); + filamentDoc["material"] = payload["type"].as(); + filamentDoc["density"] = (payload["density"].is() && payload["density"].as().length() > 0) ? payload["density"].as() : "1.24"; + filamentDoc["diameter"] = (payload["diameter"].is() && payload["diameter"].as().length() > 0) ? payload["diameter"].as() : "1.75"; + filamentDoc["weight"] = payload["weight"].as(); + filamentDoc["spool_weight"] = payload["spool_weight"].as(); + filamentDoc["article_number"] = payload["artnr"].as(); + filamentDoc["comment"] = String("automatically generated"); + filamentDoc["extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; + filamentDoc["bed_temp"] = payload["bed_temp"].is() ? payload["bed_temp"].as() : ""; + filamentDoc["external_id"] = payload["artnr"].as(); + + if (payload["multi_color_hexes"].is()) { + filamentDoc["multi_color_hexes"] = payload["multi_color_hexes"].as(); + filamentDoc["multi_color_direction"] = payload["multi_color_direction"].is() ? payload["multi_color_direction"].as() : ""; + } + else + { + filamentDoc["color_hex"] = (payload["color"].is() && payload["color"].as().length() >= 6) ? payload["color"].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; + + // Check if API is idle before creating task + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + delete params; + filamentDoc.clear(); + return 0; + } + + filamentDoc.clear(); + + // Wait for task completion and return the created filament ID + // Note: createdFilamentId will be set by sendToApi when response is received + while(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + return createdFilamentId; +} + +uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { // Check if filament exists using task system foundFilamentId = 0; // Reset previous value - - String spoolsUrl = spoolmanUrl + apiUrl + "/filament?vendor.id=" + String(vendorId); + + String spoolsUrl = spoolmanUrl + apiUrl + "/filament?vendor.id=" + String(vendorId) + "&external_id=" + String(payload["artnr"].as()); Serial.print("Check filament with URL: "); Serial.println(spoolsUrl); @@ -728,13 +854,12 @@ uint16_t checkFilament(uint16_t vendorId) { // Check if filament was found if (foundFilamentId == 0) { Serial.println("Filament not found, creating new filament..."); - uint16_t filamentId = createFilament(); + 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)); - checkSpool(); return filamentId; } } else { @@ -745,54 +870,101 @@ uint16_t checkFilament(uint16_t vendorId) { } } -bool createFilament() { - // { - // "name": "PolyTerra Charcoal Black", - // "vendor_id": 0, - // "material": "PLA", - // "price": 20, - // "density": 1.24, - // "diameter": 1.75, - // "weight": 1000, - // "spool_weight": 140, - // "article_number": "PM70820", - // "comment": "automatically generated", - // "settings_extruder_temp": 210, - // "settings_bed_temp": 60, - // "color_hex": "FF0000", - // "multi_color_hexes": "FF0000,00FF00,0000FF", - // "multi_color_direction": "coaxial", - // "external_id": "polymaker_pla_polysonicblack_1000_175", - // "extra": { - // "nozzle_temperature": "string" - // } - // } +uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& payload, String uidString) { + // Create new spool in Spoolman database using task system + // Note: Due to async nature, the ID will be stored in createdSpoolId global variable + createdSpoolId = 0; // Reset previous value + + String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; + Serial.print("Create spool with URL: "); + Serial.println(spoolsUrl); + String currentDate = getCurrentDateISO8601(); + // Create JSON payload for spool creation + JsonDocument spoolDoc; + spoolDoc["first_used"] = String(currentDate); + spoolDoc["last_used"] = String(currentDate); + spoolDoc["filament_id"] = String(filamentId); + spoolDoc["initial_weight"] = weight > 10 ? String(weight) : "1000"; + spoolDoc["spool_weight"] = (payload["spool_weight"].is() && payload["spool_weight"].as().length() > 0) ? payload["spool_weight"].as() : "180"; + spoolDoc["remaining_weight"] = (payload["weight"].is() && payload["weight"].as().length() > 0) ? payload["weight"].as() : "1000"; + spoolDoc["used_weight"] = "0"; + spoolDoc["lot_nr"] = (payload["lotnr"].is() && payload["lotnr"].as().length() > 0) ? payload["lotnr"].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; + + // Check if API is idle before creating task + if(spoolmanApiState == API_IDLE){ + // 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) + ); + } else { + Serial.println("Not spawning new task, API still active!"); + 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(spoolmanApiState != API_IDLE) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // daten mit startWriteJsonToTag schreiben + // void startWriteJsonToTag(const bool isSpoolTag, const char* payload); + payload["sm_id"].set(String(createdSpoolId)); + + String payloadString; + serializeJson(payload, payloadString); + startWriteJsonToTag(true, payloadString.c_str()); + + return createdSpoolId; } -uint16_t checkSpool() { - -} - -bool createSpool() { - // Implement specific handling for Spool creation - // { - // "first_used": "2019-08-24T14:15:22Z", - // "last_used": "2019-08-24T14:15:22Z", - // "filament_id": 0, - // "price": 20, - // "initial_weight": 200, - // "spool_weight": 200, - // "remaining_weight": 800, - // "used_weight": 200, - // "location": "Shelf A", - // "lot_nr": "52342", - // "comment": "", - // "archived": false, - // "extra": { - // "nfc_id": "string" - // } - // } +bool createBrandFilament(JsonDocument& payload, String uidString) { + uint16_t vendorId = checkVendor(payload["brand"].as()); + 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 diff --git a/src/api.h b/src/api.h index 3e525d7..83a88c7 100644 --- a/src/api.h +++ b/src/api.h @@ -20,7 +20,9 @@ typedef enum { API_REQUEST_SPOOL_LOCATION_UPDATE, API_REQUEST_VENDOR_CREATE, API_REQUEST_VENDOR_CHECK, - API_REQUEST_FILAMENT_CHECK + API_REQUEST_FILAMENT_CHECK, + API_REQUEST_FILAMENT_CREATE, + API_REQUEST_SPOOL_CREATE } SpoolmanApiRequestType; extern volatile spoolmanApiStateType spoolmanApiState; @@ -30,9 +32,6 @@ extern bool octoEnabled; extern bool sendOctoUpdate; extern String octoUrl; extern String octoToken; -extern uint16_t createdVendorId; // ID of newly created vendor -extern uint16_t foundVendorId; // ID of found vendor -extern uint16_t foundFilamentId; // ID of found filament extern bool spoolmanConnected; bool checkSpoolmanInstance(); @@ -46,12 +45,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 -uint16_t checkVendor(String vendor); // Check if vendor exists, return ID -uint16_t createVendor(String vendor); // Create vendor, return ID -uint16_t checkFilament(); // Check if filament exists, return ID -bool createFilament(); // Create filament -uint16_t checkSpool(); // Check if spool exists, return ID -bool createSpool(); // Create spool -void createFilamentFabrik(JsonDocument payload); +bool createBrandFilament(JsonDocument& payload, String uidString); #endif diff --git a/src/bambu.cpp b/src/bambu.cpp index 21fc6fa..8eae33d 100644 --- a/src/bambu.cpp +++ b/src/bambu.cpp @@ -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/nfc.cpp b/src/nfc.cpp index f85b5c4..6d0d832 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -39,12 +39,6 @@ volatile nfcReaderStateType nfcReaderState = NFC_IDLE; // 6 = reading // ***** PN532 - -// ##### Recycling Fabrik ##### -bool isRecyclingFabrik(const char* brand) { - return strcmp(brand, "Recycling Fabrik") == 0; -} - // ##### Funktionen für RFID ##### void payloadToJson(uint8_t *data) { const char* startJson = strchr((char*)data, '{'); @@ -66,12 +60,6 @@ void payloadToJson(uint8_t *data) { int max_temp = doc["max_temp"]; const char* brand = doc["brand"]; - // Recycling Fabrik - if (isRecyclingFabrik(brand)) { - // TODO: Implement specific handling for Recycling Fabrik - Serial.println("Recycling Fabrik erkannt."); - } - Serial.println(); Serial.println("-----------------"); Serial.println("JSON-Parsed Data:"); @@ -215,7 +203,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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]; @@ -266,12 +254,15 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) { oledShowProgressBar(1, 1, "Failure", "Scan spool first"); } } - // Recycling Fabrik - else if (isRecyclingFabrik(doc["type"].as().c_str())) { - // If no sm_id is present but the brand is Recycling Fabrik then + // Brand Filament not registered to Spoolman + else if ((!doc["sm_id"].is() || (doc["sm_id"].is() && (doc["sm_id"] == "0" || doc["sm_id"] == ""))) + && doc["brand"].is() && doc["artnr"].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("Recycling Fabrik Tag found!"); - createFilamentFabrik(doc); + Serial.println("New Brand Filament Tag found!"); + createBrandFilament(doc, uidString); } else { @@ -393,6 +384,9 @@ void writeJsonToTag(void *parameter) { nfcReadingTaskSuspendRequest = false; pauseBambuMqttTask = false; + free(params->payload); + delete params; + vTaskDelete(NULL); } @@ -450,6 +444,16 @@ void scanRfidTask(void * parameter) { oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); //vTaskDelay(500 / portTICK_PERIOD_MS); + + // 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) { @@ -480,7 +484,7 @@ void scanRfidTask(void * parameter) { vTaskDelay(pdMS_TO_TICKS(1)); } - if (!decodeNdefAndReturnJson(data)) + if (!decodeNdefAndReturnJson(data, uidString)) { oledShowProgressBar(1, 1, "Failure", "Unknown tag"); nfcReaderState = NFC_READ_ERROR; diff --git a/src/website.cpp b/src/website.cpp index 7c40fc7..50d47f7 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 From ece510099ef9ee9efc7f0f80d8b2b808375bf081 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 15:18:54 +0200 Subject: [PATCH 199/366] docs: update platformio.ini for beta version v1.5.12-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3fee01c..2ddc271 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12" +version = "1.5.12-beta1" to_old_version = "1.5.0" ## From 6e94092a74e0a58ac00aa37645eb632085e966fc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 28 Aug 2025 15:18:54 +0200 Subject: [PATCH 200/366] docs: update changelog and header for version v1.5.12-beta1 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a38bfc..4a15907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [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 From f450d1efdf396de6e6fe8b93d264ebc198ad9ac2 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:23:40 +0200 Subject: [PATCH 201/366] fix: enhance filament creation logic to include dynamic comments based on payload --- src/api.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index f6db794..156ba3a 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -752,10 +752,18 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { filamentDoc["weight"] = payload["weight"].as(); filamentDoc["spool_weight"] = payload["spool_weight"].as(); filamentDoc["article_number"] = payload["artnr"].as(); - filamentDoc["comment"] = String("automatically generated"); filamentDoc["extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; filamentDoc["bed_temp"] = payload["bed_temp"].is() ? payload["bed_temp"].as() : ""; - filamentDoc["external_id"] = payload["artnr"].as(); + + if (payload["artnr"].is()) + { + filamentDoc["external_id"] = payload["artnr"].as(); + filamentDoc["comment"] = payload["url"].is() ? payload["url"].as() + payload["artnr"].as() : "automatically generated"; + } + else + { + filamentDoc["comment"] = payload["url"].is() ? payload["url"].as() : "automatically generated"; + } if (payload["multi_color_hexes"].is()) { filamentDoc["multi_color_hexes"] = payload["multi_color_hexes"].as(); From bc41205f15d8263c7c3542f1aedeaca09af03930 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:23:49 +0200 Subject: [PATCH 202/366] docs: update platformio.ini for beta version v1.5.12-beta2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2ddc271..347d448 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta1" +version = "1.5.12-beta2" to_old_version = "1.5.0" ## From 3dd4b827108fd43c90f55d13460b5ba9379623a6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:23:49 +0200 Subject: [PATCH 203/366] docs: update changelog and header for version v1.5.12-beta2 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a15907..4328daf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 6bed3b086c0a4788c91c5f14564259aa5d59914f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:54:53 +0200 Subject: [PATCH 204/366] feat: add logging for decoded JSON data in NFC processing --- src/nfc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nfc.cpp b/src/nfc.cpp index 6d0d832..e595198 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -216,6 +216,9 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { nfcJsonData += (char)encodedMessage[3 + typeLength + i]; } + Serial.println("Decoded JSON Data:"); + Serial.println(nfcJsonData); + // JSON-Dokument verarbeiten JsonDocument doc; DeserializationError error = deserializeJson(doc, nfcJsonData); From d195f76d5e333761c75db2422097e7d0780e0414 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:54:59 +0200 Subject: [PATCH 205/366] docs: update platformio.ini for beta version v1.5.12-beta3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 347d448..cf52f29 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta2" +version = "1.5.12-beta3" to_old_version = "1.5.0" ## From cc8f1cfd7b824cce5d5a31dd77ae100d550445a1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 08:54:59 +0200 Subject: [PATCH 206/366] docs: update changelog and header for version v1.5.12-beta3 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4328daf..69de0e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From a2816da6545575818fc7d8275818a0e31b356f73 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:06:37 +0200 Subject: [PATCH 207/366] feat: enhance NDEF decoding to validate structure and extract JSON payload --- src/nfc.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index e595198..42057e4 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -206,14 +206,58 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { oledShowProgressBar(1, octoEnabled?5:4, "Reading", "Decoding data"); - byte typeLength = encodedMessage[3]; - byte payloadLength = encodedMessage[4]; + // Check for NDEF TLV (Type-Length-Value) structure + if (encodedMessage[0] != 0x03) { + Serial.println("Not a valid NDEF message (missing TLV tag 0x03)"); + return false; + } + + // Get the total NDEF message length from TLV + byte ndefMessageLength = encodedMessage[1]; + + // Skip TLV header (2 bytes) to get to NDEF record + const byte* ndefRecord = &encodedMessage[2]; + + // Parse NDEF record header + byte recordHeader = ndefRecord[0]; + byte typeLength = ndefRecord[1]; + + // Determine payload length (can be 1 or 4 bytes depending on SR flag) + uint32_t payloadLength = 0; + byte payloadLengthBytes = 1; + + // Check if Short Record (SR) flag is set + if (recordHeader & 0x10) { // SR flag + payloadLength = ndefRecord[2]; + payloadLengthBytes = 1; + } else { + // Long record format (4 bytes for payload length) + payloadLength = (ndefRecord[2] << 24) | (ndefRecord[3] << 16) | + (ndefRecord[4] << 8) | ndefRecord[5]; + payloadLengthBytes = 4; + } + + Serial.print("NDEF Record Header: 0x"); + Serial.println(recordHeader, HEX); + Serial.print("Type Length: "); + Serial.println(typeLength); + Serial.print("Payload Length: "); + Serial.println(payloadLength); + + // Calculate offset to payload + byte payloadOffset = 2 + payloadLengthBytes + typeLength; + + // Verify we have enough data + if (payloadOffset + payloadLength > ndefMessageLength + 2) { + Serial.println("Invalid NDEF structure - payload extends beyond message"); + return false; + } nfcJsonData = ""; - for (int i = 2; i < payloadLength+2; i++) - { - nfcJsonData += (char)encodedMessage[3 + typeLength + i]; + // Extract JSON payload + for (uint32_t i = 0; i < payloadLength; i++) { + nfcJsonData += (char)ndefRecord[payloadOffset + i]; } Serial.println("Decoded JSON Data:"); From 686eb22232d0e6da3e81ca64bd63afb306a5bb70 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:06:44 +0200 Subject: [PATCH 208/366] docs: update platformio.ini for beta version v1.5.12-beta4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index cf52f29..1273846 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta3" +version = "1.5.12-beta4" to_old_version = "1.5.0" ## From d8978170200deb5728a977726630e48dbe89d150 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:06:44 +0200 Subject: [PATCH 209/366] docs: update changelog and header for version v1.5.12-beta4 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69de0e4..1289ad3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From f1cdd3f41dbd1bd5aad94e8d888454a7d5698237 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:46:08 +0200 Subject: [PATCH 210/366] feat: enhance NDEF decoding with detailed validation and debugging output --- src/nfc.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 135 insertions(+), 16 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 42057e4..c942998 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -206,62 +206,169 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { oledShowProgressBar(1, octoEnabled?5:4, "Reading", "Decoding data"); - // Check for NDEF TLV (Type-Length-Value) structure - if (encodedMessage[0] != 0x03) { - Serial.println("Not a valid NDEF message (missing TLV tag 0x03)"); + // 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 total NDEF message length from TLV - byte ndefMessageLength = encodedMessage[1]; + // Get the NDEF message length from TLV + uint16_t ndefMessageLength = 0; + int ndefRecordOffset = 0; - // Skip TLV header (2 bytes) to get to NDEF record - const byte* ndefRecord = &encodedMessage[2]; + 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 + // 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("NDEF Record Header: 0x"); - Serial.println(recordHeader, HEX); - Serial.print("Type Length: "); - Serial.println(typeLength); 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 = 2 + payloadLengthBytes + typeLength; + byte payloadOffset = 1 + 1 + payloadLengthBytes + typeLength + idLength; + Serial.print("Calculated payload offset: "); + Serial.println(payloadOffset); + // Verify we have enough data - if (payloadOffset + payloadLength > ndefMessageLength + 2) { + 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 = ""; - // Extract JSON payload + // Extract JSON payload with validation + uint32_t actualJsonLength = 0; for (uint32_t i = 0; i < payloadLength; i++) { - nfcJsonData += (char)ndefRecord[payloadOffset + 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.println("Decoded JSON Data:"); Serial.println(nfcJsonData); + + // Trim any trailing whitespace or invalid characters + nfcJsonData.trim(); // JSON-Dokument verarbeiten JsonDocument doc; @@ -566,6 +673,18 @@ 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 longer pause after successful reading to prevent immediate re-reading + if (nfcReaderState == NFC_READ_SUCCESS) { + Serial.println("Tag erfolgreich gelesen - warte 5 Sekunden vor nächstem Scan"); + vTaskDelay(5000 / portTICK_PERIOD_MS); // 5 second pause + } // aktualisieren der Website wenn sich der Status ändert sendNfcData(); From fbd9cb66f1aeddfc838eaebacebe4082a40f5719 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:46:14 +0200 Subject: [PATCH 211/366] docs: update platformio.ini for beta version v1.5.12-beta5 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1273846..1f42fd9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta4" +version = "1.5.12-beta5" to_old_version = "1.5.0" ## From 54275f2ac97cc130d8f966d74b84122a1f2787a4 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 09:46:14 +0200 Subject: [PATCH 212/366] docs: update changelog and header for version v1.5.12-beta5 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1289ad3..c8a0925 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 95433b4842e0b3b42de96e469c93b01294033579 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:02:48 +0200 Subject: [PATCH 213/366] refactor: improve task synchronization in vendor, filament, and spool creation functions --- src/api.cpp | 80 +++++++++++++++++++++++++-------------------------- src/scale.cpp | 4 ++- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 156ba3a..7a1bbcf 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -616,6 +616,7 @@ bool updateSpoolBambuData(String payload) { uint16_t createVendor(String 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 = 0; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/vendor"; @@ -645,19 +646,18 @@ uint16_t createVendor(String vendor) { params->spoolsUrl = spoolsUrl; params->updatePayload = vendorPayload; - // Check if API is idle before creating task - if(spoolmanApiState == API_IDLE){ - // 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) - ); - } else { - Serial.println("Not spawning new task, API still active!"); + // 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; @@ -736,6 +736,7 @@ uint16_t checkVendor(String vendor) { uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // 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 = 0; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/filament"; @@ -790,19 +791,18 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { params->spoolsUrl = spoolsUrl; params->updatePayload = filamentPayload; - // Check if API is idle before creating task - if(spoolmanApiState == API_IDLE){ - // 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) - ); - } else { - Serial.println("Not spawning new task, API still active!"); + // 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; @@ -881,6 +881,7 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& payload, String uidString) { // 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 = 0; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; @@ -918,19 +919,18 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo params->spoolsUrl = spoolsUrl; params->updatePayload = spoolPayload; - // Check if API is idle before creating task - if(spoolmanApiState == API_IDLE){ - // 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) - ); - } else { - Serial.println("Not spawning new task, API still active!"); + // 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; } @@ -941,7 +941,7 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo vTaskDelay(100 / portTICK_PERIOD_MS); } - // daten mit startWriteJsonToTag schreiben + // Write data to tag with startWriteJsonToTag // void startWriteJsonToTag(const bool isSpoolTag, const char* payload); payload["sm_id"].set(String(createdSpoolId)); diff --git a/src/scale.cpp b/src/scale.cpp index 24d8797..91b7ea3 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -48,8 +48,10 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); + vTaskDelay(pdMS_TO_TICKS(500)); scale.tare(); - + vTaskDelay(pdMS_TO_TICKS(500)); + for(;;) { if (scale.is_ready()) { From 12044b657b0ed222cdbc2d7acf358d425006915c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:02:54 +0200 Subject: [PATCH 214/366] docs: update platformio.ini for beta version v1.5.12-beta6 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1f42fd9..0401cf8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta5" +version = "1.5.12-beta6" to_old_version = "1.5.0" ## From b8b6f637f2aa897ecc46cf3bc81b964ef609818a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:02:54 +0200 Subject: [PATCH 215/366] docs: update changelog and header for version v1.5.12-beta6 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8a0925..016bf30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 965ea5da1e2bc3df60ce08bf37f71c837de769bb Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:31:26 +0200 Subject: [PATCH 216/366] fix: improve API state handling and vendor name formatting --- src/api.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 7a1bbcf..9345094 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -121,7 +121,7 @@ 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; @@ -678,7 +678,10 @@ uint16_t checkVendor(String vendor) { // Check if vendor exists using task system foundVendorId = 0; // Reset previous value - String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendor; + String vendorName = vendor; + vendorName.trim(); + vendorName.replace(" ", "+"); + String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendorName; Serial.print("Check vendor with URL: "); Serial.println(spoolsUrl); @@ -750,7 +753,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { filamentDoc["material"] = payload["type"].as(); filamentDoc["density"] = (payload["density"].is() && payload["density"].as().length() > 0) ? payload["density"].as() : "1.24"; filamentDoc["diameter"] = (payload["diameter"].is() && payload["diameter"].as().length() > 0) ? payload["diameter"].as() : "1.75"; - filamentDoc["weight"] = payload["weight"].as(); + filamentDoc["weight"] = String(weight); filamentDoc["spool_weight"] = payload["spool_weight"].as(); filamentDoc["article_number"] = payload["artnr"].as(); filamentDoc["extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; From 0a246c1fe4511d7cfb1a44baffc92f89dfef5656 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:32:31 +0200 Subject: [PATCH 217/366] docs: update platformio.ini for beta version v1.5.12-beta7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 0401cf8..b8ed722 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta6" +version = "1.5.12-beta7" to_old_version = "1.5.0" ## From b8b6893cd01bbeb4d0dc2965ced871698e7eb30a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:32:32 +0200 Subject: [PATCH 218/366] docs: update changelog and header for version v1.5.12-beta7 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 016bf30..38a5fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 96bb8f9c7c20b0fd2496a207b5dda329175c3803 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 10:58:06 +0200 Subject: [PATCH 219/366] fix: add delay to ensure proper setting of vendor and filament IDs after API state changes --- src/api.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api.cpp b/src/api.cpp index 9345094..406e0c2 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -716,6 +716,9 @@ uint16_t checkVendor(String vendor) { while(spoolmanApiState != API_IDLE) { vTaskDelay(100 / portTICK_PERIOD_MS); } + + // Additional delay to ensure foundVendorId is properly set after API state becomes IDLE + vTaskDelay(50 / portTICK_PERIOD_MS); // Check if vendor was found if (foundVendorId == 0) { @@ -748,7 +751,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // Create JSON payload for filament creation JsonDocument filamentDoc; - filamentDoc["name"] = payload["name"].as(); + filamentDoc["name"] = payload["color_name"].as(); filamentDoc["vendor_id"] = String(vendorId); filamentDoc["material"] = payload["type"].as(); filamentDoc["density"] = (payload["density"].is() && payload["density"].as().length() > 0) ? payload["density"].as() : "1.24"; @@ -861,6 +864,9 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { while(spoolmanApiState != API_IDLE) { vTaskDelay(100 / portTICK_PERIOD_MS); } + + // Additional delay to ensure foundFilamentId is properly set after API state becomes IDLE + vTaskDelay(50 / portTICK_PERIOD_MS); // Check if filament was found if (foundFilamentId == 0) { From d8af3f45e58674d86565fa8a316f07fcccc313ed Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 11:03:05 +0200 Subject: [PATCH 220/366] fix: correct color_hex key usage and comment out unused date fields in spool creation --- src/api.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 406e0c2..843e71e 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -778,7 +778,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { } else { - filamentDoc["color_hex"] = (payload["color"].is() && payload["color"].as().length() >= 6) ? payload["color"].as() : "FFFFFF"; + filamentDoc["color_hex"] = (payload["color_hex"].is() && payload["color_hex"].as().length() >= 6) ? payload["color_hex"].as() : "FFFFFF"; } String filamentPayload; @@ -900,8 +900,8 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Create JSON payload for spool creation JsonDocument spoolDoc; - spoolDoc["first_used"] = String(currentDate); - spoolDoc["last_used"] = String(currentDate); + //spoolDoc["first_used"] = String(currentDate); + //spoolDoc["last_used"] = String(currentDate); spoolDoc["filament_id"] = String(filamentId); spoolDoc["initial_weight"] = weight > 10 ? String(weight) : "1000"; spoolDoc["spool_weight"] = (payload["spool_weight"].is() && payload["spool_weight"].as().length() > 0) ? payload["spool_weight"].as() : "180"; From eb9d9e74f47ccb49895ba9a6ffd7ad556100e0cc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 11:03:11 +0200 Subject: [PATCH 221/366] docs: update platformio.ini for beta version v1.5.12-beta8 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b8ed722..1768f45 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta7" +version = "1.5.12-beta8" to_old_version = "1.5.0" ## From 40cb835e5111664f743174d5260206d6f6f7a8ea Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 11:03:11 +0200 Subject: [PATCH 222/366] docs: update changelog and header for version v1.5.12-beta8 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a5fa0..78f372d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [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 From de39892f646f7ea3282fe178ca9a5eaf1063eaf8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 12:55:51 +0200 Subject: [PATCH 223/366] fix: update vendor and filament ID handling to use NULL and add delays for stability --- src/api.cpp | 47 ++++++++++++++++++++++++++++++----------------- src/nfc.cpp | 32 ++++++++++++++++++++++++++++---- src/scale.cpp | 3 +-- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 843e71e..7584d60 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -676,7 +676,7 @@ uint16_t createVendor(String vendor) { uint16_t checkVendor(String vendor) { // Check if vendor exists using task system - foundVendorId = 0; // Reset previous value + foundVendorId = NULL; // Reset previous value String vendorName = vendor; vendorName.trim(); @@ -696,7 +696,13 @@ uint16_t checkVendor(String vendor) { params->updatePayload = ""; // Empty for GET request // Check if API is idle before creating task - if(spoolmanApiState == API_IDLE){ + while (spoolmanApiState != API_IDLE) + { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + + if(spoolmanApiState == API_IDLE) { // Erstelle die Task BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion @@ -718,7 +724,10 @@ uint16_t checkVendor(String vendor) { } // Additional delay to ensure foundVendorId is properly set after API state becomes IDLE - vTaskDelay(50 / portTICK_PERIOD_MS); + while (foundVendorId == NULL) + { + vTaskDelay(50 / portTICK_PERIOD_MS); + } // Check if vendor was found if (foundVendorId == 0) { @@ -827,7 +836,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { // Check if filament exists using task system - foundFilamentId = 0; // Reset previous value + foundFilamentId = NULL; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/filament?vendor.id=" + String(vendorId) + "&external_id=" + String(payload["artnr"].as()); Serial.print("Check filament with URL: "); @@ -844,7 +853,7 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { params->updatePayload = ""; // Empty for GET request // Check if API is idle before creating task - if(spoolmanApiState == API_IDLE){ + //if(spoolmanApiState == API_IDLE){ // Erstelle die Task BaseType_t result = xTaskCreate( sendToApi, // Task-Funktion @@ -854,11 +863,11 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { 0, // Priorität NULL // Task-Handle (nicht benötigt) ); - } else { - Serial.println("Not spawning new task, API still active!"); - delete params; - return 0; - } + //} else { + // Serial.println("Not spawning new task, API still active!"); + // delete params; + // return 0; + //} // Wait for task completion while(spoolmanApiState != API_IDLE) { @@ -866,7 +875,9 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { } // Additional delay to ensure foundFilamentId is properly set after API state becomes IDLE - vTaskDelay(50 / portTICK_PERIOD_MS); + while (foundFilamentId == NULL) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } // Check if filament was found if (foundFilamentId == 0) { @@ -891,22 +902,21 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // 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 = 0; // Reset previous value + createdSpoolId = NULL; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; Serial.print("Create spool with URL: "); Serial.println(spoolsUrl); - String currentDate = getCurrentDateISO8601(); + //String currentDate = getCurrentDateISO8601(); // Create JSON payload for spool creation JsonDocument spoolDoc; //spoolDoc["first_used"] = String(currentDate); //spoolDoc["last_used"] = String(currentDate); spoolDoc["filament_id"] = String(filamentId); - spoolDoc["initial_weight"] = weight > 10 ? String(weight) : "1000"; + spoolDoc["initial_weight"] = weight > 10 ? String(weight-payload["spool_weight"].as()) : "1000"; spoolDoc["spool_weight"] = (payload["spool_weight"].is() && payload["spool_weight"].as().length() > 0) ? payload["spool_weight"].as() : "180"; spoolDoc["remaining_weight"] = (payload["weight"].is() && payload["weight"].as().length() > 0) ? payload["weight"].as() : "1000"; - spoolDoc["used_weight"] = "0"; spoolDoc["lot_nr"] = (payload["lotnr"].is() && payload["lotnr"].as().length() > 0) ? payload["lotnr"].as() : ""; spoolDoc["comment"] = "automatically generated"; spoolDoc["extra"]["nfc_id"] = "\"" + uidString + "\""; @@ -946,8 +956,8 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Wait for task completion and return the created spool ID // Note: createdSpoolId will be set by sendToApi when response is received - while(spoolmanApiState != API_IDLE) { - vTaskDelay(100 / portTICK_PERIOD_MS); + while(createdSpoolId == NULL) { + vTaskDelay(50 / portTICK_PERIOD_MS); } // Write data to tag with startWriteJsonToTag @@ -956,6 +966,9 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo String payloadString; serializeJson(payload, payloadString); + + nfcReaderState = NFC_IDLE; + vTaskDelay(50 / portTICK_PERIOD_MS); startWriteJsonToTag(true, payloadString.c_str()); return createdSpoolId; diff --git a/src/nfc.cpp b/src/nfc.cpp index c942998..f6223f5 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -364,8 +364,20 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { Serial.print("Actual JSON length extracted: "); Serial.println(actualJsonLength); - Serial.println("Decoded JSON Data:"); + 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(); @@ -597,7 +609,9 @@ void scanRfidTask(void * parameter) { oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); - //vTaskDelay(500 / portTICK_PERIOD_MS); + // Wait 1 second after tag detection to stabilize connection + Serial.println("Tag detected, waiting 1 second for stabilization..."); + vTaskDelay(1000 / portTICK_PERIOD_MS); // create Tag UID string String uidString = ""; @@ -620,24 +634,34 @@ 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)) { break; // Stop if reading fails } + // 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)); + // Increased delay to ensure stable reading + vTaskDelay(pdMS_TO_TICKS(5)); // Increased from 1ms to 5ms } - + + Serial.println("Tag reading completed, starting NDEF decode..."); + if (!decodeNdefAndReturnJson(data, uidString)) { oledShowProgressBar(1, 1, "Failure", "Unknown tag"); diff --git a/src/scale.cpp b/src/scale.cpp index 91b7ea3..c16ff3b 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -49,8 +49,7 @@ void scale_loop(void * parameter) { Serial.println("++++++++++++++++++++++++++++++"); vTaskDelay(pdMS_TO_TICKS(500)); - scale.tare(); - vTaskDelay(pdMS_TO_TICKS(500)); + scale_tare_counter = 10; // damit beim Starten der Waage automatisch getart wird for(;;) { if (scale.is_ready()) From af7bc2370334cb164dd235080e0b2013c4c28d62 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 12:56:07 +0200 Subject: [PATCH 224/366] docs: update platformio.ini for beta version v1.5.12-beta9 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1768f45..3984669 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta8" +version = "1.5.12-beta9" to_old_version = "1.5.0" ## From d12e766cd73a4acdc9a2802c6c6f517e1d49fb45 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 12:56:07 +0200 Subject: [PATCH 225/366] docs: update changelog and header for version v1.5.12-beta9 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f372d..e24d6a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 9231a303f332c4f699168185ba8c15560bd9890a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:09:17 +0200 Subject: [PATCH 226/366] refactor: streamline task creation in checkVendor and checkFilament functions --- src/api.cpp | 60 ++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 7584d60..8b0e2f8 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -701,27 +701,15 @@ uint16_t checkVendor(String vendor) { vTaskDelay(100 / portTICK_PERIOD_MS); } - - if(spoolmanApiState == API_IDLE) { - // 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) - ); - } else { - Serial.println("Not spawning new task, API still active!"); - delete params; - return 0; - } - - // Wait for task completion - 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) + ); // Additional delay to ensure foundVendorId is properly set after API state becomes IDLE while (foundVendorId == NULL) @@ -852,27 +840,15 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { params->spoolsUrl = spoolsUrl; params->updatePayload = ""; // Empty for GET request - // Check if API is idle before creating task - //if(spoolmanApiState == API_IDLE){ - // 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) - ); - //} else { - // Serial.println("Not spawning new task, API still active!"); - // delete params; - // return 0; - //} - - // Wait for task completion - 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) + ); // Additional delay to ensure foundFilamentId is properly set after API state becomes IDLE while (foundFilamentId == NULL) { From da788616130bee7cbec0ba9cdc4cf17229014ec1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:09:25 +0200 Subject: [PATCH 227/366] docs: update platformio.ini for beta version v1.5.12-beta10 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3984669..e818fe7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta9" +version = "1.5.12-beta10" to_old_version = "1.5.0" ## From 08abd1a37fa9d4007ccdbbbeddc223f76849ad38 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:09:26 +0200 Subject: [PATCH 228/366] docs: update changelog and header for version v1.5.12-beta10 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e24d6a9..14356b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 721dac1ead26fcb27107f2e2755bedd198235fc6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:19:17 +0200 Subject: [PATCH 229/366] fix: update spoolman ID reset values to 65535 for better API response detection --- src/api.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8b0e2f8..40f97c6 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -5,6 +5,7 @@ #include #include "debug.h" #include "scale.h" +#include "nfc.h" #include volatile spoolmanApiStateType spoolmanApiState = API_IDLE; @@ -151,7 +152,7 @@ void sendToApi(void *parameter) { else httpCode = http.PUT(updatePayload); if (httpCode == HTTP_CODE_OK) { - Serial.println("Spoolman erfolgreich aktualisiert"); + Serial.println("Spoolman Abfrage erfolgreich"); // Restgewicht der Spule auslesen String payload = http.getString(); @@ -676,7 +677,7 @@ uint16_t createVendor(String vendor) { uint16_t checkVendor(String vendor) { // Check if vendor exists using task system - foundVendorId = NULL; // Reset previous value + foundVendorId = 65535; // Reset to invalid value to detect when API response is received String vendorName = vendor; vendorName.trim(); @@ -711,8 +712,8 @@ uint16_t checkVendor(String vendor) { NULL // Task-Handle (nicht benötigt) ); - // Additional delay to ensure foundVendorId is properly set after API state becomes IDLE - while (foundVendorId == NULL) + // Wait until foundVendorId is updated by the API response (not 65535 anymore) + while (foundVendorId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); } @@ -824,7 +825,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { // Check if filament exists using task system - foundFilamentId = NULL; // Reset previous value + 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: "); @@ -850,8 +851,8 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { NULL // Task-Handle (nicht benötigt) ); - // Additional delay to ensure foundFilamentId is properly set after API state becomes IDLE - while (foundFilamentId == NULL) { + // Wait until foundFilamentId is updated by the API response (not 65535 anymore) + while (foundFilamentId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); } @@ -878,7 +879,7 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // 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 = NULL; // Reset previous value + createdSpoolId = 65535; // Reset to invalid value to detect when API response is received String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; Serial.print("Create spool with URL: "); @@ -932,7 +933,7 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Wait for task completion and return the created spool ID // Note: createdSpoolId will be set by sendToApi when response is received - while(createdSpoolId == NULL) { + while(createdSpoolId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); } From 0f19dc4f46c64f1cd62cf914d4aaa0574fa097b0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:19:21 +0200 Subject: [PATCH 230/366] docs: update platformio.ini for beta version v1.5.12-beta11 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e818fe7..17cac60 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta10" +version = "1.5.12-beta11" to_old_version = "1.5.0" ## From 2587227e78c05d978910fa72e7433aa490ef618f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:19:22 +0200 Subject: [PATCH 231/366] docs: update changelog and header for version v1.5.12-beta11 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14356b4..53522f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 046f770a525c3e2a848aa1924c7f08c9bd050dfb Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:29:07 +0200 Subject: [PATCH 232/366] fix: update createdVendorId reset value to 65535 for improved API handling --- src/api.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 40f97c6..e9ec60f 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -618,7 +618,7 @@ uint16_t createVendor(String 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 = 0; // Reset previous value + createdVendorId = 65535; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/vendor"; Serial.print("Create vendor with URL: "); @@ -668,8 +668,8 @@ uint16_t createVendor(String vendor) { // Wait for task completion and return the created vendor ID // Note: createdVendorId will be set by sendToApi when response is received - while(spoolmanApiState != API_IDLE) { - vTaskDelay(100 / portTICK_PERIOD_MS); + while(createdVendorId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); } return createdVendorId; From 26e905050dd9d3f249583731d645b7d245725774 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 13:40:29 +0200 Subject: [PATCH 233/366] fix: update createdFilamentId reset value to 65535 for better task handling --- src/api.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index e9ec60f..8ca7e02 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -741,7 +741,7 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // 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 = 0; // Reset previous value + createdFilamentId = 65535; // Reset previous value String spoolsUrl = spoolmanUrl + apiUrl + "/filament"; Serial.print("Create filament with URL: "); @@ -757,8 +757,8 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { filamentDoc["weight"] = String(weight); filamentDoc["spool_weight"] = payload["spool_weight"].as(); filamentDoc["article_number"] = payload["artnr"].as(); - filamentDoc["extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; - filamentDoc["bed_temp"] = payload["bed_temp"].is() ? payload["bed_temp"].as() : ""; + filamentDoc["settings_extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; + filamentDoc["settings_bed_temp"] = payload["bed_temp"].is() ? payload["bed_temp"].as() : ""; if (payload["artnr"].is()) { @@ -816,8 +816,8 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // Wait for task completion and return the created filament ID // Note: createdFilamentId will be set by sendToApi when response is received - while(spoolmanApiState != API_IDLE) { - vTaskDelay(100 / portTICK_PERIOD_MS); + while(createdFilamentId == 65535) { + vTaskDelay(50 / portTICK_PERIOD_MS); } return createdFilamentId; From bff6e722199c65f50fa8b018b1e405f08ef37025 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:10:49 +0200 Subject: [PATCH 234/366] fix: reset NFC state on API send failure to allow retry --- src/api.cpp | 3 +- src/nfc.cpp | 433 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 374 insertions(+), 62 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8ca7e02..597cbfd 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -346,9 +346,8 @@ void sendToApi(void *parameter) { 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(); diff --git a/src/nfc.cpp b/src/nfc.cpp index f6223f5..28124d4 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -99,9 +99,7 @@ bool formatNdefTag() { } return success; - } - -uint16_t readTagSize() +}uint16_t readTagSize() { uint8_t buffer[4]; memset(buffer, 0, 4); @@ -109,97 +107,412 @@ uint16_t readTagSize() return buffer[2]*8; } +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 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(); +} + +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; +} + 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("========================"); 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"); + + // IMPORTANT: Use safe NDEF initialization instead of aggressive clearing + Serial.println("Schritt 1: Sichere NDEF-Initialisierung..."); + if (!initializeNdefStructure()) { + Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); + oledShowMessage("NDEF init failed"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + return 0; + } + Serial.println("✓ NDEF-Struktur sicher initialisiert"); + + // 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("Schritt 2: 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) { + // 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); - - if (!(nfc.ntag2xx_WritePage(4+i, pageBuffer))) - { - Serial.println("Fehler beim Schreiben der Seite."); - free(combinedData); + // Write page to tag + if (!nfc.ntag2xx_WritePage(pageNumber, pageBuffer)) { + Serial.print("FEHLER beim Schreiben der Seite "); + Serial.println(pageNumber); + Serial.print("Möglicherweise Page-Limit erreicht für "); + Serial.println(tagType); + free(tlvData); return 0; } - yield(); - //esp_task_wdt_reset(); + 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(); - i++; - a += 4; - totalSize -= bytesToWrite; + bytesWritten += bytesToWrite; + pageNumber++; + + yield(); + vTaskDelay(5 / portTICK_PERIOD_MS); // Small 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"); + Serial.println(); + return 1; } From 257f4df80011932ec91f5deb26a9d4abdab11d4b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:10:56 +0200 Subject: [PATCH 235/366] docs: update platformio.ini for beta version v1.5.12-beta12 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 17cac60..0686d1c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta11" +version = "1.5.12-beta12" to_old_version = "1.5.0" ## From 02febfa943b79a0c144976bb1d6361dd1f6f061e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:10:56 +0200 Subject: [PATCH 236/366] docs: update changelog and header for version v1.5.12-beta12 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53522f6..5cb4194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [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 From 47bdf022ece0c4d35b840ae7ed912329c6462247 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:17:10 +0200 Subject: [PATCH 237/366] refactor: reorganize clearUserDataArea function for improved clarity and safety --- src/nfc.cpp | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 28124d4..3e2b90a 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -223,38 +223,6 @@ uint16_t getMaxUserDataPages() return maxPages; } -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(); -} - bool initializeNdefStructure() { // Write minimal NDEF structure without destroying the tag // This creates a clean slate while preserving tag functionality @@ -300,6 +268,38 @@ bool initializeNdefStructure() { 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(); From 382caeacedf35a3ab0272c40e11dfb749de4fb30 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:17:15 +0200 Subject: [PATCH 238/366] docs: update platformio.ini for beta version v1.5.12-beta13 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 0686d1c..71d9ea6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta12" +version = "1.5.12-beta13" to_old_version = "1.5.0" ## From 69bf5f90faac2125f5de7f52761cfbc5b27485f5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 14:17:15 +0200 Subject: [PATCH 239/366] docs: update changelog and header for version v1.5.12-beta13 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cb4194..e311266 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 1f880fc8f1338fe1828d9c0d9603d275df09d119 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 15:33:06 +0200 Subject: [PATCH 240/366] refactor: optimize JSON payload structure and enhance NFC tag validation process --- src/api.cpp | 19 ++- src/nfc.cpp | 408 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/nfc.h | 1 + 3 files changed, 416 insertions(+), 12 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 597cbfd..8391ff8 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -938,10 +938,25 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Write data to tag with startWriteJsonToTag // void startWriteJsonToTag(const bool isSpoolTag, const char* payload); - payload["sm_id"].set(String(createdSpoolId)); + + // 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 + + // Copy all other fields from original payload (excluding sm_id if it exists) + for (JsonPair kv : payload.as()) { + if (strcmp(kv.key().c_str(), "sm_id") != 0) { // Skip sm_id to avoid duplication + optimizedPayload[kv.key()] = kv.value(); + } + } String payloadString; - serializeJson(payload, payloadString); + serializeJson(optimizedPayload, payloadString); + + Serial.println("Optimized JSON with sm_id first:"); + Serial.println(payloadString); + + optimizedPayload.clear(); nfcReaderState = NFC_IDLE; vTaskDelay(50 / portTICK_PERIOD_MS); diff --git a/src/nfc.cpp b/src/nfc.cpp index 3e2b90a..e9d0844 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -314,6 +314,39 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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 + uint16_t actualMaxPage = maxWritablePage; + for (uint16_t testPage = maxWritablePage; testPage >= 4; testPage--) { + if (nfc.ntag2xx_ReadPage(testPage, testBuffer)) { + actualMaxPage = testPage; + Serial.print("Found actual max readable page: "); + Serial.println(actualMaxPage); + break; + } + } + 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..."); @@ -375,15 +408,110 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println("✓ Payload passt in den Tag - Schreibvorgang wird fortgesetzt"); - // IMPORTANT: Use safe NDEF initialization instead of aggressive clearing - Serial.println("Schritt 1: Sichere NDEF-Initialisierung..."); + // STEP 1: Read current tag content for debugging + Serial.println(); + Serial.println("=== SCHRITT 1: AKTUELLER TAG-INHALT ==="); + uint8_t currentContent[64]; // Read first 16 pages + memset(currentContent, 0, 64); + + for (uint8_t page = 4; page < 20; page++) { + uint8_t pageData[4]; + if (nfc.ntag2xx_ReadPage(page, pageData)) { + memcpy(¤tContent[(page-4)*4], pageData, 4); + Serial.print("Seite "); + Serial.print(page); + Serial.print(": "); + for (int i = 0; i < 4; i++) { + if (pageData[i] < 0x10) Serial.print("0"); + Serial.print(pageData[i], HEX); + Serial.print(" "); + } + Serial.println(); + } else { + Serial.print("Fehler beim Lesen von Seite "); + Serial.println(page); + } + } + Serial.println("========================================="); + + // STEP 2: Simple write test - write one test page + Serial.println(); + Serial.println("=== SCHRITT 2: SCHREIBTEST ==="); + uint8_t testPage[4] = {0xAA, 0xBB, 0xCC, 0xDD}; // Test pattern + + if (!nfc.ntag2xx_WritePage(10, testPage)) { // Use page 10 for test + Serial.println("FEHLER: Einfacher Schreibtest fehlgeschlagen!"); + Serial.println("Tag ist möglicherweise schreibgeschützt oder defekt"); + oledShowMessage("Tag write protected?"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + // Verify test write + uint8_t readBack[4]; + if (!nfc.ntag2xx_ReadPage(10, readBack)) { + Serial.println("FEHLER: Kann Testdaten nicht zurücklesen!"); + 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; + } + + Serial.println("✓ Schreibtest erfolgreich - Tag ist beschreibbar"); + Serial.println("================================"); + + // STEP 3: NDEF initialization with verification + Serial.println(); + Serial.println("=== SCHRITT 3: NDEF-INITIALISIERUNG ==="); if (!initializeNdefStructure()) { Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); oledShowMessage("NDEF init failed"); vTaskDelay(2000 / portTICK_PERIOD_MS); return 0; } - Serial.println("✓ NDEF-Struktur sicher initialisiert"); + + // 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("=========================================="); // Allocate memory for the complete TLV structure uint8_t* tlvData = (uint8_t*) malloc(totalTlvSize); @@ -444,7 +572,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { uint8_t pageNumber = 4; uint16_t totalBytes = offset + 1; - Serial.println("Schritt 2: Schreibe neue NDEF-Daten..."); + Serial.println(); + Serial.println("=== SCHRITT 4: SCHREIBE NEUE NDEF-DATEN ==="); Serial.print("Schreibe "); Serial.print(totalBytes); Serial.print(" Bytes in "); @@ -452,6 +581,13 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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); @@ -467,6 +603,53 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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; + } + + // IMMEDIATE verification after each write - this is critical! + Serial.print("Verifiziere Seite "); + Serial.print(pageNumber); + Serial.print("... "); + + uint8_t verifyBuffer[4]; + vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay before verification + + if (nfc.ntag2xx_ReadPage(pageNumber, verifyBuffer)) { + bool writeSuccess = true; + for (int i = 0; i < bytesToWrite; i++) { + if (verifyBuffer[i] != pageBuffer[i]) { + writeSuccess = 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 (!writeSuccess) { + Serial.println("❌ SCHREIBVORGANG FEHLGESCHLAGEN!"); + free(tlvData); + return 0; + } else { + Serial.println("✓"); + } + } else { + Serial.println("❌ Kann Seite nicht zur Verifikation lesen!"); free(tlvData); return 0; } @@ -511,7 +694,129 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.print((bytesWritten * 100) / availableUserData); Serial.println("%"); Serial.println("✓ Bestehende Daten wurden überschrieben"); + + // CRITICAL: Verify the write by reading back the data Serial.println(); + Serial.println("=== WRITE VERIFICATION ==="); + + // Wait a moment for tag to stabilize + vTaskDelay(100 / portTICK_PERIOD_MS); + + // Read back the written data to verify + uint8_t verifyBuffer[totalBytes]; + memset(verifyBuffer, 0, totalBytes); + + bool verificationSuccess = true; + uint8_t verifyPage = 4; + uint16_t verifyBytesRead = 0; + + while (verifyBytesRead < totalBytes && verifyPage <= maxWritablePage) { + uint8_t pageData[4]; + if (!nfc.ntag2xx_ReadPage(verifyPage, pageData)) { + Serial.print("VERIFICATION FAILED: Cannot read page "); + Serial.println(verifyPage); + verificationSuccess = false; + break; + } + + // Copy page data to verify buffer + uint16_t bytesToCopy = min(4, (int)(totalBytes - verifyBytesRead)); + memcpy(&verifyBuffer[verifyBytesRead], pageData, bytesToCopy); + + verifyBytesRead += bytesToCopy; + verifyPage++; + } + + if (verificationSuccess && verifyBytesRead >= totalBytes) { + // Compare written data with read data + bool dataMatches = true; + for (uint16_t i = 0; i < totalBytes; i++) { + if (verifyBuffer[i] != tlvData[i]) { + Serial.print("VERIFICATION FAILED: Data mismatch at byte "); + Serial.print(i); + Serial.print(" - Expected: 0x"); + Serial.print(tlvData[i], HEX); + Serial.print(", Read: 0x"); + Serial.println(verifyBuffer[i], HEX); + dataMatches = false; + break; + } + } + + if (dataMatches) { + Serial.println("✓ WRITE VERIFICATION SUCCESSFUL!"); + Serial.println("✓ All written data verified correctly"); + + // Additional JSON verification - try to parse the written JSON + Serial.println("=== JSON VERIFICATION ==="); + + // Find and extract JSON from verified data + // Look for the JSON payload within the NDEF structure + bool jsonFound = false; + for (uint16_t i = 0; i < totalBytes - 10; i++) { + if (verifyBuffer[i] == '{') { + // Found potential JSON start + String extractedJson = ""; + uint16_t jsonEnd = 0; + + for (uint16_t j = i; j < totalBytes; j++) { + if (verifyBuffer[j] >= 32 && verifyBuffer[j] <= 126) { + extractedJson += (char)verifyBuffer[j]; + if (verifyBuffer[j] == '}') { + jsonEnd = j; + break; + } + } + } + + Serial.print("Extracted JSON from tag: "); + Serial.println(extractedJson); + + // Try to parse the extracted JSON + JsonDocument testDoc; + DeserializationError error = deserializeJson(testDoc, extractedJson); + if (!error) { + Serial.println("✓ JSON VERIFICATION SUCCESSFUL!"); + Serial.print("✓ JSON is valid and parseable"); + + if (testDoc["sm_id"].is()) { + Serial.print(" - sm_id found: "); + Serial.println(testDoc["sm_id"].as()); + } else { + Serial.println(" - WARNING: sm_id not found in JSON!"); + } + + jsonFound = true; + testDoc.clear(); + break; + } else { + Serial.print("JSON parse error: "); + Serial.println(error.c_str()); + } + } + } + + if (!jsonFound) { + Serial.println("WARNING: No valid JSON found in verified data!"); + verificationSuccess = false; + } + + } else { + verificationSuccess = false; + } + } else { + Serial.println("VERIFICATION FAILED: Could not read back all data"); + verificationSuccess = false; + } + + Serial.println("========================="); + Serial.println(); + + if (!verificationSuccess) { + Serial.println("❌ WRITE FAILED - Data verification unsuccessful"); + Serial.println("❌ Tag may not contain the expected data"); + return 0; + } return 1; } @@ -759,6 +1064,73 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { return true; } +bool quickSpoolIdCheck(String uidString) { + // Fast-path: Read only first 2-3 pages to check for sm_id pattern + // This dramatically speeds up known spool recognition + + Serial.println("=== FAST-PATH: Quick sm_id Check ==="); + + // Read first 3 pages (12 bytes) after NDEF header (pages 4-6) + uint8_t quickData[12]; + memset(quickData, 0, 12); + + for (uint8_t page = 4; page < 7; page++) { + if (!nfc.ntag2xx_ReadPage(page, quickData + (page - 4) * 4)) { + Serial.print("Failed to read page "); + Serial.println(page); + return false; // Fall back to full read + } + } + + // Convert to string for pattern matching + String quickCheck = ""; + for (int i = 0; i < 12; i++) { + if (quickData[i] >= 32 && quickData[i] <= 126) { + quickCheck += (char)quickData[i]; + } + } + + Serial.print("Quick data (first 12 bytes): "); + Serial.println(quickCheck); + + // Look for sm_id pattern at the beginning + if (quickCheck.indexOf("\"sm_id\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") < 0) { + Serial.println("✓ FAST-PATH: sm_id found in first bytes - known spool detected!"); + + // Extract sm_id from quick data if possible + int smIdStart = quickCheck.indexOf("\"sm_id\":\"") + 9; + int smIdEnd = quickCheck.indexOf("\"", smIdStart); + + if (smIdEnd > smIdStart) { + String quickSpoolId = quickCheck.substring(smIdStart, smIdEnd); + Serial.print("✓ Quick extracted sm_id: "); + Serial.println(quickSpoolId); + + // Set as active spool immediately + activeSpoolId = quickSpoolId; + lastSpoolId = activeSpoolId; + + oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); + Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); + return true; // Skip full tag reading! + } + } + + // Check for other quick patterns + if (quickCheck.indexOf("\"location\":\"") >= 0) { + Serial.println("✓ FAST-PATH: Location tag detected"); + return false; // Need full read for location processing + } + + if (quickCheck.indexOf("\"brand\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") >= 0) { + Serial.println("✓ FAST-PATH: New brand filament detected (sm_id:0)"); + 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; @@ -768,11 +1140,13 @@ void writeJsonToTag(void *parameter) { nfcReaderState = NFC_WRITING; - // First request the reading task to be suspended and than wait until it responds - nfcReadingTaskSuspendRequest = true; - while(nfcReadingTaskSuspendState == false){ - vTaskDelay(100 / portTICK_PERIOD_MS); - } + // IMPORTANT: Do NOT suspend reading task during writing! + // We need to be able to read during write verification + // Just set the state to WRITING to prevent scan conflicts + Serial.println("NFC Write Task starting - Reader remains active for verification"); + + // Small delay to ensure any ongoing operations complete + vTaskDelay(100 / portTICK_PERIOD_MS); //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert @@ -860,7 +1234,9 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - nfcReadingTaskSuspendRequest = false; + // Since we didn't suspend reading, we don't need to re-enable it + // Just reset the state back to IDLE + Serial.println("NFC Write Task completed - Reader was never suspended"); pauseBambuMqttTask = false; free(params->payload); @@ -938,6 +1314,18 @@ void scanRfidTask(void * parameter) { 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) { diff --git a/src/nfc.h b/src/nfc.h index 2c3d5f3..10368c6 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -16,6 +16,7 @@ typedef enum{ void startNfc(); void scanRfidTask(void * parameter); void startWriteJsonToTag(const bool isSpoolTag, const char* payload); +bool quickSpoolIdCheck(String uidString); extern TaskHandle_t RfidReaderTask; extern String nfcJsonData; From 3e59ce136603d87535e85e4ece178ac974ccbe1c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 15:33:13 +0200 Subject: [PATCH 241/366] docs: update platformio.ini for beta version v1.5.12-beta14 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 71d9ea6..6cf680d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta13" +version = "1.5.12-beta14" to_old_version = "1.5.0" ## From 1f2195470394d37ed9fa9aef0e0b12cdaa273470 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 15:33:13 +0200 Subject: [PATCH 242/366] docs: update changelog and header for version v1.5.12-beta14 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e311266..080c185 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From c89adb6256d53b7e2c9814824e39cfcd7fdef493 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 15:52:16 +0200 Subject: [PATCH 243/366] refactor: enhance NFC write operation handling and prevent tag operations during write --- src/nfc.cpp | 26 +++++++++++++++++--------- src/nfc.h | 1 + 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index e9d0844..0b61ee3 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; @@ -1068,6 +1069,12 @@ bool quickSpoolIdCheck(String uidString) { // Fast-path: Read only first 2-3 pages to check for sm_id pattern // 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 first 3 pages (12 bytes) after NDEF header (pages 4-6) @@ -1139,14 +1146,16 @@ void writeJsonToTag(void *parameter) { Serial.println(params->payload); nfcReaderState = NFC_WRITING; + nfcWriteInProgress = true; // Block all tag operations during write - // IMPORTANT: Do NOT suspend reading task during writing! - // We need to be able to read during write verification - // Just set the state to WRITING to prevent scan conflicts - Serial.println("NFC Write Task starting - Reader remains active for verification"); + // Suspend reading task during writing to prevent interference + // But keep low-level NFC operations available for verification + nfcReadingTaskSuspendRequest = true; + while(nfcReadingTaskSuspendState == false){ + vTaskDelay(100 / portTICK_PERIOD_MS); + } - // Small delay to ensure any ongoing operations complete - vTaskDelay(100 / portTICK_PERIOD_MS); + Serial.println("NFC Write Task starting - All tag operations blocked during write"); //pauseBambuMqttTask = true; // aktualisieren der Website wenn sich der Status ändert @@ -1234,9 +1243,8 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - // Since we didn't suspend reading, we don't need to re-enable it - // Just reset the state back to IDLE - Serial.println("NFC Write Task completed - Reader was never suspended"); + nfcReadingTaskSuspendRequest = false; + nfcWriteInProgress = false; // Re-enable tag operations pauseBambuMqttTask = false; free(params->payload); diff --git a/src/nfc.h b/src/nfc.h index 10368c6..3633772 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -24,6 +24,7 @@ extern String activeSpoolId; extern String lastSpoolId; extern volatile nfcReaderStateType nfcReaderState; extern volatile bool pauseBambuMqttTask; +extern volatile bool nfcWriteInProgress; extern bool tagProcessed; From 2a0f999f3bf8e28f0f6559e9cbfca6f779c2c038 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 16:02:51 +0200 Subject: [PATCH 244/366] refactor: enhance NFC write operation diagnostics and improve error handling --- src/nfc.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 129 insertions(+), 22 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 0b61ee3..4776749 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -411,14 +411,54 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { // STEP 1: Read current tag content for debugging Serial.println(); - Serial.println("=== SCHRITT 1: AKTUELLER TAG-INHALT ==="); - uint8_t currentContent[64]; // Read first 16 pages - memset(currentContent, 0, 64); + Serial.println("=== SCHRITT 1: NFC-INTERFACE-DIAGNOSE ==="); + // First, check if the NFC interface is working at all + Serial.println("Teste 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.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(); + } + + // Test a few different pages to see which ones are accessible + uint8_t testData[4]; + for (uint8_t testPage = 0; testPage <= 10; 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"); + } + vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads + } + + Serial.println("=== SCHRITT 2: AKTUELLER TAG-INHALT ==="); + + // Only read user data pages that are confirmed to be readable for (uint8_t page = 4; page < 20; page++) { uint8_t pageData[4]; if (nfc.ntag2xx_ReadPage(page, pageData)) { - memcpy(¤tContent[(page-4)*4], pageData, 4); Serial.print("Seite "); Serial.print(page); Serial.print(": "); @@ -431,19 +471,82 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { } else { Serial.print("Fehler beim Lesen von Seite "); Serial.println(page); + // If we can't read basic user data pages, there's a fundamental problem + if (page <= 6) { + Serial.println("KRITISCHER FEHLER: Kann grundlegende User-Data-Seiten nicht lesen!"); + Serial.println("Möglicherweise NFC-Interface-Problem oder Tag-Zustandsproblem"); + return 0; + } } + vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads } Serial.println("========================================="); - // STEP 2: Simple write test - write one test page Serial.println(); - Serial.println("=== SCHRITT 2: SCHREIBTEST ==="); + Serial.println("=== SCHRITT 3: SCHREIBTEST ==="); + Serial.println(); + Serial.println("=== SCHRITT 3: SCHREIBTEST ==="); + + // If basic pages are not readable, try to reinitialize NFC interface + Serial.println("Versuche NFC-Interface zu stabilisieren..."); + + // Give the NFC interface time to stabilize + vTaskDelay(100 / portTICK_PERIOD_MS); + + // Try to reestablish communication + bool interfaceOk = false; + for (int retry = 0; retry < 3; retry++) { + Serial.print("NFC-Interface Test "); + Serial.print(retry + 1); + Serial.print("/3... "); + + uint8_t ccRetest[4]; + if (nfc.ntag2xx_ReadPage(3, ccRetest)) { + Serial.println("✓"); + interfaceOk = true; + break; + } else { + Serial.println("❌"); + vTaskDelay(200 / portTICK_PERIOD_MS); + } + } + + if (!interfaceOk) { + Serial.println("FEHLER: NFC-Interface nicht stabil - Schreibvorgang abgebrochen"); + oledShowMessage("NFC Interface Error"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + return 0; + } + + Serial.println("NFC-Interface ist stabil - fahre mit Schreibtest fort"); + uint8_t testPage[4] = {0xAA, 0xBB, 0xCC, 0xDD}; // Test pattern if (!nfc.ntag2xx_WritePage(10, testPage)) { // Use page 10 for test Serial.println("FEHLER: Einfacher Schreibtest fehlgeschlagen!"); Serial.println("Tag ist möglicherweise schreibgeschützt oder defekt"); - oledShowMessage("Tag write protected?"); + + // Additional diagnostics + Serial.println("=== ERWEITERTE DIAGNOSE ==="); + + // Check if this is a timing issue + Serial.println("Teste Tag-Erkennung erneut..."); + 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 Schreibvorgang entfernt!"); + oledShowMessage("Tag removed during write"); + } else { + Serial.println("URSACHE: Tag ist vorhanden aber nicht beschreibbar"); + Serial.println("Möglicherweise: Schreibschutz, Defekt, oder Timing-Problem"); + oledShowMessage("Tag write protected?"); + } + Serial.println("==============================="); + vTaskDelay(3000 / portTICK_PERIOD_MS); return 0; } @@ -1146,16 +1249,11 @@ void writeJsonToTag(void *parameter) { Serial.println(params->payload); nfcReaderState = NFC_WRITING; - nfcWriteInProgress = true; // Block all tag operations during write + nfcWriteInProgress = true; // Block high-level tag operations during write - // Suspend reading task during writing to prevent interference - // But keep low-level NFC operations available for verification - nfcReadingTaskSuspendRequest = true; - while(nfcReadingTaskSuspendState == false){ - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - Serial.println("NFC Write Task starting - All tag operations blocked during write"); + // 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 @@ -1243,8 +1341,8 @@ void writeJsonToTag(void *parameter) { sendWriteResult(nullptr, success); sendNfcData(); - nfcReadingTaskSuspendRequest = false; - nfcWriteInProgress = false; // Re-enable tag operations + // Only reset the write protection flag - reading task was never suspended + nfcWriteInProgress = false; // Re-enable high-level tag operations pauseBambuMqttTask = false; free(params->payload); @@ -1279,8 +1377,8 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { void scanRfidTask(void * parameter) { Serial.println("RFID Task gestartet"); for(;;) { - // Wenn geschrieben wird Schleife aussetzen - if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest && !booting) + // Skip scanning during write operations, but keep NFC interface active + if (nfcReaderState != NFC_WRITING && !nfcWriteInProgress && !nfcReadingTaskSuspendRequest && !booting) { nfcReadingTaskSuspendState = false; yield(); @@ -1425,8 +1523,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(); } From 8702469020887ae160c948557df5cdeda1cdd841 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 16:02:56 +0200 Subject: [PATCH 245/366] docs: update platformio.ini for beta version v1.5.12-beta15 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 6cf680d..5cf82d5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta14" +version = "1.5.12-beta15" to_old_version = "1.5.0" ## From bda8c3dd98465042ac290443abfb177b2047a4a1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 16:02:57 +0200 Subject: [PATCH 246/366] docs: update changelog and header for version v1.5.12-beta15 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 080c185..7c4f369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [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 From fef7e5aa4b14d18d462f4949559df3ff6908fa1d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:04:33 +0200 Subject: [PATCH 247/366] Refactor NFC interface handling and improve error diagnostics - Removed unused function for getting current date in ISO8601 format. - Updated JSON key names in filament and spool creation to use shorter identifiers. - Enhanced NFC interface reset procedure with detailed logging and retry mechanisms. - Improved stability checks after write operations to ensure NFC interface readiness. - Added comprehensive error handling and diagnostics for NFC read/write operations. - Streamlined the quick spool ID check to optimize performance and reliability. --- src/api.cpp | 70 ++--- src/nfc.cpp | 719 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 601 insertions(+), 188 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 8391ff8..b12de2a 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -9,18 +9,6 @@ #include volatile spoolmanApiStateType spoolmanApiState = API_IDLE; -// Returns current date and time in ISO8601 format -String getCurrentDateISO8601() { - struct tm timeinfo; - if(!getLocalTime(&timeinfo)) { - Serial.println("Failed to obtain time"); - return "1970-01-01T00:00:00Z"; - } - char timeStringBuff[25]; - strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%SZ", &timeinfo); - return String(timeStringBuff); -} - //bool spoolman_connected = false; String spoolmanUrl = ""; bool octoEnabled = false; @@ -627,7 +615,6 @@ uint16_t createVendor(String vendor) { JsonDocument vendorDoc; vendorDoc["name"] = vendor; vendorDoc["comment"] = "automatically generated"; - vendorDoc["empty_spool_weight"] = 180; vendorDoc["external_id"] = vendor; String vendorPayload; @@ -748,34 +735,34 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // Create JSON payload for filament creation JsonDocument filamentDoc; - filamentDoc["name"] = payload["color_name"].as(); + filamentDoc["name"] = payload["cn"].as(); filamentDoc["vendor_id"] = String(vendorId); - filamentDoc["material"] = payload["type"].as(); - filamentDoc["density"] = (payload["density"].is() && payload["density"].as().length() > 0) ? payload["density"].as() : "1.24"; - filamentDoc["diameter"] = (payload["diameter"].is() && payload["diameter"].as().length() > 0) ? payload["diameter"].as() : "1.75"; + 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["spool_weight"].as(); - filamentDoc["article_number"] = payload["artnr"].as(); - filamentDoc["settings_extruder_temp"] = payload["extruder_temp"].is() ? payload["extruder_temp"].as() : ""; - filamentDoc["settings_bed_temp"] = payload["bed_temp"].is() ? payload["bed_temp"].as() : ""; - - if (payload["artnr"].is()) + 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["artnr"].as(); - filamentDoc["comment"] = payload["url"].is() ? payload["url"].as() + payload["artnr"].as() : "automatically generated"; + filamentDoc["external_id"] = payload["an"].as(); + filamentDoc["comment"] = payload["u"].is() ? payload["u"].as() + payload["an"].as() : "automatically generated"; } else { - filamentDoc["comment"] = payload["url"].is() ? payload["url"].as() : "automatically generated"; + filamentDoc["comment"] = payload["u"].is() ? payload["u"].as() : "automatically generated"; } - if (payload["multi_color_hexes"].is()) { - filamentDoc["multi_color_hexes"] = payload["multi_color_hexes"].as(); - filamentDoc["multi_color_direction"] = payload["multi_color_direction"].is() ? payload["multi_color_direction"].as() : ""; + 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["color_hex"].is() && payload["color_hex"].as().length() >= 6) ? payload["color_hex"].as() : "FFFFFF"; + filamentDoc["color_hex"] = (payload["c"].is() && payload["c"].as().length() >= 6) ? payload["c"].as() : "FFFFFF"; } String filamentPayload; @@ -883,17 +870,14 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; Serial.print("Create spool with URL: "); Serial.println(spoolsUrl); - //String currentDate = getCurrentDateISO8601(); // Create JSON payload for spool creation JsonDocument spoolDoc; - //spoolDoc["first_used"] = String(currentDate); - //spoolDoc["last_used"] = String(currentDate); spoolDoc["filament_id"] = String(filamentId); - spoolDoc["initial_weight"] = weight > 10 ? String(weight-payload["spool_weight"].as()) : "1000"; - spoolDoc["spool_weight"] = (payload["spool_weight"].is() && payload["spool_weight"].as().length() > 0) ? payload["spool_weight"].as() : "180"; - spoolDoc["remaining_weight"] = (payload["weight"].is() && payload["weight"].as().length() > 0) ? payload["weight"].as() : "1000"; - spoolDoc["lot_nr"] = (payload["lotnr"].is() && payload["lotnr"].as().length() > 0) ? payload["lotnr"].as() : ""; + 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 + "\""; @@ -942,13 +926,15 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // 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(); // Copy all other fields from original payload (excluding sm_id if it exists) - for (JsonPair kv : payload.as()) { - if (strcmp(kv.key().c_str(), "sm_id") != 0) { // Skip sm_id to avoid duplication - optimizedPayload[kv.key()] = kv.value(); - } - } + //for (JsonPair kv : payload.as()) { + // if (strcmp(kv.key().c_str(), "sm_id") != 0) { // Skip sm_id to avoid duplication + // optimizedPayload[kv.key()] = kv.value(); + // } + //} String payloadString; serializeJson(optimizedPayload, payloadString); diff --git a/src/nfc.cpp b/src/nfc.cpp index 4776749..3228c92 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -409,12 +409,12 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println("✓ Payload passt in den Tag - Schreibvorgang wird fortgesetzt"); - // STEP 1: Read current tag content for debugging + // STEP 1: NFC Interface Reset and Reinitialization Serial.println(); - Serial.println("=== SCHRITT 1: NFC-INTERFACE-DIAGNOSE ==="); + Serial.println("=== SCHRITT 1: NFC-INTERFACE RESET UND NEUINITIALISIERUNG ==="); // First, check if the NFC interface is working at all - Serial.println("Teste NFC-Interface-Zustand..."); + Serial.println("Teste aktuellen NFC-Interface-Zustand..."); // Try to read capability container (which worked during detection) uint8_t ccTest[4]; @@ -422,6 +422,88 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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++) { @@ -432,9 +514,13 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println(); } - // Test a few different pages to see which ones are accessible + Serial.println("=== SCHRITT 2: INTERFACE-FUNKTIONSTEST ==="); + + // Test a few critical pages to ensure stable operation uint8_t testData[4]; - for (uint8_t testPage = 0; testPage <= 10; testPage++) { + bool basicPagesReadable = true; + + for (uint8_t testPage = 0; testPage <= 6; testPage++) { bool readable = nfc.ntag2xx_ReadPage(testPage, testData); Serial.print("Seite "); Serial.print(testPage); @@ -449,88 +535,58 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println(); } else { Serial.println("❌ - Nicht lesbar"); - } - vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads - } - - Serial.println("=== SCHRITT 2: AKTUELLER TAG-INHALT ==="); - - // Only read user data pages that are confirmed to be readable - for (uint8_t page = 4; page < 20; page++) { - uint8_t pageData[4]; - if (nfc.ntag2xx_ReadPage(page, pageData)) { - Serial.print("Seite "); - Serial.print(page); - Serial.print(": "); - for (int i = 0; i < 4; i++) { - if (pageData[i] < 0x10) Serial.print("0"); - Serial.print(pageData[i], HEX); - Serial.print(" "); - } - Serial.println(); - } else { - Serial.print("Fehler beim Lesen von Seite "); - Serial.println(page); - // If we can't read basic user data pages, there's a fundamental problem - if (page <= 6) { - Serial.println("KRITISCHER FEHLER: Kann grundlegende User-Data-Seiten nicht lesen!"); - Serial.println("Möglicherweise NFC-Interface-Problem oder Tag-Zustandsproblem"); - return 0; + if (testPage >= 3 && testPage <= 6) { // Critical pages for NDEF + basicPagesReadable = false; } } vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads } - Serial.println("========================================="); - - Serial.println(); - Serial.println("=== SCHRITT 3: SCHREIBTEST ==="); - Serial.println(); - Serial.println("=== SCHRITT 3: SCHREIBTEST ==="); - // If basic pages are not readable, try to reinitialize NFC interface - Serial.println("Versuche NFC-Interface zu stabilisieren..."); - - // Give the NFC interface time to stabilize - vTaskDelay(100 / portTICK_PERIOD_MS); - - // Try to reestablish communication - bool interfaceOk = false; - for (int retry = 0; retry < 3; retry++) { - Serial.print("NFC-Interface Test "); - Serial.print(retry + 1); - Serial.print("/3... "); - - uint8_t ccRetest[4]; - if (nfc.ntag2xx_ReadPage(3, ccRetest)) { - Serial.println("✓"); - interfaceOk = true; - break; - } else { - Serial.println("❌"); - vTaskDelay(200 / portTICK_PERIOD_MS); - } - } - - if (!interfaceOk) { - Serial.println("FEHLER: NFC-Interface nicht stabil - Schreibvorgang abgebrochen"); - oledShowMessage("NFC Interface Error"); + 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("NFC-Interface ist stabil - fahre mit Schreibtest fort"); + 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 - if (!nfc.ntag2xx_WritePage(10, testPage)) { // Use page 10 for test - Serial.println("FEHLER: Einfacher Schreibtest fehlgeschlagen!"); + // 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 DIAGNOSE ==="); + Serial.println("=== ERWEITERTE SCHREIBTEST-DIAGNOSE ==="); - // Check if this is a timing issue - Serial.println("Teste Tag-Erkennung erneut..."); + // 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); @@ -538,14 +594,14 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println(tagStillPresent ? "✓" : "❌"); if (!tagStillPresent) { - Serial.println("URSACHE: Tag wurde während Schreibvorgang entfernt!"); - oledShowMessage("Tag removed during write"); + 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 Timing-Problem"); + Serial.println("Möglicherweise: Schreibschutz, Defekt, oder Interface-Problem"); oledShowMessage("Tag write protected?"); } - Serial.println("==============================="); + Serial.println("=========================================="); vTaskDelay(3000 / portTICK_PERIOD_MS); return 0; @@ -553,8 +609,12 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { // 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; } @@ -581,12 +641,20 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { return 0; } - Serial.println("✓ Schreibtest erfolgreich - Tag ist beschreibbar"); - Serial.println("================================"); + // 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 3: NDEF initialization with verification + // STEP 4: NDEF initialization with verification Serial.println(); - Serial.println("=== SCHRITT 3: NDEF-INITIALISIERUNG ==="); + Serial.println("=== SCHRITT 4: NDEF-INITIALISIERUNG ==="); if (!initializeNdefStructure()) { Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); oledShowMessage("NDEF init failed"); @@ -617,6 +685,42 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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) { @@ -677,7 +781,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { uint16_t totalBytes = offset + 1; Serial.println(); - Serial.println("=== SCHRITT 4: SCHREIBE NEUE NDEF-DATEN ==="); + Serial.println("=== SCHRITT 6: SCHREIBE NEUE NDEF-DATEN ==="); Serial.print("Schreibe "); Serial.print(totalBytes); Serial.print(" Bytes in "); @@ -701,8 +805,26 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { // Copy data to page buffer memcpy(pageBuffer, &tlvData[bytesWritten], bytesToWrite); - // Write page to tag - if (!nfc.ntag2xx_WritePage(pageNumber, pageBuffer)) { + // 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 (!writeSuccess) { Serial.print("FEHLER beim Schreiben der Seite "); Serial.println(pageNumber); Serial.print("Möglicherweise Page-Limit erreicht für "); @@ -727,35 +849,52 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.print("... "); uint8_t verifyBuffer[4]; - vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay before verification + vTaskDelay(20 / portTICK_PERIOD_MS); // Increased delay before verification - if (nfc.ntag2xx_ReadPage(pageNumber, verifyBuffer)) { - bool writeSuccess = true; - for (int i = 0; i < bytesToWrite; i++) { - if (verifyBuffer[i] != pageBuffer[i]) { - writeSuccess = 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); + // 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 (!writeSuccess) { - Serial.println("❌ SCHREIBVORGANG FEHLGESCHLAGEN!"); - free(tlvData); - return 0; - } else { - Serial.println("✓"); - } - } else { - Serial.println("❌ Kann Seite nicht zur Verifikation lesen!"); + } + + if (!verifySuccess) { + Serial.println("❌ SCHREIBVORGANG/VERIFIKATION FEHLGESCHLAGEN!"); free(tlvData); return 0; + } else { + Serial.println("✓"); } Serial.print("Seite "); @@ -772,7 +911,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { pageNumber++; yield(); - vTaskDelay(5 / portTICK_PERIOD_MS); // Small delay between page writes + vTaskDelay(10 / portTICK_PERIOD_MS); // Slightly increased delay between page writes } free(tlvData); @@ -799,12 +938,72 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { 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("=================================================================="); + // CRITICAL: Verify the write by reading back the data Serial.println(); Serial.println("=== WRITE VERIFICATION ==="); // Wait a moment for tag to stabilize - vTaskDelay(100 / portTICK_PERIOD_MS); + vTaskDelay(200 / portTICK_PERIOD_MS); // Increased stabilization time + + // Only proceed with verification if interface is responsive + if (!interfaceResponsive) { + Serial.println("SKIPPING VERIFICATION: Interface not responsive"); + Serial.println("❌ WRITE COMPLETED but VERIFICATION SKIPPED"); + Serial.println("❌ Cannot guarantee data integrity"); + return 0; + } // Read back the written data to verify uint8_t verifyBuffer[totalBytes]; @@ -816,7 +1015,27 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { while (verifyBytesRead < totalBytes && verifyPage <= maxWritablePage) { uint8_t pageData[4]; - if (!nfc.ntag2xx_ReadPage(verifyPage, pageData)) { + + // Verification read with retry mechanism + bool pageReadSuccess = false; + for (int readAttempt = 0; readAttempt < 3; readAttempt++) { + if (nfc.ntag2xx_ReadPage(verifyPage, pageData)) { + pageReadSuccess = true; + break; + } else { + Serial.print("Verification read attempt "); + Serial.print(readAttempt + 1); + Serial.print("/3 for page "); + Serial.print(verifyPage); + Serial.println(" failed"); + + if (readAttempt < 2) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + } + } + + if (!pageReadSuccess) { Serial.print("VERIFICATION FAILED: Cannot read page "); Serial.println(verifyPage); verificationSuccess = false; @@ -829,6 +1048,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { verifyBytesRead += bytesToCopy; verifyPage++; + + vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between verification reads } if (verificationSuccess && verifyBytesRead >= totalBytes) { @@ -903,6 +1124,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { if (!jsonFound) { Serial.println("WARNING: No valid JSON found in verified data!"); verificationSuccess = false; + } else { + Serial.println("✓ JSON extracted and validated successfully"); } } else { @@ -1144,7 +1367,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { } // Brand Filament not registered to Spoolman else if ((!doc["sm_id"].is() || (doc["sm_id"].is() && (doc["sm_id"] == "0" || doc["sm_id"] == ""))) - && doc["brand"].is() && doc["artnr"].is()) + && 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 @@ -1169,7 +1392,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { } bool quickSpoolIdCheck(String uidString) { - // Fast-path: Read only first 2-3 pages to check for sm_id pattern + // 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! @@ -1180,60 +1403,197 @@ bool quickSpoolIdCheck(String uidString) { Serial.println("=== FAST-PATH: Quick sm_id Check ==="); - // Read first 3 pages (12 bytes) after NDEF header (pages 4-6) - uint8_t quickData[12]; - memset(quickData, 0, 12); + // 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 < 7; page++) { - if (!nfc.ntag2xx_ReadPage(page, quickData + (page - 4) * 4)) { + for (uint8_t page = 4; page < 9; page++) { + if (!nfc.ntag2xx_ReadPage(page, ndefData + (page - 4) * 4)) { Serial.print("Failed to read page "); Serial.println(page); return false; // Fall back to full read } } - // Convert to string for pattern matching - String quickCheck = ""; - for (int i = 0; i < 12; i++) { - if (quickData[i] >= 32 && quickData[i] <= 126) { - quickCheck += (char)quickData[i]; + // 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; } } - Serial.print("Quick data (first 12 bytes): "); - Serial.println(quickCheck); + if (tlvOffset == -1) { + Serial.println("✗ FAST-PATH: No NDEF TLV found"); + return false; + } - // Look for sm_id pattern at the beginning - if (quickCheck.indexOf("\"sm_id\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") < 0) { - Serial.println("✓ FAST-PATH: sm_id found in first bytes - known spool detected!"); + // 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"); - // Extract sm_id from quick data if possible - int smIdStart = quickCheck.indexOf("\"sm_id\":\"") + 9; - int smIdEnd = quickCheck.indexOf("\"", smIdStart); + // Read additional pages to get to JSON payload + uint8_t extraData[16]; // Read 4 more pages + memset(extraData, 0, 16); - if (smIdEnd > smIdStart) { - String quickSpoolId = quickCheck.substring(smIdStart, smIdEnd); + for (uint8_t page = 9; page < 13; page++) { + if (!nfc.ntag2xx_ReadPage(page, extraData + (page - 9) * 4)) { + Serial.print("Failed to read additional page "); + Serial.println(page); + return false; + } + } + + // 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; + + 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); - // Set as active spool immediately - activeSpoolId = quickSpoolId; - lastSpoolId = activeSpoolId; - - oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); - Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); - return true; // Skip full tag reading! + // 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; + + 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 quick patterns - if (quickCheck.indexOf("\"location\":\"") >= 0) { + // 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 (quickCheck.indexOf("\"brand\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") >= 0) { - Serial.println("✓ FAST-PATH: New brand filament detected (sm_id:0)"); + 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 } @@ -1312,13 +1672,80 @@ void writeJsonToTag(void *parameter) { }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); } From 1460c6e5f9760327994aee02f6091a7556e3d95b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:04:41 +0200 Subject: [PATCH 248/366] docs: update platformio.ini for beta version v1.5.12-beta16 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5cf82d5..3ecd9ec 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta15" +version = "1.5.12-beta16" to_old_version = "1.5.0" ## From 0d3503f4f1c3297ee565027b802957324996ef87 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:04:41 +0200 Subject: [PATCH 249/366] docs: update changelog and header for version v1.5.12-beta16 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c4f369..15b0f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From ac91e71c14e061b86eef7d6390dcd946b37eddc5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:20:44 +0200 Subject: [PATCH 250/366] refactor: optimize page limit detection and remove redundant verification code --- src/api.cpp | 7 -- src/nfc.cpp | 201 ++++++++++------------------------------------------ 2 files changed, 39 insertions(+), 169 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index b12de2a..fbbfb3d 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -929,13 +929,6 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo optimizedPayload["b"] = payload["b"].as(); optimizedPayload["cn"] = payload["an"].as(); - // Copy all other fields from original payload (excluding sm_id if it exists) - //for (JsonPair kv : payload.as()) { - // if (strcmp(kv.key().c_str(), "sm_id") != 0) { // Skip sm_id to avoid duplication - // optimizedPayload[kv.key()] = kv.value(); - // } - //} - String payloadString; serializeJson(optimizedPayload, payloadString); diff --git a/src/nfc.cpp b/src/nfc.cpp index 3228c92..13db9bd 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -324,16 +324,48 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.print("WARNING: Cannot read declared max page "); Serial.println(maxWritablePage); - // Find actual maximum writable page by testing backwards + // Find actual maximum writable page by testing backwards with optimized approach uint16_t actualMaxPage = maxWritablePage; - for (uint16_t testPage = maxWritablePage; testPage >= 4; testPage--) { - if (nfc.ntag2xx_ReadPage(testPage, testBuffer)) { - actualMaxPage = testPage; - Serial.print("Found actual max readable page: "); - Serial.println(actualMaxPage); - break; + 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"); @@ -990,161 +1022,6 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { Serial.println("=================================================================="); - // CRITICAL: Verify the write by reading back the data - Serial.println(); - Serial.println("=== WRITE VERIFICATION ==="); - - // Wait a moment for tag to stabilize - vTaskDelay(200 / portTICK_PERIOD_MS); // Increased stabilization time - - // Only proceed with verification if interface is responsive - if (!interfaceResponsive) { - Serial.println("SKIPPING VERIFICATION: Interface not responsive"); - Serial.println("❌ WRITE COMPLETED but VERIFICATION SKIPPED"); - Serial.println("❌ Cannot guarantee data integrity"); - return 0; - } - - // Read back the written data to verify - uint8_t verifyBuffer[totalBytes]; - memset(verifyBuffer, 0, totalBytes); - - bool verificationSuccess = true; - uint8_t verifyPage = 4; - uint16_t verifyBytesRead = 0; - - while (verifyBytesRead < totalBytes && verifyPage <= maxWritablePage) { - uint8_t pageData[4]; - - // Verification read with retry mechanism - bool pageReadSuccess = false; - for (int readAttempt = 0; readAttempt < 3; readAttempt++) { - if (nfc.ntag2xx_ReadPage(verifyPage, pageData)) { - pageReadSuccess = true; - break; - } else { - Serial.print("Verification read attempt "); - Serial.print(readAttempt + 1); - Serial.print("/3 for page "); - Serial.print(verifyPage); - Serial.println(" failed"); - - if (readAttempt < 2) { - vTaskDelay(50 / portTICK_PERIOD_MS); - } - } - } - - if (!pageReadSuccess) { - Serial.print("VERIFICATION FAILED: Cannot read page "); - Serial.println(verifyPage); - verificationSuccess = false; - break; - } - - // Copy page data to verify buffer - uint16_t bytesToCopy = min(4, (int)(totalBytes - verifyBytesRead)); - memcpy(&verifyBuffer[verifyBytesRead], pageData, bytesToCopy); - - verifyBytesRead += bytesToCopy; - verifyPage++; - - vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between verification reads - } - - if (verificationSuccess && verifyBytesRead >= totalBytes) { - // Compare written data with read data - bool dataMatches = true; - for (uint16_t i = 0; i < totalBytes; i++) { - if (verifyBuffer[i] != tlvData[i]) { - Serial.print("VERIFICATION FAILED: Data mismatch at byte "); - Serial.print(i); - Serial.print(" - Expected: 0x"); - Serial.print(tlvData[i], HEX); - Serial.print(", Read: 0x"); - Serial.println(verifyBuffer[i], HEX); - dataMatches = false; - break; - } - } - - if (dataMatches) { - Serial.println("✓ WRITE VERIFICATION SUCCESSFUL!"); - Serial.println("✓ All written data verified correctly"); - - // Additional JSON verification - try to parse the written JSON - Serial.println("=== JSON VERIFICATION ==="); - - // Find and extract JSON from verified data - // Look for the JSON payload within the NDEF structure - bool jsonFound = false; - for (uint16_t i = 0; i < totalBytes - 10; i++) { - if (verifyBuffer[i] == '{') { - // Found potential JSON start - String extractedJson = ""; - uint16_t jsonEnd = 0; - - for (uint16_t j = i; j < totalBytes; j++) { - if (verifyBuffer[j] >= 32 && verifyBuffer[j] <= 126) { - extractedJson += (char)verifyBuffer[j]; - if (verifyBuffer[j] == '}') { - jsonEnd = j; - break; - } - } - } - - Serial.print("Extracted JSON from tag: "); - Serial.println(extractedJson); - - // Try to parse the extracted JSON - JsonDocument testDoc; - DeserializationError error = deserializeJson(testDoc, extractedJson); - if (!error) { - Serial.println("✓ JSON VERIFICATION SUCCESSFUL!"); - Serial.print("✓ JSON is valid and parseable"); - - if (testDoc["sm_id"].is()) { - Serial.print(" - sm_id found: "); - Serial.println(testDoc["sm_id"].as()); - } else { - Serial.println(" - WARNING: sm_id not found in JSON!"); - } - - jsonFound = true; - testDoc.clear(); - break; - } else { - Serial.print("JSON parse error: "); - Serial.println(error.c_str()); - } - } - } - - if (!jsonFound) { - Serial.println("WARNING: No valid JSON found in verified data!"); - verificationSuccess = false; - } else { - Serial.println("✓ JSON extracted and validated successfully"); - } - - } else { - verificationSuccess = false; - } - } else { - Serial.println("VERIFICATION FAILED: Could not read back all data"); - verificationSuccess = false; - } - - Serial.println("========================="); - Serial.println(); - - if (!verificationSuccess) { - Serial.println("❌ WRITE FAILED - Data verification unsuccessful"); - Serial.println("❌ Tag may not contain the expected data"); - return 0; - } - return 1; } From bd8f4606c69e21d87b8ced46c3d0e668a8744acf Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:30:04 +0200 Subject: [PATCH 251/366] feat: add progress bar updates for vendor and filament creation processes --- src/api.cpp | 10 ++++++++++ src/display.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/api.cpp b/src/api.cpp index fbbfb3d..624a57d 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -602,6 +602,8 @@ bool updateSpoolBambuData(String payload) { // #### Brand Filament uint16_t createVendor(String vendor) { + 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 @@ -662,6 +664,8 @@ uint16_t createVendor(String vendor) { } uint16_t checkVendor(String vendor) { + 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 @@ -724,6 +728,8 @@ uint16_t checkVendor(String vendor) { } 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 @@ -810,6 +816,8 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { } 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 @@ -862,6 +870,8 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { } 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 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 From aea11e0c06ada172d2ceda201671ac94b557a450 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:31:25 +0200 Subject: [PATCH 252/366] fix: update vendor check to use shorthand key in payload --- src/api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.cpp b/src/api.cpp index 624a57d..e025725 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -955,7 +955,7 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo } bool createBrandFilament(JsonDocument& payload, String uidString) { - uint16_t vendorId = checkVendor(payload["brand"].as()); + uint16_t vendorId = checkVendor(payload["b"].as()); if (vendorId == 0) { Serial.println("ERROR: Failed to create/find vendor"); return false; From 687e57b77a237b3f2f9d54ea4f9a49029492ad90 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:32:46 +0200 Subject: [PATCH 253/366] docs: update platformio.ini for beta version v1.5.12-beta17 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3ecd9ec..f00f9f5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta16" +version = "1.5.12-beta17" to_old_version = "1.5.0" ## From 213b9c099c59612fc4c740a773ced04f51e24f04 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:32:46 +0200 Subject: [PATCH 254/366] docs: update changelog and header for version v1.5.12-beta17 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15b0f60..5173426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [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 From 17f03e9472a5db98d2117a16be28cd12b5902ec0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 17:57:23 +0200 Subject: [PATCH 255/366] feat: add display delay for vendor, filament, and spool creation processes --- src/api.cpp | 11 ++++++++++- src/scale.cpp | 12 +++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index e025725..70adeb6 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -654,6 +654,9 @@ uint16_t createVendor(String vendor) { 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) { @@ -806,6 +809,9 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { 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) { @@ -948,7 +954,10 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo optimizedPayload.clear(); nfcReaderState = NFC_IDLE; - vTaskDelay(50 / portTICK_PERIOD_MS); + + // Delay for Display Bar + vTaskDelay(1000 / portTICK_PERIOD_MS); + startWriteJsonToTag(true, payloadString.c_str()); return createdSpoolId; diff --git a/src/scale.cpp b/src/scale.cpp index c16ff3b..d3ba2e0 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -48,9 +48,6 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); - vTaskDelay(pdMS_TO_TICKS(500)); - scale_tare_counter = 10; // damit beim Starten der Waage automatisch getart wird - for(;;) { if (scale.is_ready()) { @@ -120,12 +117,13 @@ void start_scale(bool touchSensorConnected) { 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); // this value is obtained by calibrating the scale with known weights; see the README for details + scale.tare(); + // Display Gewicht oledShowWeight(0); From 1c0ddb52baa4772da535b70fc36a5201247254a4 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:04:47 +0200 Subject: [PATCH 256/366] fix: replace progress bar with message display for remaining weight in sendToApi function --- src/api.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 70adeb6..c2e6c17 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -158,7 +158,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 @@ -173,7 +174,8 @@ 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: From cb77112976b3d2f00db4f1506595d11514d8aa31 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:04:56 +0200 Subject: [PATCH 257/366] docs: update platformio.ini for beta version v1.5.12-beta18 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index f00f9f5..cc9819a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta17" +version = "1.5.12-beta18" to_old_version = "1.5.0" ## From d9a8388ac729e5acccd2e3ad806f309cfc8256a3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:04:56 +0200 Subject: [PATCH 258/366] docs: update changelog and header for version v1.5.12-beta18 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5173426..b8745e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [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 From e0cc99e993bd9e0816ad7474fa3f0cf2ec378878 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:06:48 +0200 Subject: [PATCH 259/366] chore: update version to 2.0.0 in platformio.ini --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index cc9819a..beca2f2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,8 +9,8 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "1.5.12-beta18" -to_old_version = "1.5.0" +version = "2.0.0" +to_old_version = "2.0.0" ## [env:esp32dev] From 587485d0dee27d8e1bc12658e27efb61453f7059 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:06:55 +0200 Subject: [PATCH 260/366] docs: update platformio.ini for beta version v2.0.0-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index beca2f2..ddf850d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0" +version = "2.0.0-beta1" to_old_version = "2.0.0" ## From fcd637cc304fc52bf73ba747d8ae0af87415541f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:06:55 +0200 Subject: [PATCH 261/366] docs: update changelog and header for version v2.0.0-beta1 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8745e3..762f2e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 7ff499f9847c6db1626864ce85c94f1b9a887211 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:18:59 +0200 Subject: [PATCH 262/366] docs: add Manufacturer Tags support documentation in German and English --- README.de.md | 28 ++++++ README.md | 28 ++++++ README_ManufacturerTags_DE.md | 159 ++++++++++++++++++++++++++++++++++ README_ManufacturerTags_EN.md | 145 +++++++++++++++++++++++++++++++ 4 files changed, 360 insertions(+) create mode 100644 README_ManufacturerTags_DE.md create mode 100644 README_ManufacturerTags_EN.md diff --git a/README.de.md b/README.de.md index 248e67c..e1015bc 100644 --- a/README.de.md +++ b/README.de.md @@ -27,6 +27,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 +40,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 diff --git a/README.md b/README.md index 1988b0c..e8f7fe3 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,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 +44,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 diff --git a/README_ManufacturerTags_DE.md b/README_ManufacturerTags_DE.md new file mode 100644 index 0000000..ebdd7f9 --- /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 für zusätzliche Informationen + +### 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..f21085f --- /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 for additional information + +### 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 From 02e31878eede9543c9b95fad80053201ec1dc552 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:22:40 +0200 Subject: [PATCH 263/366] docs: clarify product URL description for Manufacturer Tags in German and English documentation --- README_ManufacturerTags_DE.md | 2 +- README_ManufacturerTags_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README_ManufacturerTags_DE.md b/README_ManufacturerTags_DE.md index ebdd7f9..bd46b35 100644 --- a/README_ManufacturerTags_DE.md +++ b/README_ManufacturerTags_DE.md @@ -62,7 +62,7 @@ Hersteller Tags müssen eine JSON-Payload mit spezifischen Feldern enthalten, di - **`mc`** (multicolor): Komma-getrennte Hex-Farben für Mehrfarben-Filamente - **`mcd`** (multicolor direction): Richtung für Mehrfarben (coaxial, longitudinal) -- **`u`** (url): Produkt-URL für zusätzliche Informationen +- **`u`** (url): Produkt-URL mit direktem Link zum Artikel zB für Nachbestellung ### Beispiel Tag diff --git a/README_ManufacturerTags_EN.md b/README_ManufacturerTags_EN.md index f21085f..f2ad5a8 100644 --- a/README_ManufacturerTags_EN.md +++ b/README_ManufacturerTags_EN.md @@ -62,7 +62,7 @@ Manufacturer tags must contain a JSON payload with specific fields using **short - **`mc`** (multicolor): Comma-separated hex colors for multicolor filaments - **`mcd`** (multicolor direction): Direction for multicolor (coaxial, longitudinal) -- **`u`** (url): Product URL for additional information +- **`u`** (url): Product URL with direct link to the article e.g. for reordering ### Example Tag From f0eced85858170631bdfd257705178d050a161e3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:30:58 +0200 Subject: [PATCH 264/366] fix: increase delay in start_scale function for improved stability --- src/scale.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index d3ba2e0..3ee71c6 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -111,7 +111,7 @@ 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++) { + for (uint16_t i = 0; i < 3000; i++) { yield(); vTaskDelay(pdMS_TO_TICKS(1)); esp_task_wdt_reset(); @@ -121,7 +121,8 @@ void start_scale(bool touchSensorConnected) { vTaskDelay(pdMS_TO_TICKS(5000)); } - scale.set_scale(calibrationValue); // this value is obtained by calibrating the scale with known weights; see the README for details + scale.set_scale(calibrationValue); + vTaskDelay(pdMS_TO_TICKS(5000)); scale.tare(); // Display Gewicht From 4cce9f8d5db3d7abdc377ac8675445b019397414 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:31:08 +0200 Subject: [PATCH 265/366] docs: update platformio.ini for beta version v2.0.0-beta2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ddf850d..b060254 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta1" +version = "2.0.0-beta2" to_old_version = "2.0.0" ## From 52a7f6b5b665d5656171968760a17e7c4eb6d72a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:31:08 +0200 Subject: [PATCH 266/366] docs: update changelog and header for version v2.0.0-beta2 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 762f2e0..19a9500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [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 From b2c68d5aac435fbefe8e820e8bf48e4b068fb6ff Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:44:21 +0200 Subject: [PATCH 267/366] refactor: update createVendor and checkVendor functions to accept JsonDocument payload --- src/api.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index c2e6c17..1a68515 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -603,7 +603,7 @@ bool updateSpoolBambuData(String payload) { } // #### Brand Filament -uint16_t createVendor(String vendor) { +uint16_t createVendor(const JsonDocument& payload) { oledShowProgressBar(2, 5, "New Brand", "Create new Vendor"); // Create new vendor in Spoolman database using task system @@ -617,9 +617,25 @@ uint16_t createVendor(String vendor) { // Create JSON payload for vendor creation JsonDocument vendorDoc; - vendorDoc["name"] = vendor; + vendorDoc["name"] = payload["b"].as(); vendorDoc["comment"] = "automatically generated"; - vendorDoc["external_id"] = vendor; + + // 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["external_id"] = externalId; String vendorPayload; serializeJson(vendorDoc, vendorPayload); @@ -668,13 +684,13 @@ uint16_t createVendor(String vendor) { return createdVendorId; } -uint16_t checkVendor(String vendor) { +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 = vendor; + String vendorName = payload["b"].as(); vendorName.trim(); vendorName.replace(" ", "+"); String spoolsUrl = spoolmanUrl + apiUrl + "/vendor?name=" + vendorName; @@ -716,7 +732,7 @@ uint16_t checkVendor(String vendor) { // Check if vendor was found if (foundVendorId == 0) { Serial.println("Vendor not found, creating new vendor..."); - uint16_t vendorId = createVendor(vendor); + uint16_t vendorId = createVendor(payload); if (vendorId == 0) { Serial.println("Failed to create vendor, returning 0."); return 0; // Failed to create vendor @@ -725,7 +741,7 @@ uint16_t checkVendor(String vendor) { return vendorId; } } else { - Serial.println("Vendor found: " + vendor); + Serial.println("Vendor found: " + payload["b"].as()); Serial.print("Vendor ID: "); Serial.println(foundVendorId); return foundVendorId; @@ -966,7 +982,7 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo } bool createBrandFilament(JsonDocument& payload, String uidString) { - uint16_t vendorId = checkVendor(payload["b"].as()); + uint16_t vendorId = checkVendor(payload); if (vendorId == 0) { Serial.println("ERROR: Failed to create/find vendor"); return false; From ba226027678b6e63c710768b03b7f068d1cc0392 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:44:33 +0200 Subject: [PATCH 268/366] docs: update platformio.ini for beta version v2.0.0-beta3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b060254..ee9dc47 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta2" +version = "2.0.0-beta3" to_old_version = "2.0.0" ## From 480e2da23ebafacad2355c515f8324474e9ea97e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:44:33 +0200 Subject: [PATCH 269/366] docs: update changelog and header for version v2.0.0-beta3 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19a9500..2cd88bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 2a4f8bb679b88f2dde6a63612dd78ec56882ad6f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:45:16 +0200 Subject: [PATCH 270/366] fix: update to_old_version in platformio.ini to reflect correct previous version --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ee9dc47..4ec348e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,7 +10,7 @@ [common] version = "2.0.0-beta3" -to_old_version = "2.0.0" +to_old_version = "1.5.10" ## [env:esp32dev] From 7f6bce1699d135af0cf12ed3522d54fa3f74396e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:56:20 +0200 Subject: [PATCH 271/366] fix: update createVendor function to use external_id as comment instead of static text --- src/api.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 1a68515..a93c33f 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -618,7 +618,6 @@ uint16_t createVendor(const JsonDocument& payload) { // Create JSON payload for vendor creation JsonDocument vendorDoc; vendorDoc["name"] = payload["b"].as(); - vendorDoc["comment"] = "automatically generated"; // Extract domain from URL if present, otherwise use brand name String externalId = ""; @@ -635,7 +634,7 @@ uint16_t createVendor(const JsonDocument& payload) { } else { externalId = payload["b"].as(); } - vendorDoc["external_id"] = externalId; + vendorDoc["comment"] = externalId; String vendorPayload; serializeJson(vendorDoc, vendorPayload); From 92155605586fc9b10a1f448d3428219d03b6362b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:57:41 +0200 Subject: [PATCH 272/366] docs: update platformio.ini for beta version v2.0.0-beta4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4ec348e..8fd79d1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta3" +version = "2.0.0-beta4" to_old_version = "1.5.10" ## From f28b34e4272e9ebb20c8f64d26593f2878e85f46 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Fri, 29 Aug 2025 18:57:42 +0200 Subject: [PATCH 273/366] docs: update changelog and header for version v2.0.0-beta4 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd88bb..c66f4aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [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 From a35f15eca5d8b135b88e02a7c3097da40cddc9c7 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 08:25:52 +0200 Subject: [PATCH 274/366] fix: call scale.tare() in setup after starting scale --- src/main.cpp | 1 + src/scale.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fd12e8c..16fa7ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,7 @@ void setup() { // Scale start_scale(touchSensorConnected); + scale.tare(); // WDT initialisieren mit 10 Sekunden Timeout bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus diff --git a/src/scale.cpp b/src/scale.cpp index 3ee71c6..f9d652e 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -122,8 +122,8 @@ void start_scale(bool touchSensorConnected) { } scale.set_scale(calibrationValue); - vTaskDelay(pdMS_TO_TICKS(5000)); - scale.tare(); + //vTaskDelay(pdMS_TO_TICKS(5000)); + //scale.tare(); // Display Gewicht oledShowWeight(0); From 5666a58da2c5f0efca2f34e74654fbbeed370225 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 08:25:58 +0200 Subject: [PATCH 275/366] docs: update platformio.ini for beta version v2.0.0-beta5 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 8fd79d1..49418ea 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta4" +version = "2.0.0-beta5" to_old_version = "1.5.10" ## From bc51956793895b10901fb84eb1d34571d9266757 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 08:25:58 +0200 Subject: [PATCH 276/366] docs: update changelog and header for version v2.0.0-beta5 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c66f4aa..03a2b1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [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 From 9b362b3c737f798b372fb8c1619cbf7f270da471 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 08:52:45 +0200 Subject: [PATCH 277/366] BREAKING CHANGE: Handling of Spools with Tags from Vendors. fix: improve get_last_tag function to handle non-beta tags and fallback to newest tag --- scripts/update_changelog.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index 5a9b732..aa48399 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -14,10 +14,27 @@ 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 From d5d7358f58513950fab29d55e797907c2a91141d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 08:54:40 +0200 Subject: [PATCH 278/366] fix: enhance commit categorization for breaking changes --- scripts/update_changelog.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index aa48399..bb6b602 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -41,7 +41,12 @@ def get_last_tag(): 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']): + + # 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' @@ -51,6 +56,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': [] @@ -72,7 +78,9 @@ def get_changes_from_git(): 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() + 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: From 79eacae22567c8ad0304a1f2d608450463bf27f1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 09:27:57 +0200 Subject: [PATCH 279/366] feat: implement robust page reading and safe tag detection with error recovery --- src/nfc.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 13db9bd..3a7ec60 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -1678,9 +1678,75 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { } } +// 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; +} + +// 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(;;) { + // 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) { @@ -1691,7 +1757,8 @@ 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); @@ -1708,9 +1775,9 @@ void scanRfidTask(void * parameter) { oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag"); - // Wait 1 second after tag detection to stabilize connection - Serial.println("Tag detected, waiting 1 second for stabilization..."); - vTaskDelay(1000 / 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 = ""; @@ -1753,9 +1820,10 @@ void scanRfidTask(void * parameter) { 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 @@ -1767,8 +1835,8 @@ void scanRfidTask(void * parameter) { yield(); esp_task_wdt_reset(); - // Increased delay to ensure stable reading - vTaskDelay(pdMS_TO_TICKS(5)); // Increased from 1ms to 5ms + // Reduced delay for faster reading + vTaskDelay(pdMS_TO_TICKS(2)); // Reduced from 5ms to 2ms } Serial.println("Tag reading completed, starting NDEF decode..."); @@ -1815,10 +1883,13 @@ void scanRfidTask(void * parameter) { Serial.println("Tag nach erfolgreichem Lesen entfernt - bereit für nächsten Tag"); } - // Add a longer pause after successful reading to prevent immediate re-reading + // Add a pause after successful reading to prevent immediate re-reading if (nfcReaderState == NFC_READ_SUCCESS) { - Serial.println("Tag erfolgreich gelesen - warte 5 Sekunden vor nächstem Scan"); - vTaskDelay(5000 / portTICK_PERIOD_MS); // 5 second pause + 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 From dfe9e4dbe91a0615618f9e62f3c52231dbaf9be8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 09:28:09 +0200 Subject: [PATCH 280/366] docs: update platformio.ini for beta version v2.0.0-beta6 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 49418ea..65fe54e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta5" +version = "2.0.0-beta6" to_old_version = "1.5.10" ## From 00b9bc08af8c3f616deb5e0494db4cbebcc618d8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 09:28:10 +0200 Subject: [PATCH 281/366] docs: update changelog and header for version v2.0.0-beta6 --- CHANGELOG.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03a2b1d..2abd74c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,102 @@ # Changelog +## [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 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 From 10aeb9bc5206074d4f252c06e3573b21dc72a1ee Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 09:28:33 +0200 Subject: [PATCH 282/366] docs: update changelog and header for version v2.0.0-beta6 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2abd74c..2b0c2b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - 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 @@ -96,7 +97,6 @@ - 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 From 4d84169b293ebc4b6100af145b30b2626650ddce Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:09:22 +0200 Subject: [PATCH 283/366] feat: enhance NFC tag reading with robust error recovery and JSON optimization for fast-path detection --- src/nfc.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index 3a7ec60..dde0012 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -1285,10 +1285,11 @@ bool quickSpoolIdCheck(String uidString) { memset(ndefData, 0, 20); for (uint8_t page = 4; page < 9; page++) { - if (!nfc.ntag2xx_ReadPage(page, ndefData + (page - 4) * 4)) { - Serial.print("Failed to read page "); - Serial.println(page); - return false; // Fall back to full read + 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 } } @@ -1358,10 +1359,11 @@ bool quickSpoolIdCheck(String uidString) { memset(extraData, 0, 16); for (uint8_t page = 9; page < 13; page++) { - if (!nfc.ntag2xx_ReadPage(page, extraData + (page - 9) * 4)) { - Serial.print("Failed to read additional page "); - Serial.println(page); - return false; + 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 } } @@ -1655,10 +1657,60 @@ void writeJsonToTag(void *parameter) { 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) { @@ -1762,6 +1814,11 @@ void scanRfidTask(void * parameter) { 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) { @@ -1857,6 +1914,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 @@ -1864,6 +1924,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"); } } From 2e3fc197417d298c200eb2a5f2d7035a68c63518 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:09:28 +0200 Subject: [PATCH 284/366] docs: update platformio.ini for beta version v2.0.0-beta7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 65fe54e..dd64eca 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta6" +version = "2.0.0-beta7" to_old_version = "1.5.10" ## From b9e488d675a08e5c3395501d787c14d8bd6d09b3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:09:28 +0200 Subject: [PATCH 285/366] docs: update changelog and header for version v2.0.0-beta7 --- CHANGELOG.md | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b0c2b8..ad426cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,106 @@ # Changelog +## [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 From 7bf9868d79e25da2b7b9ada8d1bf97f7333f9798 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:17:30 +0200 Subject: [PATCH 286/366] feat: implement robust page reading with error recovery for NFC tags --- src/nfc.cpp | 62 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index dde0012..f4c5e5a 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -108,6 +108,37 @@ bool formatNdefTag() { 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 @@ -1730,37 +1761,6 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { } } -// 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; -} - // Safe tag detection with manual retry logic and short timeouts bool safeTagDetection(uint8_t* uid, uint8_t* uidLength) { const int MAX_ATTEMPTS = 3; From f664e859337e98269435aa3ab06a15b554f40cf6 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:17:37 +0200 Subject: [PATCH 287/366] docs: update platformio.ini for beta version v2.0.0-beta8 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index dd64eca..597b7bb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta7" +version = "2.0.0-beta8" to_old_version = "1.5.10" ## From 63fafa2463938d64775339a770a1e9372b683a55 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 10:17:37 +0200 Subject: [PATCH 288/366] docs: update changelog and header for version v2.0.0-beta8 --- CHANGELOG.md | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad426cd..828d597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,109 @@ # Changelog +## [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 From 6502bb7185c26d11e6657a3f47312726567d174b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:08:56 +0200 Subject: [PATCH 289/366] feat: add handling for successful NFC tag writes to send weight to Spoolman without auto-sending to Bambu --- src/main.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 16fa7ba..c63945a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -250,6 +250,25 @@ void loop() { } } + // 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 (updateSpoolWeight(activeSpoolId, weight)) + { + 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(autoSetToBambuSpoolId); From e6a5cb29a9ecb056616ad73481c91fed7e562e50 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:09:04 +0200 Subject: [PATCH 290/366] docs: update platformio.ini for beta version v2.0.0-beta9 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 597b7bb..947da80 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta8" +version = "2.0.0-beta9" to_old_version = "1.5.10" ## From 458bd2e67b4c5721d25f145a433c8e6c168de335 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:09:04 +0200 Subject: [PATCH 291/366] docs: update changelog and header for version v2.0.0-beta9 --- CHANGELOG.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 828d597..81a52b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,112 @@ # Changelog +## [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 From 602642c20352451fc0e5262c69dd03f9bfaa0529 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:27:22 +0200 Subject: [PATCH 292/366] feat: add fast-path JSON reading for web interface display --- src/nfc.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nfc.h | 1 + 2 files changed, 76 insertions(+) diff --git a/src/nfc.cpp b/src/nfc.cpp index f4c5e5a..c2a6a62 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -1299,6 +1299,61 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { 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 @@ -1436,6 +1491,14 @@ bool quickSpoolIdCheck(String uidString) { 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; @@ -1483,6 +1546,14 @@ bool quickSpoolIdCheck(String uidString) { 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; @@ -1529,6 +1600,10 @@ void writeJsonToTag(void *parameter) { // 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 = ""; diff --git a/src/nfc.h b/src/nfc.h index 3633772..57381e2 100644 --- a/src/nfc.h +++ b/src/nfc.h @@ -17,6 +17,7 @@ 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; From 0daa3a148b73ff25cb79dcc087ad41c549ffbafc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:27:29 +0200 Subject: [PATCH 293/366] docs: update platformio.ini for beta version v2.0.0-beta10 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 947da80..1367970 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta9" +version = "2.0.0-beta10" to_old_version = "1.5.10" ## From bf63ecd5944e2b879a33308b6369ab4e8070d995 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 11:27:29 +0200 Subject: [PATCH 294/366] docs: update changelog and header for version v2.0.0-beta10 --- CHANGELOG.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81a52b7..8f5c686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,115 @@ # Changelog +## [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 From 8d82e221b50ed2c33ed9f80b9c00d4e019d3357d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 14:55:42 +0200 Subject: [PATCH 295/366] feat: implement weight stabilization functions and improve tare handling --- src/scale.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++-------- src/scale.h | 6 ++ 2 files changed, 145 insertions(+), 24 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index f9d652e..0978af2 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -13,6 +13,19 @@ TaskHandle_t ScaleTask; int16_t weight = 0; +// Weight stabilization variables +#define MOVING_AVERAGE_SIZE 20 // Number of samples for moving average +#define LOW_PASS_ALPHA 0.15f // Low-pass filter coefficient (0.1-0.2 works well) +#define DISPLAY_THRESHOLD 0.5f // Only update display if change > 0.5g +#define MEASUREMENT_INTERVAL_MS 50 // Measurement interval in milliseconds + +float weightBuffer[MOVING_AVERAGE_SIZE]; +uint8_t bufferIndex = 0; +bool bufferFilled = false; +float filteredWeight = 0.0f; +int16_t lastDisplayedWeight = 0; +unsigned long lastMeasurementTime = 0; + uint8_t weigthCouterToApi = 0; uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; @@ -21,6 +34,77 @@ 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; + + // 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); + + // Only update displayed weight if change is significant + if (abs(newWeight - lastDisplayedWeight) >= DISPLAY_THRESHOLD) { + lastDisplayedWeight = newWeight; + return newWeight; + } + + return weight; // Return current weight if change is too small +} + // ##### Funktionen für Waage ##### uint8_t setAutoTare(bool autoTareValue) { Serial.print("Set AutoTare to "); @@ -39,6 +123,7 @@ uint8_t setAutoTare(bool autoTareValue) { uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); + resetWeightFilter(); // Reset stabilization filter after tare return 1; } @@ -48,37 +133,63 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); + // 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 automatisch Taren, wenn zu lange Abweichung + if (autoTare && scale_tare_counter >= 5) + { + Serial.println("Auto Tare scale"); + scale.tare(); + resetWeightFilter(); // Reset filter after auto tare + scale_tare_counter = 0; + } - // 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; - } + // Waage manuell Taren + if (scaleTareRequest == true) + { + 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; + } - // Only update weight if median changed more than 1 - int16_t newWeight = round(scale.get_units()); - if(abs(weight-newWeight) > 1){ - weight = newWeight; + // 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 + if (stabilizedWeight != weight) { + weight = stabilizedWeight; + + // Debug output for monitoring (can be removed in production) + static unsigned long lastDebugTime = 0; + if (currentTime - lastDebugTime > 1000) { // Print every second + Serial.printf("Raw: %.2f, Filtered: %.2f, Final: %d\n", + rawWeight, filteredWeight, weight); + lastDebugTime = currentTime; + } + } + + lastMeasurementTime = currentTime; } } - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(10)); // Shorter delay for more responsive loop } } @@ -125,6 +236,9 @@ void start_scale(bool touchSensorConnected) { //vTaskDelay(pdMS_TO_TICKS(5000)); //scale.tare(); + // Initialize weight stabilization filter + resetWeightFilter(); + // Display Gewicht oledShowWeight(0); @@ -209,6 +323,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)); diff --git a/src/scale.h b/src/scale.h index c38583a..35ededa 100644 --- a/src/scale.h +++ b/src/scale.h @@ -9,6 +9,12 @@ 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); + extern HX711 scale; extern int16_t weight; extern uint8_t weigthCouterToApi; From 6451d91c5914873f54caa8125800d014d3dd39dd Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 14:55:53 +0200 Subject: [PATCH 296/366] docs: update platformio.ini for beta version v2.0.0-beta11 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1367970..a44d076 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta10" +version = "2.0.0-beta11" to_old_version = "1.5.10" ## From 0bf383ecd99fbe8031557e35dbdfd6edeb4ae6c9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 14:55:54 +0200 Subject: [PATCH 297/366] docs: update changelog and header for version v2.0.0-beta11 --- CHANGELOG.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f5c686..a6640b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,118 @@ # Changelog +## [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 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 From 693ee839e5ecfd73f14471c79beb143bcf5aea86 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 14:56:09 +0200 Subject: [PATCH 298/366] docs: update changelog and header for version v2.0.0-beta11 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6640b7..594b446 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - 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 @@ -112,7 +113,6 @@ - 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 From 6cccf3d60363132c0d5846131b828a9adf4bf675 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:43:51 +0200 Subject: [PATCH 299/366] feat: enhance weight processing with filtered display and API stability checks --- src/main.cpp | 4 +++- src/scale.cpp | 46 ++++++++++++++++++++++++++++++++++------------ src/scale.h | 1 + 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c63945a..ac4b6af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -178,9 +178,11 @@ void loop() { // Ausgabe der Waage auf Display if(pauseMainTask == 0) { + // 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; } diff --git a/src/scale.cpp b/src/scale.cpp index 0978af2..0f033f2 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -17,6 +17,7 @@ int16_t weight = 0; #define MOVING_AVERAGE_SIZE 20 // Number of samples for moving average #define LOW_PASS_ALPHA 0.15f // Low-pass filter coefficient (0.1-0.2 works well) #define DISPLAY_THRESHOLD 0.5f // Only update display if change > 0.5g +#define API_THRESHOLD 2.0f // Only trigger API actions if change > 2g #define MEASUREMENT_INTERVAL_MS 50 // Measurement interval in milliseconds float weightBuffer[MOVING_AVERAGE_SIZE]; @@ -24,6 +25,7 @@ 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 weigthCouterToApi = 0; @@ -44,6 +46,7 @@ void resetWeightFilter() { 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++) { @@ -96,13 +99,31 @@ int16_t processWeightReading(float rawWeight) { // Round to nearest gram int16_t newWeight = round(smoothedWeight); - // Only update displayed weight if change is significant + // Update displayed weight if display threshold is reached if (abs(newWeight - lastDisplayedWeight) >= DISPLAY_THRESHOLD) { lastDisplayedWeight = newWeight; - return newWeight; } - return weight; // Return current weight if change is too small + // 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; + + Serial.printf("Stable weight change detected: %d -> %d (diff: %d)\n", + weight, newWeight, abs(newWeight - weight)); + } + + 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 ##### @@ -172,17 +193,18 @@ void scale_loop(void * parameter) { // Process weight with stabilization int16_t stabilizedWeight = processWeightReading(rawWeight); - // Update global weight variable only if it changed + // Update global weight variable only if it changed significantly (for API actions) if (stabilizedWeight != weight) { weight = stabilizedWeight; - - // Debug output for monitoring (can be removed in production) - static unsigned long lastDebugTime = 0; - if (currentTime - lastDebugTime > 1000) { // Print every second - Serial.printf("Raw: %.2f, Filtered: %.2f, Final: %d\n", - rawWeight, filteredWeight, weight); - lastDebugTime = currentTime; - } + Serial.printf("API weight updated: %d\n", weight); + } + + // Debug output for monitoring (can be removed in production) + static unsigned long lastDebugTime = 0; + if (currentTime - lastDebugTime > 2000) { // Print every 2 seconds + Serial.printf("Raw: %.2f, Filtered: %.2f, Display: %d, API: %d\n", + rawWeight, filteredWeight, lastDisplayedWeight, weight); + lastDebugTime = currentTime; } lastMeasurementTime = currentTime; diff --git a/src/scale.h b/src/scale.h index 35ededa..5514544 100644 --- a/src/scale.h +++ b/src/scale.h @@ -14,6 +14,7 @@ void resetWeightFilter(); float calculateMovingAverage(); float applyLowPassFilter(float newValue); int16_t processWeightReading(float rawWeight); +int16_t getFilteredDisplayWeight(); extern HX711 scale; extern int16_t weight; From 039a29fa3c6ec74d522250d5aee153e45249dc0d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:43:59 +0200 Subject: [PATCH 300/366] docs: update platformio.ini for beta version v2.0.0-beta12 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index a44d076..1da01d3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta11" +version = "2.0.0-beta12" to_old_version = "1.5.10" ## From 7a15424bc75ede5cd18bce8a63aa020ade4f1203 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:43:59 +0200 Subject: [PATCH 301/366] docs: update changelog and header for version v2.0.0-beta12 --- CHANGELOG.md | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594b446..70513e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,122 @@ # Changelog +## [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 From 7f4b3b8d90a31adc303c83238f3c6d1522fd5867 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:52:38 +0200 Subject: [PATCH 302/366] refactor: optimize weight stabilization parameters for improved responsiveness --- src/scale.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index 0f033f2..3cf3e59 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -14,11 +14,11 @@ TaskHandle_t ScaleTask; int16_t weight = 0; // Weight stabilization variables -#define MOVING_AVERAGE_SIZE 20 // Number of samples for moving average -#define LOW_PASS_ALPHA 0.15f // Low-pass filter coefficient (0.1-0.2 works well) -#define DISPLAY_THRESHOLD 0.5f // Only update display if change > 0.5g -#define API_THRESHOLD 2.0f // Only trigger API actions if change > 2g -#define MEASUREMENT_INTERVAL_MS 50 // Measurement interval in milliseconds +#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; @@ -110,9 +110,6 @@ int16_t processWeightReading(float rawWeight) { if (abs(newWeight - lastStableWeight) >= API_THRESHOLD) { lastStableWeight = newWeight; weightToReturn = newWeight; - - Serial.printf("Stable weight change detected: %d -> %d (diff: %d)\n", - weight, newWeight, abs(newWeight - weight)); } return weightToReturn; @@ -196,14 +193,11 @@ void scale_loop(void * parameter) { // Update global weight variable only if it changed significantly (for API actions) if (stabilizedWeight != weight) { weight = stabilizedWeight; - Serial.printf("API weight updated: %d\n", weight); } // Debug output for monitoring (can be removed in production) static unsigned long lastDebugTime = 0; if (currentTime - lastDebugTime > 2000) { // Print every 2 seconds - Serial.printf("Raw: %.2f, Filtered: %.2f, Display: %d, API: %d\n", - rawWeight, filteredWeight, lastDisplayedWeight, weight); lastDebugTime = currentTime; } From 6172242f2436caa1670502b9f02b277cec937cf1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:52:46 +0200 Subject: [PATCH 303/366] docs: update platformio.ini for beta version v2.0.0-beta13 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 1da01d3..a9e8097 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta12" +version = "2.0.0-beta13" to_old_version = "1.5.10" ## From 6800c88bb215a6af08902253bc22533f920224e4 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 15:52:46 +0200 Subject: [PATCH 304/366] docs: update changelog and header for version v2.0.0-beta13 --- CHANGELOG.md | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70513e8..1a1eeb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,125 @@ # Changelog +## [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 From afde3f5f81eddd36a67e520be79537e801b6c510 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 16:40:01 +0200 Subject: [PATCH 305/366] fix: add timeout handling and error states for vendor and filament operations --- src/api.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index a93c33f..7d213b0 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -325,14 +325,25 @@ 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)); @@ -676,8 +687,20 @@ uint16_t createVendor(const JsonDocument& payload) { // Wait for task completion and return the created vendor ID // Note: createdVendorId will be set by sendToApi when response is received - while(createdVendorId == 65535) { + uint16_t timeout_counter = 0; + const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) + + while(createdVendorId == 65535 && timeout_counter < max_timeout) { vTaskDelay(50 / portTICK_PERIOD_MS); + timeout_counter++; + } + + // Check if we got a valid response or timed out + if (createdVendorId == 65535) { + Serial.println("ERROR: Timeout waiting for vendor creation response"); + createdVendorId = 0; // Set to error state + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; } return createdVendorId; @@ -723,9 +746,21 @@ uint16_t checkVendor(const JsonDocument& payload) { ); // Wait until foundVendorId is updated by the API response (not 65535 anymore) - while (foundVendorId == 65535) + uint16_t timeout_counter = 0; + const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) + + while (foundVendorId == 65535 && timeout_counter < max_timeout) { vTaskDelay(50 / portTICK_PERIOD_MS); + timeout_counter++; + } + + // Check for timeout + if (foundVendorId == 65535) { + Serial.println("ERROR: Timeout waiting for vendor check response"); + foundVendorId = 0; // Set to error state + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; } // Check if vendor was found @@ -831,8 +866,26 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // Wait for task completion and return the created filament ID // Note: createdFilamentId will be set by sendToApi when response is received - while(createdFilamentId == 65535) { + uint16_t timeout_counter = 0; + const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) + + while(createdFilamentId == 65535 && timeout_counter < max_timeout) { vTaskDelay(50 / portTICK_PERIOD_MS); + timeout_counter++; + } + + // Check if we got a valid response or timed out + if (createdFilamentId == 65535) { + Serial.println("ERROR: Timeout waiting for filament creation response"); + createdFilamentId = 0; // Set to error state + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; + } + + if (createdFilamentId == 0) { + Serial.println("ERROR: Filament creation failed (HTTP error)"); + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; } return createdFilamentId; @@ -869,8 +922,20 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { ); // Wait until foundFilamentId is updated by the API response (not 65535 anymore) - while (foundFilamentId == 65535) { + uint16_t timeout_counter = 0; + const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) + + while (foundFilamentId == 65535 && timeout_counter < max_timeout) { vTaskDelay(50 / portTICK_PERIOD_MS); + timeout_counter++; + } + + // Check for timeout + if (foundFilamentId == 65535) { + Serial.println("ERROR: Timeout waiting for filament check response"); + foundFilamentId = 0; // Set to error state + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; } // Check if filament was found @@ -949,8 +1014,26 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Wait for task completion and return the created spool ID // Note: createdSpoolId will be set by sendToApi when response is received - while(createdSpoolId == 65535) { + uint16_t timeout_counter = 0; + const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) + + while(createdSpoolId == 65535 && timeout_counter < max_timeout) { vTaskDelay(50 / portTICK_PERIOD_MS); + timeout_counter++; + } + + // Check if we got a valid response or timed out + if (createdSpoolId == 65535) { + Serial.println("ERROR: Timeout waiting for spool creation response"); + createdSpoolId = 0; // Set to error state + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; + } + + if (createdSpoolId == 0) { + Serial.println("ERROR: Spool creation failed (HTTP error)"); + nfcReaderState = NFC_IDLE; // Reset NFC state + return 0; } // Write data to tag with startWriteJsonToTag From 5cc58927a695d72ba2bcdf7c1baf98fea11452c5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 16:47:18 +0200 Subject: [PATCH 306/366] feat: implement retry mechanism and timeout handling for API requests --- src/api.cpp | 166 +++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 94 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 7d213b0..86d97df 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -124,28 +124,69 @@ void sendToApi(void *parameter) { String octoToken = params->octoToken; bool triggerWeightUpdate = params->triggerWeightUpdate; String spoolIdForWeight = params->spoolIdForWeight; - uint16_t weightValue = params->weightValue; + 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 if (httpType == "GET") httpCode = http.GET(); - 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) { + // 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()); @@ -225,10 +266,9 @@ void sendToApi(void *parameter) { } else if (httpCode == HTTP_CODE_CREATED) { Serial.println("Spoolman erfolgreich erstellt"); - // Parse response for created resources - String payload = http.getString(); + // Parse response for created resources 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()); @@ -280,14 +320,17 @@ void sendToApi(void *parameter) { Serial.println(weightPayload); // Execute weight update - http.begin(weightUrl); - http.addHeader("Content-Type", "application/json"); + HTTPClient weightHttp; + weightHttp.setReuse(false); + weightHttp.setTimeout(HTTP_TIMEOUT_MS); + weightHttp.begin(weightUrl); + weightHttp.addHeader("Content-Type", "application/json"); - int weightHttpCode = http.PUT(weightPayload); + int weightHttpCode = weightHttp.PUT(weightPayload); if (weightHttpCode == HTTP_CODE_OK) { Serial.println("Weight update successful"); - String weightResponse = http.getString(); + String weightResponse = weightHttp.getString(); JsonDocument weightResponseDoc; DeserializationError weightError = deserializeJson(weightResponseDoc, weightResponse); @@ -310,6 +353,7 @@ void sendToApi(void *parameter) { oledShowProgressBar(1, 1, "Failure!", "Weight update"); } + weightHttp.end(); weightDoc.clear(); } } else { @@ -351,7 +395,6 @@ void sendToApi(void *parameter) { nfcReaderState = NFC_IDLE; // Reset NFC state to allow retry } - http.end(); vTaskDelay(50 / portTICK_PERIOD_MS); // Speicher freigeben @@ -687,20 +730,8 @@ uint16_t createVendor(const JsonDocument& payload) { // Wait for task completion and return the created vendor ID // Note: createdVendorId will be set by sendToApi when response is received - uint16_t timeout_counter = 0; - const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) - - while(createdVendorId == 65535 && timeout_counter < max_timeout) { + while(createdVendorId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); - timeout_counter++; - } - - // Check if we got a valid response or timed out - if (createdVendorId == 65535) { - Serial.println("ERROR: Timeout waiting for vendor creation response"); - createdVendorId = 0; // Set to error state - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; } return createdVendorId; @@ -746,21 +777,9 @@ uint16_t checkVendor(const JsonDocument& payload) { ); // Wait until foundVendorId is updated by the API response (not 65535 anymore) - uint16_t timeout_counter = 0; - const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) - - while (foundVendorId == 65535 && timeout_counter < max_timeout) + while (foundVendorId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); - timeout_counter++; - } - - // Check for timeout - if (foundVendorId == 65535) { - Serial.println("ERROR: Timeout waiting for vendor check response"); - foundVendorId = 0; // Set to error state - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; } // Check if vendor was found @@ -866,26 +885,8 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { // Wait for task completion and return the created filament ID // Note: createdFilamentId will be set by sendToApi when response is received - uint16_t timeout_counter = 0; - const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) - - while(createdFilamentId == 65535 && timeout_counter < max_timeout) { + while(createdFilamentId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); - timeout_counter++; - } - - // Check if we got a valid response or timed out - if (createdFilamentId == 65535) { - Serial.println("ERROR: Timeout waiting for filament creation response"); - createdFilamentId = 0; // Set to error state - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; - } - - if (createdFilamentId == 0) { - Serial.println("ERROR: Filament creation failed (HTTP error)"); - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; } return createdFilamentId; @@ -922,20 +923,8 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) { ); // Wait until foundFilamentId is updated by the API response (not 65535 anymore) - uint16_t timeout_counter = 0; - const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) - - while (foundFilamentId == 65535 && timeout_counter < max_timeout) { + while (foundFilamentId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); - timeout_counter++; - } - - // Check for timeout - if (foundFilamentId == 65535) { - Serial.println("ERROR: Timeout waiting for filament check response"); - foundFilamentId = 0; // Set to error state - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; } // Check if filament was found @@ -1014,24 +1003,13 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo // Wait for task completion and return the created spool ID // Note: createdSpoolId will be set by sendToApi when response is received - uint16_t timeout_counter = 0; - const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms) - - while(createdSpoolId == 65535 && timeout_counter < max_timeout) { + while(createdSpoolId == 65535) { vTaskDelay(50 / portTICK_PERIOD_MS); - timeout_counter++; - } - - // Check if we got a valid response or timed out - if (createdSpoolId == 65535) { - Serial.println("ERROR: Timeout waiting for spool creation response"); - createdSpoolId = 0; // Set to error state - nfcReaderState = NFC_IDLE; // Reset NFC state - return 0; } + // Check if spool creation was successful if (createdSpoolId == 0) { - Serial.println("ERROR: Spool creation failed (HTTP error)"); + Serial.println("ERROR: Spool creation failed"); nfcReaderState = NFC_IDLE; // Reset NFC state return 0; } From bec769e95a857a8403cf622b8c9011193e3c0827 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 16:47:24 +0200 Subject: [PATCH 307/366] docs: update platformio.ini for beta version v2.0.0-beta14 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index a9e8097..d2e6ebc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta13" +version = "2.0.0-beta14" to_old_version = "1.5.10" ## From e537c6ec0744d8e857b263eb272fe3914fb25241 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 16:47:24 +0200 Subject: [PATCH 308/366] docs: update changelog and header for version v2.0.0-beta14 --- CHANGELOG.md | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a1eeb6..663d1cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,129 @@ # Changelog +## [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 From ab005b3dd1a161555dd8775971fb1009cdb08964 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 17:03:17 +0200 Subject: [PATCH 309/366] docs: update platformio.ini for version v2.0.1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index d2e6ebc..d0ddcbe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.0-beta14" +version = "2.0.1" to_old_version = "1.5.10" ## From f2b38a5a99c307c7392e18f9c18365ad91f054e5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 17:03:17 +0200 Subject: [PATCH 310/366] docs: update changelog and header for version v2.0.1 --- CHANGELOG.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 663d1cd..921cd61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,131 @@ # Changelog +## [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 From 9ae9e80dcdd5f47db20a2093842a17b9cdb55ea9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 30 Aug 2025 18:13:42 +0200 Subject: [PATCH 311/366] docs: add German and English wiki documentation --- .gitignore | 3 +- WIKI_DE.md | 468 +++++++++++++++++++++++++++++++++ WIKI_EN.md | 746 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1216 insertions(+), 1 deletion(-) create mode 100644 WIKI_DE.md create mode 100644 WIKI_EN.md diff --git a/.gitignore b/.gitignore index a6e7ff5..7709e53 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ _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/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 From 87288e606b0632c66260921a8cc540d4f01efa8e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 1 Sep 2025 13:33:12 +0200 Subject: [PATCH 312/366] refactor: remove redundant tare calls in setup and start_scale functions --- src/main.cpp | 1 - src/scale.cpp | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ac4b6af..0864f16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,7 +59,6 @@ void setup() { // Scale start_scale(touchSensorConnected); - scale.tare(); // WDT initialisieren mit 10 Sekunden Timeout bool panic = true; // Wenn true, löst ein WDT-Timeout einen System-Panik aus diff --git a/src/scale.cpp b/src/scale.cpp index 3cf3e59..a5519f1 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -250,7 +250,6 @@ void start_scale(bool touchSensorConnected) { scale.set_scale(calibrationValue); //vTaskDelay(pdMS_TO_TICKS(5000)); - //scale.tare(); // Initialize weight stabilization filter resetWeightFilter(); @@ -258,6 +257,9 @@ void start_scale(bool touchSensorConnected) { // Display Gewicht oledShowWeight(0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + scale.tare(); + Serial.println("starte Scale Task"); BaseType_t result = xTaskCreatePinnedToCore( scale_loop, /* Function to implement the task */ From 66eef2242b46444a88f73f2dbbd09e98471cb307 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 1 Sep 2025 13:39:41 +0200 Subject: [PATCH 313/366] feat: add weight check and update spool weight in writeJsonToTag function --- src/nfc.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/nfc.cpp b/src/nfc.cpp index c2a6a62..9e92b76 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -1650,7 +1650,30 @@ 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 } From 4cf3858d0a1a9349483bf79385dd44937c4da4d9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 1 Sep 2025 13:40:00 +0200 Subject: [PATCH 314/366] docs: update platformio.ini for version v2.0.2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index d0ddcbe..3216f02 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.1" +version = "2.0.2" to_old_version = "1.5.10" ## From 818094c36e3602454d18842fe83de45df3a369ef Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 1 Sep 2025 13:40:01 +0200 Subject: [PATCH 315/366] docs: update changelog and header for version v2.0.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 921cd61..f256b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [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 From cca0bd9dbe4ca3a43fc83bbb495dbafc73f77a65 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Mon, 1 Sep 2025 14:03:08 +0200 Subject: [PATCH 316/366] fix: reduce delay in start_scale function and reset weight after tare --- src/scale.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scale.cpp b/src/scale.cpp index a5519f1..9e2aa03 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -257,8 +257,10 @@ void start_scale(bool touchSensorConnected) { // Display Gewicht oledShowWeight(0); - vTaskDelay(1000 / portTICK_PERIOD_MS); + vTaskDelay(500 / portTICK_PERIOD_MS); scale.tare(); + vTaskDelay(500 / portTICK_PERIOD_MS); + weight = 0; Serial.println("starte Scale Task"); BaseType_t result = xTaskCreatePinnedToCore( From 1dba2b2f234be0740af8769ef977f130b646293e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:15:27 +0200 Subject: [PATCH 317/366] fix: reset weight counter logic and update spool ID in loop function --- src/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0864f16..b17fb23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -220,7 +220,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; @@ -272,7 +271,7 @@ void loop() { if(octoEnabled && sendOctoUpdate && spoolmanApiState == API_IDLE) { - updateSpoolOcto(autoSetToBambuSpoolId); + updateSpoolOcto(activeSpoolId.toInt()); sendOctoUpdate = false; } } From 9ec5bca652fcbca7477d79041f160428a1e425e1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:15:34 +0200 Subject: [PATCH 318/366] docs: update platformio.ini for beta version v2.0.2-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3216f02..b3e2b6d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2" +version = "2.0.2-beta1" to_old_version = "1.5.10" ## From 100328b1d68b749acf3bf4216a65c16bff40af1f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:15:34 +0200 Subject: [PATCH 319/366] docs: update changelog and header for version v2.0.2-beta1 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f256b56..c75a921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [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 From 0baa1d286eb055099ffa17aca711ae8e288c4689 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:36:34 +0200 Subject: [PATCH 320/366] feat: add updateOctoSpoolId for OctoPrint integration and change autoSetToBambuSpoolId type to uint16_t --- src/api.cpp | 1 + src/api.h | 1 + src/bambu.cpp | 2 +- src/bambu.h | 2 +- src/main.cpp | 6 +++++- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 86d97df..3129d20 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -21,6 +21,7 @@ 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; diff --git a/src/api.h b/src/api.h index 83a88c7..a8aac63 100644 --- a/src/api.h +++ b/src/api.h @@ -33,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); diff --git a/src/bambu.cpp b/src/bambu.cpp index 8eae33d..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; 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/main.cpp b/src/main.cpp index b17fb23..4cfe8d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -242,6 +242,10 @@ void loop() { { autoSetToBambuSpoolId = activeSpoolId.toInt(); } + if (octoEnabled) + { + updateOctoSpoolId = activeSpoolId.toInt(); + } } else { @@ -271,7 +275,7 @@ void loop() { if(octoEnabled && sendOctoUpdate && spoolmanApiState == API_IDLE) { - updateSpoolOcto(activeSpoolId.toInt()); + updateSpoolOcto(updateOctoSpoolId); sendOctoUpdate = false; } } From 0f63880d1f690438d071a2a755eac391973a1c99 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:36:38 +0200 Subject: [PATCH 321/366] docs: update platformio.ini for beta version v2.0.2-beta2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b3e2b6d..4aaa501 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta1" +version = "2.0.2-beta2" to_old_version = "1.5.10" ## From b80184bf23dea22e9dfd9055c94c8bbbfe0fcdaf Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:36:39 +0200 Subject: [PATCH 322/366] docs: update changelog and header for version v2.0.2-beta2 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c75a921..6a32af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [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 From 3a82175bb6c56f5c0e718b2afe7ed5c15224fb0b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:45:21 +0200 Subject: [PATCH 323/366] fix: correct tare scale function to set scaleTareRequest flag --- src/scale.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index 9e2aa03..42d0083 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -141,7 +141,7 @@ uint8_t setAutoTare(bool autoTareValue) { uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); - resetWeightFilter(); // Reset stabilization filter after tare + scaleTareRequest == true; return 1; } @@ -151,6 +151,7 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); + scaleTareRequest == true; // Initialize weight filter resetWeightFilter(); lastMeasurementTime = millis(); @@ -257,11 +258,6 @@ void start_scale(bool touchSensorConnected) { // Display Gewicht oledShowWeight(0); - vTaskDelay(500 / portTICK_PERIOD_MS); - scale.tare(); - vTaskDelay(500 / portTICK_PERIOD_MS); - weight = 0; - Serial.println("starte Scale Task"); BaseType_t result = xTaskCreatePinnedToCore( scale_loop, /* Function to implement the task */ From b4f1fc3b0a441e4ea5b2f11369ad2d3a0361e86b Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:45:33 +0200 Subject: [PATCH 324/366] docs: update platformio.ini for beta version v2.0.2-beta3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4aaa501..859d975 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta2" +version = "2.0.2-beta3" to_old_version = "1.5.10" ## From 77fbacc681eec5823737991099c7da9794cb6172 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 17:45:33 +0200 Subject: [PATCH 325/366] docs: update changelog and header for version v2.0.2-beta3 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a32af1..5a1b3c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [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 From 51335456e36e2bb59b2325f84110a0d693f64937 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:02:24 +0200 Subject: [PATCH 326/366] fix: reset weight filter after tare scale operation --- src/scale.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scale.cpp b/src/scale.cpp index 42d0083..021f071 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -141,6 +141,7 @@ uint8_t setAutoTare(bool autoTareValue) { uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); + resetWeightFilter(); scaleTareRequest == true; return 1; @@ -151,7 +152,7 @@ void scale_loop(void * parameter) { Serial.println("Scale Loop started"); Serial.println("++++++++++++++++++++++++++++++"); - scaleTareRequest == true; + //scaleTareRequest == true; // Initialize weight filter resetWeightFilter(); lastMeasurementTime = millis(); From 16c3a65cca0c6aaf3113fb3c4d34f2fddc544ccc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:02:29 +0200 Subject: [PATCH 327/366] docs: update platformio.ini for beta version v2.0.2-beta4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 859d975..9184ea4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta3" +version = "2.0.2-beta4" to_old_version = "1.5.10" ## From d9469eaa4257690151fb1908c1056e7e8b9f10b0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:02:29 +0200 Subject: [PATCH 328/366] docs: update changelog and header for version v2.0.2-beta4 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1b3c1..64f9a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [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 From 85cff3923cdabcb5ae394dc6f14286908974fc1f Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:15:13 +0200 Subject: [PATCH 329/366] fix: correct tare scale request handling in tareScale function --- src/scale.cpp | 1 - src/website.cpp | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index 021f071..095eee5 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -142,7 +142,6 @@ uint8_t tareScale() { Serial.println("Tare scale"); scale.tare(); resetWeightFilter(); - scaleTareRequest == true; return 1; } diff --git a/src/website.cpp b/src/website.cpp index 50d47f7..0ba3ac2 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -81,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") { From b4a06d0f2af3c9f14deb67fc416f9105d9c33a87 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:15:19 +0200 Subject: [PATCH 330/366] docs: update platformio.ini for beta version v2.0.2-beta5 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 9184ea4..87af69b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta4" +version = "2.0.2-beta5" to_old_version = "1.5.10" ## From 45a623cff65829cdcf8a637ba41c31a764b5ebb5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:15:19 +0200 Subject: [PATCH 331/366] docs: update changelog and header for version v2.0.2-beta5 --- CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64f9a81..0741d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [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 From 2b195ed9ea69e08d2dc6c4ef97f1a5bc54523605 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:23:36 +0200 Subject: [PATCH 332/366] fix: correct assignment operator in scale tare request handling --- src/website.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/website.cpp b/src/website.cpp index 0ba3ac2..0daf49f 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -81,7 +81,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp else if (doc["type"] == "scale") { uint8_t success = 0; if (doc["payload"] == "tare") { - scaleTareRequest == true; + scaleTareRequest = true; success = 1; //success = tareScale(); } From 5db80d367014a0a89308c940486caf52698a6207 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:24:32 +0200 Subject: [PATCH 333/366] fix: set scale tare request to true in setup function --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 4cfe8d9..81d0a0c 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 From 2ee60ce430955b397d5a5f509e1c1e16fd2ccc0c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:24:37 +0200 Subject: [PATCH 334/366] docs: update platformio.ini for beta version v2.0.2-beta6 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 87af69b..ca32a9b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta5" +version = "2.0.2-beta6" to_old_version = "1.5.10" ## From e74f6076b234b737428396c4309fae87f17d9f6c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:24:37 +0200 Subject: [PATCH 335/366] docs: update changelog and header for version v2.0.2-beta6 --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0741d48..c1c3600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## [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 From 10587276c201d8d6fd31db35501aa42d9784a30d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:37:07 +0200 Subject: [PATCH 336/366] docs: update platformio.ini for version v2.0.3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ca32a9b..ca21099 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.2-beta6" +version = "2.0.3" to_old_version = "1.5.10" ## From f0d1692ae13a54dc1cce1587915b005be180e378 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:37:07 +0200 Subject: [PATCH 337/366] docs: update changelog and header for version v2.0.3 --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1c3600..8de0cff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [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 From 98ec5b98467bfa0b7c0dab46c858f6bc6156d824 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:47:02 +0200 Subject: [PATCH 338/366] refactor: disable auto tare and weight filter reset in scale loop --- src/scale.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index 095eee5..3a56e77 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -167,8 +167,9 @@ void scale_loop(void * parameter) { if (autoTare && scale_tare_counter >= 5) { Serial.println("Auto Tare scale"); - scale.tare(); - resetWeightFilter(); // Reset filter after auto tare + //scale.tare(); + //resetWeightFilter(); // Reset filter after auto tare + scaleTareRequest = true; scale_tare_counter = 0; } From bcb7c039e2fbbf8d4f2ac633323336434703ca32 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:49:25 +0200 Subject: [PATCH 339/366] refactor: filter out automatic release documentation commits in changelog categorization --- scripts/update_changelog.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index bb6b602..6058f2d 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -42,6 +42,12 @@ def categorize_commit(commit_msg): """Categorize commit messages based on conventional commits""" lower_msg = commit_msg.lower() + # 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: @@ -77,11 +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() - # 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) + 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") From 37309da1858d0469026968299f120f6345cd2aab Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:49:42 +0200 Subject: [PATCH 340/366] docs: update platformio.ini for version v2.0.4 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ca21099..816e4f1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.3" +version = "2.0.4" to_old_version = "1.5.10" ## From f5a1debd7d4a201d1a78a38e98a2f48b08ac88c5 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Tue, 2 Sep 2025 18:49:42 +0200 Subject: [PATCH 341/366] docs: update changelog and header for version v2.0.4 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de0cff..a9e8f6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 043c2d4fa8631bf4468ead09f399c5b79e3f1453 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:06:31 +0200 Subject: [PATCH 342/366] refactor: improve auto tare logic and reset conditions in scale handling --- src/main.cpp | 11 ----------- src/scale.cpp | 25 ++++++++++++++----------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 81d0a0c..e777332 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -197,17 +197,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) { diff --git a/src/scale.cpp b/src/scale.cpp index 3a56e77..ddd9f1b 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -161,20 +161,21 @@ void scale_loop(void * parameter) { // Only measure at defined intervals to reduce noise if (currentTime - lastMeasurementTime >= MEASUREMENT_INTERVAL_MS) { + // 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; + } + if (scale.is_ready()) { - // Waage automatisch Taren, wenn zu lange Abweichung - if (autoTare && scale_tare_counter >= 5) - { - Serial.println("Auto Tare scale"); - //scale.tare(); - //resetWeightFilter(); // Reset filter after auto tare - scaleTareRequest = true; - scale_tare_counter = 0; - } - // Waage manuell Taren - if (scaleTareRequest == true) + if (scaleTareRequest == true || (autoTare && scale_tare_counter >= 5)) { Serial.println("Re-Tare scale"); oledShowMessage("TARE Scale"); @@ -184,6 +185,8 @@ void scale_loop(void * parameter) { vTaskDelay(pdMS_TO_TICKS(1000)); oledShowWeight(0); scaleTareRequest = false; + scale_tare_counter = 0; + weight = 0; // Reset global weight variable after tare } // Get raw weight reading From f810bc5352f462c115dd5413881f99a4603408c9 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:06:50 +0200 Subject: [PATCH 343/366] docs: update platformio.ini for beta version v2.0.4-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 816e4f1..4222312 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.4" +version = "2.0.4-beta1" to_old_version = "1.5.10" ## From f9aa7f2e6b65e7187a510121a5d510ffd976e2c3 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:06:50 +0200 Subject: [PATCH 344/366] docs: update changelog and header for version v2.0.4-beta1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9e8f6e..518c254 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [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 From 2c435e5c9817643b28da035e1db2c27371ed2a20 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:18:43 +0200 Subject: [PATCH 345/366] refactor: adjust auto tare counter threshold and reposition tare check in scale loop --- src/scale.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index ddd9f1b..69d3dfc 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -161,21 +161,10 @@ void scale_loop(void * parameter) { // Only measure at defined intervals to reduce noise if (currentTime - lastMeasurementTime >= MEASUREMENT_INTERVAL_MS) { - // 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; - } - if (scale.is_ready()) { // Waage manuell Taren - if (scaleTareRequest == true || (autoTare && scale_tare_counter >= 5)) + if (scaleTareRequest == true || (autoTare && scale_tare_counter >= 20)) { Serial.println("Re-Tare scale"); oledShowMessage("TARE Scale"); @@ -200,6 +189,17 @@ void scale_loop(void * parameter) { 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; + } + // Debug output for monitoring (can be removed in production) static unsigned long lastDebugTime = 0; if (currentTime - lastDebugTime > 2000) { // Print every 2 seconds From d43fceebbc8c35d3973757fba24431376f507862 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:18:50 +0200 Subject: [PATCH 346/366] docs: update platformio.ini for beta version v2.0.4-beta2 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4222312..2551aa0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.4-beta1" +version = "2.0.4-beta2" to_old_version = "1.5.10" ## From 301109c37b47427c2cf324ff0cb6358d1ca6847d Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:18:51 +0200 Subject: [PATCH 347/366] docs: update changelog and header for version v2.0.4-beta2 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 518c254..3788f50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [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 From 666c92948358150a9c36b33d6b156e8c721d557e Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:28:03 +0200 Subject: [PATCH 348/366] fix: update progress bar message from "Tare scale" to "Searching scale" fix: Scale tare function after boot --- src/scale.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scale.cpp b/src/scale.cpp index 69d3dfc..dceeddc 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -242,7 +242,7 @@ void start_scale(bool touchSensorConnected) { scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); - oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Tare scale"); + oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Serching scale"); for (uint16_t i = 0; i < 3000; i++) { yield(); vTaskDelay(pdMS_TO_TICKS(1)); From a7b06c9b9709a2a02b71a16cfb1b6f3d8684f696 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:28:09 +0200 Subject: [PATCH 349/366] docs: update platformio.ini for version v2.0.5 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2551aa0..3ec9fc3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.4-beta2" +version = "2.0.5" to_old_version = "1.5.10" ## From 16887f5248b2244970f6fa9915a23343df1329fc Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:28:10 +0200 Subject: [PATCH 350/366] docs: update changelog and header for version v2.0.5 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3788f50..0617f2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [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" fix: 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 From 8f6ecb350f51059f1542720039adcb3803a44f37 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:37:57 +0200 Subject: [PATCH 351/366] fix: correct progress bar message and update tare function description --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0617f2d..836e6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ - improve auto tare logic and reset conditions in scale handling ### Fixed -- update progress bar message from "Tare scale" to "Searching scale" fix: Scale tare function after boot +- update progress bar message from 'Tare scale' to 'Searching scale' +- Scale tare function after boot ## [2.0.4-beta2] - 2025-09-03 From 40fdb667fac4554beee936bf540abb144c08a6f8 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:38:07 +0200 Subject: [PATCH 352/366] docs: update platformio.ini for version v2.0.6 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3ec9fc3..457ff88 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.5" +version = "2.0.6" to_old_version = "1.5.10" ## From e0d641c8179db70b3efaee0437f00e66c1527489 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 15:38:07 +0200 Subject: [PATCH 353/366] docs: update changelog and header for version v2.0.6 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 836e6ad..c5a2388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [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 From e604231139304ee0592899ce7b2bc99454e07d98 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 18:45:24 +0200 Subject: [PATCH 354/366] fix: prevent weight display during NFC write operations --- src/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e777332..c9a41ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -135,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) { @@ -154,7 +154,9 @@ void loop() { { autoSetToBambuSpoolId = 0; autoAmsCounter = 0; - oledShowWeight(weight); + if (!nfcWriteInProgress) { + oledShowWeight(weight); + } } } else @@ -176,7 +178,8 @@ void loop() { 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(); From 61174273fe080c573e22d0423485d4edc24c44c1 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 18:45:36 +0200 Subject: [PATCH 355/366] docs: update platformio.ini for beta version v2.0.6-beta1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 457ff88..8b4db76 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.6" +version = "2.0.6-beta1" to_old_version = "1.5.10" ## From 6bb4384852cf8e67d0ce7a875b3d9c71d7c46aaf Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 3 Sep 2025 18:45:36 +0200 Subject: [PATCH 356/366] docs: update changelog and header for version v2.0.6-beta1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a2388..b64ccbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [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 From 0a6a183a38b87adc038f00cd2fe2476a1262bb54 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:31:07 +0200 Subject: [PATCH 357/366] docs: add support information for Recycling Fabrik --- README.de.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.de.md b/README.de.md index e1015bc..72cacbe 100644 --- a/README.de.md +++ b/README.de.md @@ -11,6 +11,21 @@ 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](img/rf-logo.png)](https://www.recyclingfabrik.com) + +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 From 1d421930d83baedbe047ed9b7dfaf6cdb6007d87 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:32:15 +0200 Subject: [PATCH 358/366] feat: add RF logo image --- img/rf-logo.png | Bin 0 -> 18415 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/rf-logo.png diff --git a/img/rf-logo.png b/img/rf-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..78e80b4f890c73e03506aca8a0132f0d6793db0d GIT binary patch literal 18415 zcmeEuWmB9@6Yin`7D70-Q6{~2MzA-E{nSbcL?sD;4Z=a+|OHezMfxj zsG?Ywy{CJ6dRnfzhA;)WZ)hk4C?F6BO;SQs2?T<*0)b%Ykr07*ij2IYfgi{Y5}HmR z5blTnzF|hGuLMCLQjnymu!?);X_l9R?vT%B3bt5mJn0Wis$)ZNZt>+;NoPY%SEVtm zUNzqAi~@WSqM@_~DWoRJPpTP6Ry4B5f+95uiX;zT4T!Bi$;mk6|89^Z@W;=|O(>%v zZJaqAZggB%2`i358ir6wCn6(x{z#N?^-bx5Bl?)hZ|*i}?RI|0?(~k*;k?x=`)PgC zX=ryW1p&|%1geS2;-UH9D_7XO|7HO)pnDI@3HVC>|8M+fhX02>>cBLJAU~vlTZ@&6 zpuf+sa_k^b%TV-K3d?o_%pWA-DPo97WWQeE^SOT}zs7dXbtk%?U78;*uH$ukFl(m1 z+%jPCAL;%IaNXYna`~x)NTu;#K0+-U7(_xpL!7T4;mG=>YktFkggS&uVGPJ@J`?V% z>u$*;p-1p&Y=S_!Mx=9~8YGB?vPftjdKT{Ya^_mF3mxkIJ|i9$2;>eEL;y;D4}U5N zvGlk!YpNg2w?&6=gFv*1z#q`C;BCWUG8Ss`nNY~omctwSjVx4MSORj1sK}7yL_>3V zca&$$Rgu9T_laY3M8??ljkAR5Lsk$(7=MT;JZplNH$rSUte#(|KI_K$_& zpn)bF2;>8(Wf4nik#NC_M+l=iW;SA5YD^_faU#>tWFAoIKyES4h_lRWo)=w%aAq*5 zJ%YfCCQSeWrNZSQ3Vnqa&Vc`|`09$uSzySMLzmw>(QhC_IS{OoY#>#KSwACs%n^9{7d(e?hjI4!8u)gw$MQDUv-yzH7!ByphtMGaV}Xb%BuI#B zd9pz1e=8BVZ}MZkbXBKppPMpJ>_MziA1fJQV3fYE0DtjKEu$Rk0|8C=)LFf zBacG%8aBRf@UrHWMt&O6ZY7N-}!?>o1(T{o2c+Z@Cyj z>zDl;z6|;q*YoA&#=-$ng3Dmup?4rqCtL)91Ik2lB=qpxE?vk2m2sGLs3K(R`)siK zXUOTn&{;>-h~bXNmd)8%bvT$XrKuxHbVdH9mnq+GGx;0R{EsIF?LiC>NZV%k^NSlVQ%jS6xo6dCA&iz?Z^zZ4H}iK&f|wDK5j<2u z_u^CO52|CXKzPbTgm4<5eNyE5h-I#tRB~X(^?iDI1*KkzzwYhsv{`Vjt-7nhw)46- zgvaU8`)+?ZW%Km)tl&hZQz?91~qNoO|w%y9f|+PhmS zF@jG>alrQ51$>Tx3TdUFHlT`k{$?y7=#R4Slz>vBOO#IbB>&T%@s8B5Q=yzo*WneH z$5yxg!~Ko3SDEcqzuL~zX6)LCb@x5;x+$oS^1*C;IWH?(N1Fm3 zZ$D%TKTHyQ1dIv#Oe&7XA@{za4E7Cq+>udScCawn$_lH(dwEo!bXkuNTQM$+6?(b_Z1QNzX3%$N5(_K*A`nYbpW>ljWrJ{*v!sr>o(8AJIuL91Lucw-H_@Y&+*^?56cUv)-anwcVnzqp;^V>`;u%$nb- zo#T_g0EHt&*wIpjg^6kGs?#86cv#^@U)Xw2Z<_`1tynNG7U&qM&m-K8V6#^FR~lPW z-rM7jwP4NVLXrJ$R7M?z{W$3~&3M<32;|#FiNc36Y`ZuRA*G zq+;8YDFk)we?(05hx22?vJKF>Q} zyDswh~4CR`Utuj{S5yi{J;wRO9tTNF|D-Bt-Z^2FC5`e2g;hy zYbPI^71l-aq+90yPcd)l>Rjh2oU$(8G>ijNM(}muB|wzUr%5JGyfA4icL(ON6ZJJ{ zeE^U_j|jM>^i;a$;b!ykTwYFlD+6(S?0x+F^W*d+hU<3u3~2-enQIi9c%f}*P9E;h z(1^r>%!H|LGT^EA`l34=AYN-jLfl&H>`%?Z#Z*a5*s8+b8DsS5%VaU0n2rNv6jCB2 zPJ=JXJIskVT2y(|5nm~|_rL8RXtmqMm)dEB8xa0638_nOb`z6r_A4%w(}YJ>!c4^u z6c?$KnhB!!@e^0nHsS*^oC+^1pl}9|xmU^J>TgF#NMe&ihif9k^va7xnZDQTc)C@j5tM`^swEbp(T2!wQ& z_g39j0Sl;_jb=|gcJ#6pabQI=)q;NioCn-y7imosWUg@ir&Ht2^)+NRRC%Q&2Hg`rIHUkr_?=paxxH840roBy$lj_HvZcC3}6r31Ozm9BLg{HXYMRaCu^rlMg)?V8IMW+_+0;H%hXJX=oHyT zmP$;)oSp&wK^t*ZggfB|_gJPg6o|zgL1;f>pQ#6rY5BGrrrv+FT>13c%CeSKH4Hg7qg@bVZLCG)*gO_{zwMUYy&y(8=29+^Dpa=Ba1c_>=tV&|nR;M5a0c^z47gLGZdnX-q^ z*#3LP)qe62=bWV+0TW?2A%K3E0U3e$6H!!BKaMFa^_YDu;iWa5og#h%5vDbM5$gel z{5xSU8J7&DOTuyeT zCkmkK@DyT$aR{$r|MWY+RvGDKo_hmZ{%!iM`4myJ%tUseeV2Qql~T|BEUT&}B4vW~ zZ%UlSh33&$`X}S}4Y*2e_?f7E4@{1FhUNkND}Ngt<2ad?{Sx3mYQ6|OhFP;)SH$HO z_^kLH&+BrRFz!WdT@Bwb{1rs3O!H%W!31X62$P4H2~?3X)Z1O9Uxl^4(ADAHoVQDT zY&lLpdn+)3qwk8tHeS5dr}Evo3f$@*y7k>>=z7$3e5kuu7_B91-nGD+urIGnCZDko za*~XLe3&$m6@dt^KlN1rxT_I?_$K zzeylnPAY@|CGH7G1dT^>DUI~fiCo~e>p90hTu`uay{;HmGj&*NpsM>_&izb;wB(pB zDyB7sAx{^bSwOB22^z!YEAU&+A@ewFFI z{Ul%bDPiO#G?y7cr8m%MQ9{BjaVk~>!tp&#X$F);6&KpTIZ>(_)dT3SfK^ipQ(`!_ z;ym+jo=NQT_hXZ9GUcd5#hQ1yX{uwa^)PwKq)s&1EBV{B3ah&-!pE$S{(FKT-6 z-g*_-Au=vxLl3?Aq^j0)IVof#0Y8}H1ELfdh$*Dnom%Nnvr*j2wX_JrPn#%YzMpT) zOG#~XbmGR8+lB1lBPQrH*R+ro*5fykwb*0S8hn7~sesP*m;b;D&ybI8ebpz*-@{ar zy*65l`PlHbQh4`aOV!bi>kXmb`W!kPgalH^@b^<}^qn;f7mvbnIqQ{rZ-Fu9KtTi- zm_Uj$wT=~ACRJZik0z9+Kw42oHoOgazvcPrmWO!8wnW7{I)X;w;b?=}>eThkbZ>Yj z)J6^ja==331aTk-+}4YPdST^|8*+SPSyn_~Tp84Cu^nNfk|v}2S|gz=9so#c!2r6o zbccW4Hoa6H^r-tuPyWebOKEtfifY43NI=Y%1DY3BQpM=6JB`UeKm^GM^=N~BFDYF> z{woTEa87y^5xPTLHNfTDJVCj%CrU9Xu4HbvY!H}pEcnwN4I^22qLQN0dk#=1u)%)d z3kGfPF|Roq#k!Gd-r1$;H)=?IPH09qj@nI?qYbj|HlL0aN?>VkoOB}JIg)sHdjKl{A- zSuQz?lBkHWCMmqpSO(7`W`YDat5;Xx&4jj7|BYax0dt0Vj(v=Nzr~w=-RJO1@`uNc z#%y5vu%TuUHiVkmQo9<~INz3p(b8#e3e8rRG2egU~1nU`5a8+N9<_H3Ow(fg?rZVVfND^H0|FRt#HV#jJTEk$Z`ALVK_ z+&X1G#3O@Pf7riv{gr?H9G!=q;Hm-loK|AdyM^PDhMLk+DI9!f6Uf9R*1v@e5#!xK zPKFWC7w?A`)-m|F6Lza@6TCpx%1?yYHjrJd5$`~$q>^p9vl3GW!U!=x2HC1s&+-7RBQK<-XU}7`h4pK#pEiCE=)e{N#xT5eeB)KPY$uRBQK2d?575EU6glVKK(wCewLZ*Opy=Y6AKHb>~oNA&b})XU=U#qxbNBR2Ttn5f_NTTuSunALBOw)#x_ zIgMoOv)#zKB*nv>e>@{oQ*K*&G;F;5?l1cv>v>|-m`TX4V=Z*FpKs|YXEc5twKxf6 zJLx3GAPj-aICi)jA*Q}^G-hw|Zy@D%e=x)Yk`FtZc5DgnhW%>OVB)aL^mTtW?fkB)b^@Y@dF4E{GK6x8Qnj3jtEyts zKSJ-A6gAa2iSmlKUO%$(Gky| zsa~HuL_+NyTG3a|V*Wj;IaS~(k`3L9)-?}ROVyF`XI*8}O8gqlJ)>8^QH?-W|0{y* zeW3QJ zcJD3{NssE$M(kGmLSZ-)%pq5}T>UxO1~1b#A9Nj;B?zZlvzW?4BarpX)!?}};_H&cBZ<%x?ZWNx|oZQNB2v?{ePYJvYdrHp>Gn;9FTOVnSS&sV17@<>L(_atny` zdg;P#S{?TryPY>q=R`mg;Nc}Dh}&T1eE?49{J_XiRVV9(a!b#9=~pHamB90_pP1UC z8K2G_J*je?*HlxdI-(e?lLJ_FfnXV~L{a+N+n?K;8R?Qq2A||g|85rgoS-GCe5ErA z>CiIx19iGN(%2iemX;U!ZK|&NHv7tb1_sJ2=AAAm3=oj&xy5&x zQ3=vYvh&anPM5uFh!T-4nG44S`rOS2n9RS~AphM*yc9u2XD<|ujz|Tx(rQ!2_@H?D zicV-mWp;Zp>D-U=wSpQyB)ulw%#0%iCjB@y6^)UZEooDC6hfTy<*)Ht8y0=A$obt}<@{q9?OBn#BM<3clTh%GX-{GKy#aL0o$|ALs_=GRx_j3%?<33`-9Nr)Bwev$H@OlM57 zY~icO%ZKxL_oie7D-o$~RG41_Y)&1CaBjNBhr z_TnLO>7)4~e5HT`uZqmMiK#KFRYQ#{N1w$6&E3~I0^(7QqQ@UDyWOP@8lMhl-|hH= zglDFZYBhwccn}mqrYl$1ea^MPLPk8k=fqjA(XAHT7%(Ko*;)eCD9Xk_Ph!ocb!-Si zUHAN<04LyNztM?MnHF5bK7Bye;=6gfdT}y#9zHwSK_TEd+2}!X$LZp$^p`)tIM12d zW`1NB=t9b)dpvp_e3_9}tf|5hp+W2x$&gk-eikDes{gbL%h*$nSYKJ0%N%vOhDs+I zgH_kF+nBlL?@RP-Bvq5UMVd-7O0TCPwc8xCt%1Jz{&xh*(?W~FYR5MkM+ZUylyJJJ zJ4jeCtahBs*%ShVlUuPhWzhId+;2Voe>w{^*-xY$kK8Oyo{ZtPAtQWtzpB|$!iB13aYpfQ z<;p3R6I58*6?}gszoUWokOh1>CrsvnDC6!EL;clB8W^wwnVdk}m-cM_|1 z%?WH!y3fHH&FGo@V*B?Nc)+vLB>GMGO9^5Wm21*X{|0L0y?bls5G82klQo`IpyY&u zbQP;LikZM`g+X%(6rKH=6`q^)6tdymktX_Def_1%m;s_IExk`B z_iDczoB?Y~6~GB+)?t28L+vEQrqSyEP1m3h@z|*~dlnI4^6l;p>3s6L3V7NS%m-+K z(G>W zIaB8u>9$RZd4LDvSu@|{YwwxL&ZpqKY44?yGqzFA32AF-8HR;v$|vh7Vax0LtwqEN z%R{s2ABzXan8$K~45nOD?`XZa0PBm-dkB^{T#TtiNjO& zQO^OZabxbsfIJ!nO#kG#vRIc6#jKJ`rsnF^zm5ONLr$%jFS{ZC)-$uW8Yt<4b8eE( z4{}jvorYuTVFW;vdns)FxSQCz{3Tn6$_3XuhTwEF{HPXF<@qG*m)0v#Lm+GwGAB!A z#eodSdzW~lx}t^Vn8}JQr4)`9JRD@LrCLhF#s|+FigD;NGJag*{zk`O-vC|UF$qHs zaK*`(_}b_dbWH#bxWyx(K_M1AG{$;k&8+4VNQ%~c-yo0EvgxeAFQ_>QVF@N+wCYw@ z$-k`;HwNDrb>F5*?=!#|!WR8Y>+P-dT9l4^aQ!J(b4)uBRjq9QzI zbX&IM$aj)zI?To3p*tkUX|~iPGdud<{I}*tp+d&4B=wmp2(m0Lrtjl@L*S~K2FhX^ zj^mDwb^b3GAiwOjikgE;R4IpQt&g)h)}|6$g1XL1Q02ct;yoywnhG(Bn7n^~S7MrV z99~RTiVrJQuM>`F>n7D1ABKKXYgLt#E8x?obggk|=MZU%O(`@gun zSyX|6aXKfjqtM9W>JLS=R)d!KVHNQ7Ohw`O^fS#_<^vkCG<~{2so+MtQ8UpJH(_r= zUBiq2G2@;50yJOzGj*B4U%s?ww3BmUyd=KSZ9&o67j=GN|d0Dk=yLMBJROQa!$_UU_~wbvr9F^Un%DkDD+_=Lmw-N0kXM3MW_E0`>?^r9PdNNBd|X z_dWO}T;9B@qgSMy7znnGGiw_j1j^|;=FVf((M+6 zh(Xq22R?RrEMlRAht00mCX@V*_hP%8ULgf*vNre2E7A3w< zs*ZckYCPKfCmY-Ar=^%Sm2CcH{mBP1#HK?~i^W-#z6SuWDKyrE6-!DRGDc|fi;t;i zR;5Hf(4nBuH>xtRJ_@(`hpvsNI_6_RBE3<~hN3y^a%CWUIh6#Prv@jWG5zs_h2q+# z#KPD8FqRG;n*^c%C<61;B=xN&ht7kP?Y$V&I@a&xQNL086`u-1m0bh7t|TO3x7}e< zAYqjWZJXb6%BOeBzDLr7XZEgm^XaTCe-HIKY*^Iohjsj>%;J>&8|T75?c>yMuvu4y zOR$-`$5}+~ODnf@url1bubO+sz4fDA6S==sHPVbx>)N449LZ7qsG%pd4pyX`<7>=C z?Zz$XU)ZK(0+>q-+Z#oq;Cg>*#`bG_G99#$^MrcPebBbRBx!2x z(5UN9HKSfd87h&*DI0@mq5~9~vE%{8urc3Yn)5@%qwZZ(ed6jB1i~=RV5j-NmlF`2 zIsh;k-Q*snYk+c9xpd-x^)oa@&-E2;y`B!Q4YCyk*N?wBQt6C?A@Dgw|Rbdj) zn9DiKUTFiRgjjQ>Dq$KY;o^;{h8HC&@kgcXge7%`Lad1(P+6oQ3mM5p`^q6YvsU?n z8S8#*UvzPB`+UBmws$3ULS3>4jOx+r)dO+D$14PZw~b^2e}!@o8iUqRIQ7@k)AC2d ze(o#x2`joNS%1jt#9;&X0_mLEgFi-` z6(1ou&?zdYYAeynOxlq-J0t`@9IL~eBB;j97f zjXO$^77TW!h4sfkGg(Ke7)A?mWQ_K^6TUlu?Q!~az`sb}k)tJ5B>W;YR!E4If>|Jb zv%zLG2MBUU4N51|!DW&s&D??xN120awH<kk7)UW54q$O;yF)Wsn>lMk{Mh4J(JJLB0fFGhF7ieK!Auo%}fe^{dj=hv) zOou?!XuN#8-XQIL{sot#OAABFinY7VQx;Hp6i!4I27w`67M4jfQz@zKR=B*2OnZtN z?RMWpYxll}-B9Htmu%tue8$zu*gT3T@W?G}Uh>yyoXT)f7z!{lm}C8(efr0+3KYTo zU<;egAM#aAR)?@}BXcFw_bjU-#(kb1px|_?khh=zg&HkOpDut0PlH zU8#tw)TT!~EdV}bOgg7DJVMJiqSgSlQXfItuye%crJW*IS|4JJq*=Btr=OC!6-(Zk z;;E~c{3uob9yq0_!9Z%nvl&lIYEUFsWL?P}ptfSQixL8V!75;^2=VaVZsVsxBP`Zd z%&>b|8?a+)>`XVBr~HWe1uH?=dN5pM^gk;gh(!IZ=xxQej%Grz{t0AEn>ZoqvF?wG zQE6=07WtuLX=C3llJEG=3x|2J zes~*w`ni31971@@Ld|6mU-nV61^0f_i7QlS{=`}Uy~KS@4JQc^v?MGKZj7uW9L(>A zm1@kb9afAYQs&p=B_D5bcUVfx{XJdcESMs?kY?c1NDT9hUrdtGOk>TaQx2C6zOIT@ znhhJvZ@NhiUie8v8RF2_S&wby7|Q;ekm;(g*Hb6Hur9VP_5@{zSZ2!+y_0KOZC!kV zFvd7?h^=?B+O(;muQyX<5`|N;_lIiKEGM0I?%{&*@xfrpu5HXf-9nV~7Nf=ZZ=hh4 z2>K$X^$s30$bL9@CB5=#2uw!7U?vBBYkN#~s_rPiiko4!Y08eWP96-UJ*MWywAk_i zuh=Z5rOw;V*?|)u($xNNQBWjK%wmAaUfUy{w8`pD4y9;?3kUMdXJH4%7w8t;Nn|QB z<6II3U)|p~6qp}Xz+HxFZmEbjbV(XWvX~f2X^PVD31VTn zTm{9}EvvZjNM(O;pqz2fcUCG4i)4n^3_}FmRVq%rTs^u6njxlVGY2b=Y8fUWW>I@l zUjHnWR%ETkMabqhDOKZ6dlV28DvE&|@T+&Vu_x@i$KoCcT&Oy0UIWV;QPL+o zrN?${Cu{!O^y`Tv17}%a_N>ozw)QC5uSZ*y(WQBQfJX|U{hT&;p zRB8(m11+o5rwV&DdX|nFGP^D(`4#E}n1_Yf=~TfOWyUtysxoReDRb$zpYaW}c9r6| zb~v1f?~EXXgnd#_%(A74LXNbny_`{hEa?3*)b=J>`A2i4I(=Un^OA z3C+D-c8mtxdwL(`y;{a#7p1W+D7@hgk_Sp*PgTuro{g!rSqq0NG*z!3PpHuksOa3) zFSt(D~r_e_TW7J4HN8%1Q$t0`lS;N`rM%=d29j8yQ8-?=8 zC-;9(ixe~Ub!J9fx6XsW+hU4biG;2Oy~h}|!kvGO{qyH}?Wd;{T_~GwrlyZ{M85HY z-j0D~(L41u&NT%GPx}AlZ@Q^M6}0s`G#=gjjrxrYRXpap1NgfaeT%@-=-_GH`;UKr zJhr%eu_xRyqfBux*g(B}ePFK*$~ICg_xz<*>tjb=uGl=jmMWIEqo`)Ve8M^AWK81r z>Fcs~-XKPHH4>Qsb2?RMs@f{F##bO|J69HJouxwz>zyt$E`9Y_0e1A91g zy(PQ9(C}6ClMf|1UgoO{?4o%IF8+K%=BC7c=xHsTh*qJ5^iJQ2%~MLHivNB**T%xK zz~B6AcJYh92S2K5qn*oxn*V7I7Tjr^zR79O8axzsuXN@d zYo6+`l1}ZJ%Qw`LS8hniWkUR2shf3El+x9PO>tjN;Dopex~F2Q61QF^Ezag&UoMJk z$Pj8J`EHqhV<&SNa^4(&^KHdGT2)y$NLCZlUp3Ys{4J$VM;kqY3GQA`MU#V5YpN5~ z8`mmWJx|u0m`joScWfUUE{LSB!fIMhgmdzUynx;RJT0jy&xvGI?NS=?P9$l6S(LOa z6r9x`7MQ8=$3)o?>R7DDxyw7+|XrX?M8p&_BFdP`bJ-8pFw#xm3rE^mS9#@|{D!!@a# z5!T9@N}Wmo%(*M#;b;Z@T-+PBl~I~Bj>8qPrl^mgC5p5A*~EmBgGUp0*ifZX-n99z zqg-r)w0!-db!F9L9o(LW-D#&{9gN27URhFpwD z9=l)%#DTqqel5ACdP$l1W^gv%9GgYUU}`1(+DLuoQW0EGI$}5x(t>wwG4f=+fcn)M zHujeR+oWV$CbYlr6~SrQA1qx4OHF}>^iiSleh1kcK4#3ZV=Xd_>Lzx)h?h}xAbrpI zbM$}0y-f4{5eO;`Ogu*(?U zg)l1i4k*^9sver-+rQagsHk_V-&fjCf#&)SLN;Mzq%x{L{|- z(gHOM=uoRVCV~oPHI%+^m2&k+Ea1rSxZkJT^Cfu6XXa#YLgjnaviY4XUZMJf}s!r5jvx77boEz8&|;*`B7pKBr6(^+d1D#8Nz z*|Ov4s6UQA(IJ3149bJ7kaM!D;|7PuD0>i0WuFJD~(lj!8=puK5J;=X6J z%C(vpeX@saHNpAtl6)I9zd6vLQUS`Ws4rTW#g*F%R)~eu^|h8C$Ui8cJ))9!=3=e2JiZ}JO?lDL+}~!0*^=#7H9!)N{Vbb6 zP+^rTwV-}1&Gz0-E6gWsQR!4rvr%mL2(}Km#=>qxv7d2_;`8PBD;43KN2WCOpOcAJ zQOIyI&PN`aT#V@?xOyOIf&_G%v}468qEB2}>h zZDKH~g}kQ<3p0-Tm=mL8@Ii3Hf&x&;O#dzwniS50|F51YYqwRnUf@3HA(Yh$`~)5_ zkV9OeYnn*Z-6LZ;X3XEG*2*TuMZwnNDr+|TLJdai=T3Kw)d#r#*|&`{KNHwtHRl5s ze$&F13D3^aK{rZkFYNlJwvK7Lh{O0Jui&u;zVWXcusdWS_dbkJQqQOa+r%3SIFn2C z6x!3U=|z0%o{TV!PP#@(sTVLWV1@^Ah-KN09^Vxabbo01l{I5D%CTO{9&UaM}JiA;f0k+;!-HQw(ipxV;`=8|V(hzSU%DEMjZfCDyW)Dwbs%M~E^eq=*Jv=^#M0Ed`#tIuJq~hPqwK-JZGNo z;8=WuR8~=b)cprwH4=|4>U*d^HYXZQEF_m+b|`*_?MK;T@5efAZc!-1y#z?rHu4Et z-z~(ek+cVR5lLJ+b$+IZFoi1yg0WkMtyzkw(VQhmo=>Pg&A~%OTF@86<<$lQb*}6t z5}^NzA%r=enG615H?;$offHLr3K8%G>2+|p(>ey-wn|K;%IZvs@0&~vS6NM$(#@21 z)c(BA4{{JMT9&6T9>xv7!ZYVD$D^!&J^^WZ?Zu8c^oZ3CE(j^ty3`Hz!lCq?$tSSF zmEh$>e&~(APKdO0-5FTAf^BSPUR#e-apGuxR!?~RfI9A2X z7;7(~Y=8Y0HeYd~BZW6r;Ui`gWwao!Q^SEE>=pkslg^4@o&Je>1ee-qh2R&qmEX&F zbDN;N;9d0n&I?>r%sY@St(@#k7%4LG?R@^@4-(lCqmMi4Yb#tfc~nL56<@7(ao}z9 z=oUhjk}ORy1m}5q7=}}dNay6>-u~Zo~mlwRmlniTdzeD57=h(EeFA- z1Z$nidcSn)(t3hXzAnZM{0d@UV_z~0o32$z?Kkx2W z7<$_mTaxN91t+en*^!D#fMT7V^cg2cx|}`)2_#+9F?D3*4?UGF!0Nj$6{jYd2eUIB z|6v0oF7|5pTU|Ff#7cRzBpx1?-^6H1;z)>FpsK6>##~$*fwzsULd>9{U6wbl64~m`fFk4R# z474Ut5hV)PeCIZ=gEtXFIM+*fLA!@O7g;XCf%_Xg~8ib>z};-Qc(P)1QPvPb%X5~D#P}Nlk4_v zX9u({(kW7;1*5?GIx&!j(<7M&X)t5^a-iRMEXD5n9V?F=hF0qBk7^^ySIy!>X%-v0 zj3zvQ6Vp)Ix{#{P6Fc{pt;lVYw(QD3OchN8&0@Py0l<@tHM!3@U(~4=Zk%uj++NSc zv%bO+|2yp}6%?1HM)&HMI?>Ut(9`})Xha`v!{0*YTa60 z#q1VnZls?#+-B?dK?-7!ZhK)bHuW(*5W7u;J#^sIE)8j;!Jz(Wwvbw{`u35dNXBv3 z#NI?bSgW|5=8VhJ39U;04~wBWY|qHNqUoPnJCApUc?z@R*qooUsfWtsWJEB4WRPbr zh1E(>kn9n#1&JL-LlIim_!DxH8=YQ%ZG;&bX4-$dZ9+b$g@4AEL$}Jd!hRP!RwZxg zKX?ys<&h))hgB9wC7Nou;U9zvv;;~i8b(u>>^U;QcO8?$T4g)P(RlIX&X3mpsjm%vYr~ zx2K|J{@*=DAMT!f#I^0)FL$NU_%3tlLqC!G`d5nTH>ttljjWk>s-=ehsvnU!#}s*m z|AQL@F36l|K=Y)>Lz?UWMWg($d&O5oGdUb&Z|bsXTZ6OldXF&4I{+2?XC2|CJ8_bajMjV~h8hSW$a z2|z%$h_Vfd)R{!FlTvPGTFWs@)nRe)S?DhL*SY0gvABO^?cft&G#v1lF^U+Kr&2s9 zY_rTVKZ1o!q%Mlu`bx}wZ$UY8g#9bY8#jgVlO%o3DA7=drf#=rXV!`2n{(gT`-mZ(eB?|kK?f#%cC6gQ7_Ui2Eu|5B)Ag872$*&Guoc#LqCSoi3 z%Olqi9?or%ZB@12$?IDaocfBn*jvn?_n#{3{_d#u{*_}B+qLNz?U^XI!}$019gd18 zt!5=Ho_En_Tm_&c5a?alfBzT2_iV$-RG+10pzg~naQO*bulKMzzXkB1T;JqWZ=UXK zCtHe)<(>%N1Xga>bIvxOxi630SVFBIt1($##>MZvES{>np6%Rn@+W6Hzg-#wcR_!( zTqdt?Ro*Z>Nv(cb;X~-M(G)X`r6YQgAz&>6s>%W{*# zt>a2Y(mBSWge!xrDoW9EY^&@Vlcm^IL>19u%Wa1QJ5n}%Al*iR~afdEp**A6|dMa zP8fVLut~&gg%v9_uFrW!TDUw(21Ez8H)enw(MZ2^Xe7L&p5n&u}~w|`(JvS?S#)OMCJ z2>wlTA`|%^>x#w!i_BQb_7@7I1+Pp-CX10a8^Tc$rFz#{@sEI<`;SUg5x0uwob%n0 z-k8b%S*Uf?zYSY2iuP!;c71;qxT&p2B}@XY3uevbI{Il+TR?Qm^%7uKXJ!64t30Npbw#mQEU*k? zQWrUqXK>e((So7#o{je+%}6H8d2?@{U6IZIN`b$?8+;d2va{BnAaed|#*?!SR?F})wQg;)OG8qr_LldS2<#T($tN&?L2mUq({p zn=mGoT@H)5Yi8ze*`d@Q_J8%p*$Ff98w4Z1JFxCiZ24iTc;xy^tI4tF%?=75%{k|_ z%k1^UrN`5E=w!!Aet06zIpf5l9Y@aZQkB#0TEwLMGk{h!0mzdg&#dWWL2pI zrllWjZ`WjC2w`lAa-NXt&r#^U=Kd=cZp$iPpb5H#R)79YoWW_k>6fd0`wb<*$ZwOh z1%+DfKdP^f-hf0*Ld!+2`h;9YWN`K)K z$PyEZd=la&w)tLQ!pR2Ew0gTC3lH! zoMAL&smrxMl>=eA`kR47%E%EPC}! z#m918fmW)t(zBwzI(rFW&&3MrquG|zs`f#@qa@^7lLFwUHx3vIVCg!0Bai;p#T5? literal 0 HcmV?d00001 From 76d5e7640ff5714f9cc83f182558f1eee82a59cd Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:33:24 +0200 Subject: [PATCH 359/366] fix: update Recycling Fabrik logo display format in README --- README.de.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.de.md b/README.de.md index 72cacbe..aefb834 100644 --- a/README.de.md +++ b/README.de.md @@ -13,7 +13,9 @@ Discord Server: [https://discord.gg/my7Gvaxj2v](https://discord.gg/my7Gvaxj2v) ## NEU: Recycling Fabrik -[![Recycling Fabrik](img/rf-logo.png)](https://www.recyclingfabrik.com) + + 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, From fbbc226a7d00c72b938455e2ead510d9073a5294 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:36:07 +0200 Subject: [PATCH 360/366] docs: add Recycling Fabrik section with logo and information --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index e8f7fe3..3b1b88e 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,24 @@ 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 From 682ed2e232d0bc86bd854dba0dcdf9d21da8c96c Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:36:12 +0200 Subject: [PATCH 361/366] chore: remove unnecessary separator in Recycling Fabrik section --- README.de.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.de.md b/README.de.md index aefb834..e058baa 100644 --- a/README.de.md +++ b/README.de.md @@ -27,6 +27,8 @@ Die Recycling Fabrik ist ein deutsches Unternehmen, das sich der Entwicklung und 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) From e21e13efe66e6959deeb76d2fcb499e7cff0a6a0 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Wed, 10 Sep 2025 17:37:16 +0200 Subject: [PATCH 362/366] docs: add additional information about Recycling Fabrik in README files --- README.de.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.de.md b/README.de.md index e058baa..e499e37 100644 --- a/README.de.md +++ b/README.de.md @@ -27,6 +27,7 @@ Die Recycling Fabrik ist ein deutsches Unternehmen, das sich der Entwicklung und 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) + --- diff --git a/README.md b/README.md index 3b1b88e..cfef460 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Recycling Fabrik is a German company dedicated to developing and manufacturing s 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) From 10caf06021be8d2073622d6f004d6a69e70f0b50 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 13 Sep 2025 10:06:52 +0200 Subject: [PATCH 363/366] fix: add HTTP service to mDNS responder --- src/wlan.cpp | 1 + 1 file changed, 1 insertion(+) 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"); } From d7b0884d36ed58d7908b4fe3e5f375335f4ea8ae Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 13 Sep 2025 10:08:29 +0200 Subject: [PATCH 364/366] docs: update platformio.ini for version v2.0.7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 8b4db76..e10f3f6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [common] -version = "2.0.6-beta1" +version = "2.0.7" to_old_version = "1.5.10" ## From e943d2e70cc1ef0b7e64ed767c233f48adbc2271 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 13 Sep 2025 10:08:29 +0200 Subject: [PATCH 365/366] docs: update changelog and header for version v2.0.7 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b64ccbc..2bc2f3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # 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 From e1da8eb52505097eeab4aaa0b08b5668cd09f1d4 Mon Sep 17 00:00:00 2001 From: Anzarion Date: Tue, 30 Sep 2025 10:37:58 +0200 Subject: [PATCH 366/366] Fix: Add NULL checks to prevent crash without RFID module - Added NULL checks before vTaskSuspend/vTaskResume in scale.cpp - Prevents crash when calibrating without RFID module connected - Allows scale to work as standalone device without RFID --- src/scale.cpp | 10 +++++----- src/scale.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/scale.cpp b/src/scale.cpp index dceeddc..699df9d 100644 --- a/src/scale.cpp +++ b/src/scale.cpp @@ -28,7 +28,7 @@ int16_t lastDisplayedWeight = 0; int16_t lastStableWeight = 0; // For API/action triggering unsigned long lastMeasurementTime = 0; -uint8_t weigthCouterToApi = 0; +uint8_t weightCounterToApi = 0; uint8_t scale_tare_counter = 0; bool scaleTareRequest = false; uint8_t pauseMainTask = 0; @@ -285,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; @@ -393,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 5514544..aff65e1 100644 --- a/src/scale.h +++ b/src/scale.h @@ -18,7 +18,7 @@ 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;