From 8343fe887b6230ea74ee48ae0a5bf505a0307af8 Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sat, 26 Jul 2025 22:14:58 +0200 Subject: [PATCH 1/5] 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 2/5] 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 3/5] 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 4/5] 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 5/5] 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();