From 3253e7d40771228cc64f3b3776f61a4003c8f50a Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Sat, 1 Mar 2025 10:41:44 +0100 Subject: [PATCH 001/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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/185] 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 b95497aec23a76e4ceaa45badc7a1e13cf8374b9 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Thu, 7 Aug 2025 21:12:01 +0200 Subject: [PATCH 156/185] 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 f133a1b321d5fd6473dcfd1586a295e4fb6f0232 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Thu, 7 Aug 2025 21:12:01 +0200 Subject: [PATCH 157/185] 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 158/185] 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 0a02912e4a7e951f27ffb774579b389089d4836a Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 15:33:08 +0200 Subject: [PATCH 159/185] 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/185] 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 d7ee52ba1f02dd0fb20596ab0e52c631259ca6be Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 15:39:10 +0200 Subject: [PATCH 161/185] 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 162/185] 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 accb02ab80baf995e9120bc80de89897fe4ef49e Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 16:16:39 +0200 Subject: [PATCH 163/185] 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 164/185] 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 0e00fd8b914ece1f9e007db97e3c8291344a36e2 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 18:00:25 +0200 Subject: [PATCH 165/185] 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 166/185] 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 69ae5cab5f3fab8e0b5d6b6751ce4b42ef2db21e Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Fri, 8 Aug 2025 18:14:26 +0200 Subject: [PATCH 167/185] 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 168/185] 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 169/185] 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 170/185] 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 171/185] 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 172/185] 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 173/185] 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 174/185] 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 175/185] 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 176/185] 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 177/185] 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 178/185] 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 179/185] 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 180/185] 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 181/185] 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 182/185] 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 183/185] 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 184/185] 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 185/185] 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