From 97a13687475ec5ce271b9739cdf1d453a3983b8b Mon Sep 17 00:00:00 2001 From: Jan Philipp Ecker Date: Sun, 3 Aug 2025 16:51:09 +0200 Subject: [PATCH] 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(), "{"