Compare commits

..

8 Commits

Author SHA1 Message Date
a156cac18e Merge pull request #44 from janecker/graphics_rework
Graphics rework
2025-08-06 08:27:24 +02:00
Jan Philipp Ecker
09f4c43f89 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.
2025-08-05 19:43:05 +02:00
Jan Philipp Ecker
ec0e544f30 Fixes typos in upgrade page
Fixes names of binary files on the upgrade page.
2025-08-05 19:41:06 +02:00
Jan Philipp Ecker
b6d82c8afe 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).
2025-08-05 17:44:59 +02:00
Jan Philipp Ecker
97a1368747 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.
2025-08-03 16:51:09 +02:00
Jan Philipp Ecker
85a9bcf8bd Remove unused parameter of sendNfcData()
Removes unused client parameter of the sendNfcData function.
2025-08-02 23:05:56 +02:00
Jan Philipp Ecker
c450df59aa Replaces usage of String with const char* in heap debug function
Replaces String with const char* in printHeapDebugData to reduce heap fragmentation.
2025-08-02 22:53:38 +02:00
Jan Philipp Ecker
722ef421cb 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.
2025-08-02 22:52:19 +02:00
19 changed files with 307 additions and 161 deletions

View File

@@ -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 {

View File

@@ -57,7 +57,7 @@
<div class="update-options">
<div class="update-section">
<h2>Firmware Update</h2>
<p>Upload a new firmware file (filaman_*.bin)</p>
<p>Upload a new firmware file (upgrade_filaman_firmware_*.bin)</p>
<div class="update-form">
<form id="firmwareForm" enctype='multipart/form-data' data-type="firmware">
<input type='file' name='update' accept='.bin' required>
@@ -68,7 +68,7 @@
<div class="update-section">
<h2>Webpage Update</h2>
<p>Upload a new webpage file (webpage_*.bin)</p>
<p>Upload a new webpage file (upgrade_filaman_website_*.bin)</p>
<div class="update-form">
<form id="webpageForm" enctype='multipart/form-data' data-type="webpage">
<input type='file' name='update' accept='.bin' required>

View File

@@ -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<float>();
switch(requestType){
case API_REQUEST_SPOOL_WEIGHT_UPDATE:
remainingWeight = doc["remaining_weight"].as<uint16_t>();
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;
}
else if ( requestType == API_REQUEST_SPOOL_LOCATION_UPDATE) {
oledShowMessage("Location updated!");
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;
}
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);
@@ -208,13 +242,15 @@ bool updateSpoolTagId(String uidString, const char* payload) {
updateDoc.clear();
// Update Spool weight
if (weight > 10) updateSpoolWeight(doc["sm_id"].as<String>(), weight);
//TBD: how to handle this with spool and locatin tags? Also potential parallel access again
//if (weight > 10) updateSpoolWeight(doc["sm_id"].as<String>(), 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 == "") {

View File

@@ -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);

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -2,10 +2,12 @@
#include "api.h"
#include <vector>
#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<String> splitTextIntoLines(String text, uint8_t textSize) {
std::vector<String> splitTextIntoLines(const String &text, uint8_t textSize) {
std::vector<String> lines;
display.setTextSize(textSize);
@@ -120,7 +117,7 @@ std::vector<String> 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<String> 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();
display.setTextSize(1);
display.setCursor(0, 4);
display.print("v");
display.print(VERSION);
iconToggle = !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);
} 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) {
if (spoolmanConnected) {
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 +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();

View File

@@ -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);

View File

@@ -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
{
@@ -233,5 +236,15 @@ void loop() {
}
}
if(sendOctoUpdate && spoolmanApiState == API_IDLE){
autoSetToBambuSpoolId = activeSpoolId.toInt();
if(octoEnabled)
{
updateSpoolOcto(autoSetToBambuSpoolId);
}
sendOctoUpdate = false;
}
esp_task_wdt_reset();
}

9
src/main.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef MAIN_H
#define MAIN_H
#include <Arduino.h>
extern bool booting;
#endif

View File

@@ -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,14 +227,19 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
}
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<String>());
if (doc["sm_id"].is<String>() && doc["sm_id"] != "")
{
oledShowProgressBar(2, octoEnabled?5:4, "Spool Tag", "Weighing");
Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as<String>());
activeSpoolId = doc["sm_id"].as<String>();
lastSpoolId = activeSpoolId;
Serial.println("Api state: " + String(spoolmanApiState));
}
else if(doc["location"].is<String>() && doc["location"] != "")
{
@@ -238,16 +251,17 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
else
{
Serial.println("Location update tag scanned without scanning spool before!");
oledShowMessage("No spool scanned before!");
oledShowProgressBar(1, 1, "Failure", "Scan spool first");
}
}
else
{
Serial.println("Keine SPOOL-ID gefunden.");
activeSpoolId = "";
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");
}
}
@@ -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)) {
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;
oledShowIcon("success");
while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,13 +230,11 @@ uint8_t calibrate_scale() {
returnState = 1;
}
else
{
{
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();
@@ -248,7 +244,6 @@ uint8_t calibrate_scale() {
returnState = 0;
}
}
}
else
{
Serial.println("HX711 not found.");

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();