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/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)

diff --git a/src/api.cpp b/src/api.cpp index e19fb9a..4b65f4b 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,52 @@ 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"); + Serial.println(remainingWeight); + //oledShowMessage("Remaining: " + String(remaining_weight) + "g"); + if(!octoEnabled){ + // TBD: Do not use Strings... + oledShowProgressBar(1, 1, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + remainingWeight = 0; + }else{ + // ocoto is enabled, trigger octo update + sendOctoUpdate = true; + } + break; + case API_REQUEST_SPOOL_LOCATION_UPDATE: + 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... + oledShowProgressBar(5, 5, "Spool Tag", ("Done: " + String(remainingWeight) + " g remain").c_str()); + remainingWeight = 0; + break; } - else if ( requestType == API_REQUEST_SPOOL_LOCATION_UPDATE) { - oledShowMessage("Location updated!"); - } - - vTaskDelay(3000 / portTICK_PERIOD_MS); } doc.clear(); - } else { + switch(requestType){ + case API_REQUEST_SPOOL_WEIGHT_UPDATE: + case API_REQUEST_SPOOL_LOCATION_UPDATE: + case API_REQUEST_SPOOL_TAG_ID_UPDATE: + oledShowProgressBar(1, 1, "Failure!", "Spoolman update"); + break; + case API_REQUEST_OCTO_SPOOL_UPDATE: + oledShowProgressBar(1, 1, "Failure!", "Octoprint update"); + break; + case API_REQUEST_BAMBU_UPDATE: + oledShowProgressBar(1, 1, "Failure!", "Bambu update"); + break; + } Serial.println("Fehler beim Senden an Spoolman! HTTP Code: " + String(httpCode)); - oledShowMessage("Spoolman update failed"); + + // TBD: really required? vTaskDelay(2000 / portTICK_PERIOD_MS); } @@ -155,6 +187,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); @@ -185,7 +219,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; @@ -208,13 +242,15 @@ 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; } 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 +266,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 +294,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 +319,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 +330,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 +341,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); @@ -551,9 +597,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); @@ -564,6 +607,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); @@ -572,6 +616,7 @@ bool checkSpoolmanInstance(const String& url) { spoolmanApiState = API_IDLE; oledShowTopRow(); + spoolmanConnected = true; return strcmp(status, "healthy") == 0; } @@ -617,6 +662,7 @@ String loadSpoolmanUrl() { } bool initSpoolman() { + oledShowProgressBar(3, 7, DISPLAY_BOOT_TEXT, "Spoolman init"); spoolmanUrl = loadSpoolmanUrl(); spoolmanUrl.trim(); if (spoolmanUrl == "") { 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/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/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 diff --git a/src/display.cpp b/src/display.cpp index dab0ccf..0ccaa5f 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2,10 +2,12 @@ #include "api.h" #include #include "icons.h" +#include "main.h" 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)) { @@ -14,15 +16,10 @@ 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); + oledShowProgressBar(0, 7, DISPLAY_BOOT_TEXT, "Display init"); } void oledclearline() { @@ -45,14 +42,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 +57,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 +117,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 +145,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 +168,46 @@ void oledShowMessage(String message, uint8_t size) { void oledShowTopRow() { oledclearline(); - if (bambu_connected == 1) { - display.drawBitmap(50, 0, bitmap_bambu_on , 16, 16, WHITE); - } else { - display.drawBitmap(50, 0, bitmap_off , 16, 16, WHITE); - } + display.setTextSize(1); + display.setCursor(0, 4); + display.print("v"); + display.print(VERSION); - if (spoolmanApiState != API_INIT) { - display.drawBitmap(80, 0, bitmap_spoolman_on , 16, 16, WHITE); - } else { - display.drawBitmap(80, 0, bitmap_off , 16, 16, WHITE); - } + iconToggle = !iconToggle; - if (wifiOn == 1) { - display.drawBitmap(107, 0, wifi_on , 16, 16, WHITE); - } else { - display.drawBitmap(107, 0, wifi_off , 16, 16, WHITE); + // 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); + } 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){ + 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){ + 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 +235,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..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); } @@ -118,6 +120,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) { @@ -212,19 +220,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 { @@ -232,6 +235,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/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 e7aec4b..fe1a486 100644 --- a/src/nfc.cpp +++ b/src/nfc.cpp @@ -18,8 +18,14 @@ JsonDocument rfidData; String activeSpoolId = ""; String lastSpoolId = ""; 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 @@ -196,6 +202,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 +227,41 @@ 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 = ""; + oledShowProgressBar(1, 1, "Failure", "Unkown tag"); + } + }else{ + oledShowProgressBar(octoEnabled?5:4, octoEnabled?5:4, "Failure!", "Spoolman unavailable"); } } @@ -257,11 +271,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); @@ -269,19 +283,24 @@ 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"); - + 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 @@ -289,10 +308,10 @@ void writeJsonToTag(void *parameter) { } foundNfcTag(nullptr, success); break; + }else{ + Serial.println("CP 3.2"); } - if (i == 0) oledShowMessage("Waiting for NFC-Tag"); - yield(); esp_task_wdt_reset(); vTaskDelay(pdMS_TO_TICKS(1)); @@ -300,29 +319,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(nullptr); + 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); } @@ -337,13 +364,13 @@ 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; } sendWriteResult(nullptr, success); - sendNfcData(nullptr); + sendNfcData(); vTaskResume(RfidReaderTask); pauseBambuMqttTask = false; @@ -351,20 +378,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) } } @@ -384,14 +417,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_IDLE) { + // 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 +463,7 @@ void scanRfidTask(void * parameter) { if (!decodeNdefAndReturnJson(data)) { - oledShowMessage("NFC-Tag unknown"); - vTaskDelay(2000 / portTICK_PERIOD_MS); + oledShowProgressBar(1, 1, "Failure", "Unknown tag"); nfcReaderState = NFC_READ_ERROR; } else @@ -438,12 +475,14 @@ 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?! + oledShowProgressBar(1, 1, "Failure", "Unkown tag type"); Serial.println("This doesn't seem to be an NTAG2xx tag (UUID length != 7 bytes)!"); } } @@ -459,22 +498,21 @@ void scanRfidTask(void * parameter) { } // aktualisieren der Website wenn sich der Status ändert - sendNfcData(nullptr); + sendNfcData(); } yield(); } } 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 if (! versiondata) { // Wenn keine Antwort kommt Serial.println("Kann kein RFID Board finden !"); // Sende Text "Kann kein..." an seriellen Monitor - //delay(5000); - //ESP.restart(); 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/nfc.h b/src/nfc.h index 8f8cf5a..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; @@ -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/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 8172d9f..4be30c7 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)); @@ -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"); + oledShowProgressBar(3, 3, "Failure", "Calibration error"); - 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 6723a0c..7c40fc7 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); @@ -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(), "{" @@ -69,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()); } } @@ -150,11 +149,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){ @@ -189,6 +188,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/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); diff --git a/src/wlan.cpp b/src/wlan.cpp index cbbba38..92081bc 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(1, 7, DISPLAY_BOOT_TEXT, "WiFi init"); //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();