diff --git a/html/rfid.js b/html/rfid.js
index 52866ea..ae9cd68 100644
--- a/html/rfid.js
+++ b/html/rfid.js
@@ -7,6 +7,7 @@ let heartbeatTimer = null;
let lastHeartbeatResponse = Date.now();
const HEARTBEAT_TIMEOUT = 20000;
let reconnectTimer = null;
+let spoolDetected = false;
// WebSocket Funktionen
function startHeartbeat() {
@@ -508,12 +509,15 @@ function updateNfcStatusIndicator(data) {
if (data.found === 0) {
// Kein NFC Tag gefunden
indicator.className = 'status-circle';
+ spoolDetected = false;
} else if (data.found === 1) {
// NFC Tag erfolgreich gelesen
indicator.className = 'status-circle success';
+ spoolDetected = true;
} else {
// Fehler beim Lesen
indicator.className = 'status-circle error';
+ spoolDetected = true;
}
}
@@ -574,7 +578,7 @@ function updateNfcData(data) {
`;
// Spoolman ID anzeigen
- html += `
Spoolman ID: ${data.sm_id || 'No Spoolman ID'}
`;
+ html += `Spoolman ID: ${data.sm_id} (Open in Spoolman)
`;
}
else if(data.location)
{
@@ -618,78 +622,83 @@ function updateNfcData(data) {
}
function writeNfcTag() {
- const selectedText = document.getElementById("selected-filament").textContent;
- if (selectedText === "Please choose...") {
- alert('Please select a Spool first.');
- return;
- }
+ if(!spoolDetected || confirm("Are you sure you want to overwrite the Tag?") == true){
+ const selectedText = document.getElementById("selected-filament").textContent;
+ if (selectedText === "Please choose...") {
+ alert('Please select a Spool first.');
+ return;
+ }
- const spoolsData = window.getSpoolData();
- const selectedSpool = spoolsData.find(spool =>
- `${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
- );
+ const spoolsData = window.getSpoolData();
+ const selectedSpool = spoolsData.find(spool =>
+ `${spool.id} | ${spool.filament.name} (${spool.filament.material})` === selectedText
+ );
- if (!selectedSpool) {
- alert('Ausgewählte Spule konnte nicht gefunden werden.');
- return;
- }
+ if (!selectedSpool) {
+ alert('Ausgewählte Spule konnte nicht gefunden werden.');
+ return;
+ }
- // Temperaturwerte korrekt extrahieren
- let minTemp = "175";
- let maxTemp = "275";
-
- if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
- selectedSpool.filament.nozzle_temperature.length >= 2) {
- minTemp = String(selectedSpool.filament.nozzle_temperature[0]);
- maxTemp = String(selectedSpool.filament.nozzle_temperature[1]);
- }
+ // Temperaturwerte korrekt extrahieren
+ let minTemp = "175";
+ let maxTemp = "275";
+
+ if (Array.isArray(selectedSpool.filament.nozzle_temperature) &&
+ selectedSpool.filament.nozzle_temperature.length >= 2) {
+ minTemp = String(selectedSpool.filament.nozzle_temperature[0]);
+ maxTemp = String(selectedSpool.filament.nozzle_temperature[1]);
+ }
- // Erstelle das NFC-Datenpaket mit korrekten Datentypen
- const nfcData = {
- color_hex: selectedSpool.filament.color_hex || "FFFFFF",
- type: selectedSpool.filament.material,
- min_temp: minTemp,
- max_temp: maxTemp,
- brand: selectedSpool.filament.vendor.name,
- sm_id: String(selectedSpool.id) // Konvertiere zu String
- };
+ // Erstelle das NFC-Datenpaket mit korrekten Datentypen
+ const nfcData = {
+ color_hex: selectedSpool.filament.color_hex || "FFFFFF",
+ type: selectedSpool.filament.material,
+ min_temp: minTemp,
+ max_temp: maxTemp,
+ brand: selectedSpool.filament.vendor.name,
+ sm_id: String(selectedSpool.id) // Konvertiere zu String
+ };
- if (socket?.readyState === WebSocket.OPEN) {
- const writeButton = document.getElementById("writeNfcButton");
- writeButton.classList.add("writing");
- writeButton.textContent = "Writing";
- socket.send(JSON.stringify({
- type: 'writeNfcTag',
- tagType: 'spool',
- payload: nfcData
- }));
- } else {
- alert('Not connected to Server. Please check connection.');
+ if (socket?.readyState === WebSocket.OPEN) {
+ const writeButton = document.getElementById("writeNfcButton");
+ writeButton.classList.add("writing");
+ writeButton.textContent = "Writing";
+ socket.send(JSON.stringify({
+ type: 'writeNfcTag',
+ tagType: 'spool',
+ payload: nfcData
+ }));
+ } else {
+ alert('Not connected to Server. Please check connection.');
+ }
}
}
function writeLocationNfcTag() {
- const selectedText = document.getElementById("locationSelect").value;
- if (selectedText === "Please choose...") {
- alert('Please select a location first.');
- return;
- }
- // Erstelle das NFC-Datenpaket mit korrekten Datentypen
- const nfcData = {
- location: String(selectedText)
- };
+ if(!spoolDetected || confirm("Are you sure you want to overwrite the Tag?") == true){
+ const selectedText = document.getElementById("locationSelect").value;
+ if (selectedText === "Please choose...") {
+ alert('Please select a location first.');
+ return;
+ }
+ // Erstelle das NFC-Datenpaket mit korrekten Datentypen
+ const nfcData = {
+ location: String(selectedText)
+ };
- if (socket?.readyState === WebSocket.OPEN) {
- const writeButton = document.getElementById("writeLocationNfcButton");
- writeButton.classList.add("writing");
- writeButton.textContent = "Writing";
- socket.send(JSON.stringify({
- type: 'writeNfcTag',
- tagType: 'location',
- payload: nfcData
- }));
- } else {
- alert('Not connected to Server. Please check connection.');
+
+ if (socket?.readyState === WebSocket.OPEN) {
+ const writeButton = document.getElementById("writeLocationNfcButton");
+ writeButton.classList.add("writing");
+ writeButton.textContent = "Writing";
+ socket.send(JSON.stringify({
+ type: 'writeNfcTag',
+ tagType: 'location',
+ payload: nfcData
+ }));
+ } else {
+ alert('Not connected to Server. Please check connection.');
+ }
}
}
diff --git a/src/api.cpp b/src/api.cpp
index 4b65f4b..8770fd2 100644
--- a/src/api.cpp
+++ b/src/api.cpp
@@ -5,7 +5,7 @@
#include
#include "debug.h"
-volatile spoolmanApiStateType spoolmanApiState = API_INIT;
+volatile spoolmanApiStateType spoolmanApiState = API_IDLE;
//bool spoolman_connected = false;
String spoolmanUrl = "";
bool octoEnabled = false;
@@ -14,6 +14,8 @@ String octoUrl = "";
String octoToken = "";
uint16_t remainingWeight = 0;
bool spoolmanConnected = false;
+bool spoolmanExtraFieldsChecked = false;
+TaskHandle_t* apiTask;
struct SendToApiParams {
SpoolmanApiRequestType requestType;
@@ -94,6 +96,11 @@ JsonDocument fetchSingleSpoolInfo(int spoolId) {
void sendToApi(void *parameter) {
HEAP_DEBUG_MESSAGE("sendToApi begin");
+ // Wait until API is IDLE
+ while(spoolmanApiState != API_IDLE){
+ Serial.println("Waiting!");
+ yield();
+ }
spoolmanApiState = API_TRANSMITTING;
SendToApiParams* params = (SendToApiParams*)parameter;
@@ -236,7 +243,7 @@ bool updateSpoolTagId(String uidString, const char* payload) {
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
- NULL // Task-Handle (nicht benötigt)
+ apiTask // Task-Handle (nicht benötigt)
);
updateDoc.clear();
@@ -282,7 +289,7 @@ uint8_t updateSpoolWeight(String spoolId, uint16_t weight) {
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
- NULL // Task-Handle (nicht benötigt)
+ apiTask // Task-Handle (nicht benötigt)
);
updateDoc.clear();
@@ -319,17 +326,17 @@ uint8_t updateSpoolLocation(String spoolId, String location){
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
- if(spoolmanApiState == API_IDLE){
- // Erstelle die Task
- BaseType_t result = xTaskCreate(
- sendToApi, // Task-Funktion
- "SendToApiTask", // Task-Name
- 6144, // Stackgröße in Bytes
- (void*)params, // Parameter
- 0, // Priorität
- NULL // Task-Handle (nicht benötigt)
- );
+ if(apiTask == nullptr){
+ // Erstelle die Task
+ BaseType_t result = xTaskCreate(
+ sendToApi, // Task-Funktion
+ "SendToApiTask", // Task-Name
+ 6144, // Stackgröße in Bytes
+ (void*)params, // Parameter
+ 0, // Priorität
+ apiTask // Task-Handle
+ );
}else{
Serial.println("Not spawning new task, API still active!");
}
@@ -374,7 +381,7 @@ bool updateSpoolOcto(int spoolId) {
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
- NULL // Task-Handle (nicht benötigt)
+ apiTask // Task-Handle (nicht benötigt)
);
updateDoc.clear();
@@ -427,7 +434,7 @@ bool updateSpoolBambuData(String payload) {
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
- NULL // Task-Handle (nicht benötigt)
+ apiTask // Task-Handle (nicht benötigt)
);
return true;
@@ -435,198 +442,222 @@ bool updateSpoolBambuData(String payload) {
// #### Spoolman init
bool checkSpoolmanExtraFields() {
- HTTPClient http;
- String checkUrls[] = {
- spoolmanUrl + apiUrl + "/field/spool",
- spoolmanUrl + apiUrl + "/field/filament"
- };
+ // Only check extra fields if they have not been checked before
+ if(!spoolmanExtraFieldsChecked){
+ HTTPClient http;
+ String checkUrls[] = {
+ spoolmanUrl + apiUrl + "/field/spool",
+ spoolmanUrl + apiUrl + "/field/filament"
+ };
- String spoolExtra[] = {
- "nfc_id"
- };
+ String spoolExtra[] = {
+ "nfc_id"
+ };
- String filamentExtra[] = {
- "nozzle_temperature",
- "price_meter",
- "price_gramm",
- "bambu_setting_id",
- "bambu_cali_id",
- "bambu_idx",
- "bambu_k",
- "bambu_flow_ratio",
- "bambu_max_volspeed"
- };
+ String filamentExtra[] = {
+ "nozzle_temperature",
+ "price_meter",
+ "price_gramm",
+ "bambu_setting_id",
+ "bambu_cali_id",
+ "bambu_idx",
+ "bambu_k",
+ "bambu_flow_ratio",
+ "bambu_max_volspeed"
+ };
- String spoolExtraFields[] = {
- "{\"name\": \"NFC ID\","
- "\"key\": \"nfc_id\","
- "\"field_type\": \"text\"}"
- };
+ String spoolExtraFields[] = {
+ "{\"name\": \"NFC ID\","
+ "\"key\": \"nfc_id\","
+ "\"field_type\": \"text\"}"
+ };
- String filamentExtraFields[] = {
- "{\"name\": \"Nozzle Temp\","
- "\"unit\": \"°C\","
- "\"field_type\": \"integer_range\","
- "\"default_value\": \"[190,230]\","
- "\"key\": \"nozzle_temperature\"}",
+ String filamentExtraFields[] = {
+ "{\"name\": \"Nozzle Temp\","
+ "\"unit\": \"°C\","
+ "\"field_type\": \"integer_range\","
+ "\"default_value\": \"[190,230]\","
+ "\"key\": \"nozzle_temperature\"}",
- "{\"name\": \"Price/m\","
- "\"unit\": \"€\","
- "\"field_type\": \"float\","
- "\"key\": \"price_meter\"}",
+ "{\"name\": \"Price/m\","
+ "\"unit\": \"€\","
+ "\"field_type\": \"float\","
+ "\"key\": \"price_meter\"}",
+
+ "{\"name\": \"Price/g\","
+ "\"unit\": \"€\","
+ "\"field_type\": \"float\","
+ "\"key\": \"price_gramm\"}",
+
+ "{\"name\": \"Bambu Setting ID\","
+ "\"field_type\": \"text\","
+ "\"key\": \"bambu_setting_id\"}",
+
+ "{\"name\": \"Bambu Cali ID\","
+ "\"field_type\": \"text\","
+ "\"key\": \"bambu_cali_id\"}",
+
+ "{\"name\": \"Bambu Filament IDX\","
+ "\"field_type\": \"text\","
+ "\"key\": \"bambu_idx\"}",
+
+ "{\"name\": \"Bambu k\","
+ "\"field_type\": \"float\","
+ "\"key\": \"bambu_k\"}",
+
+ "{\"name\": \"Bambu Flow Ratio\","
+ "\"field_type\": \"float\","
+ "\"key\": \"bambu_flow_ratio\"}",
+
+ "{\"name\": \"Bambu Max Vol. Speed\","
+ "\"unit\": \"mm3/s\","
+ "\"field_type\": \"integer\","
+ "\"default_value\": \"12\","
+ "\"key\": \"bambu_max_volspeed\"}"
+ };
+
+ Serial.println("Überprüfe Extrafelder...");
+
+ int urlLength = sizeof(checkUrls) / sizeof(checkUrls[0]);
+
+ for (uint8_t i = 0; i < urlLength; i++) {
+ Serial.println();
+ Serial.println("-------- Prüfe Felder für "+checkUrls[i]+" --------");
+ http.begin(checkUrls[i]);
+ int httpCode = http.GET();
- "{\"name\": \"Price/g\","
- "\"unit\": \"€\","
- "\"field_type\": \"float\","
- "\"key\": \"price_gramm\"}",
+ if (httpCode == HTTP_CODE_OK) {
+ String payload = http.getString();
+ JsonDocument doc;
+ DeserializationError error = deserializeJson(doc, payload);
+ if (!error) {
+ String* extraFields;
+ String* extraFieldData;
+ u16_t extraLength;
- "{\"name\": \"Bambu Setting ID\","
- "\"field_type\": \"text\","
- "\"key\": \"bambu_setting_id\"}",
-
- "{\"name\": \"Bambu Cali ID\","
- "\"field_type\": \"text\","
- "\"key\": \"bambu_cali_id\"}",
-
- "{\"name\": \"Bambu Filament IDX\","
- "\"field_type\": \"text\","
- "\"key\": \"bambu_idx\"}",
-
- "{\"name\": \"Bambu k\","
- "\"field_type\": \"float\","
- "\"key\": \"bambu_k\"}",
-
- "{\"name\": \"Bambu Flow Ratio\","
- "\"field_type\": \"float\","
- "\"key\": \"bambu_flow_ratio\"}",
-
- "{\"name\": \"Bambu Max Vol. Speed\","
- "\"unit\": \"mm3/s\","
- "\"field_type\": \"integer\","
- "\"default_value\": \"12\","
- "\"key\": \"bambu_max_volspeed\"}"
- };
-
- Serial.println("Überprüfe Extrafelder...");
-
- int urlLength = sizeof(checkUrls) / sizeof(checkUrls[0]);
-
- for (uint8_t i = 0; i < urlLength; i++) {
- Serial.println();
- Serial.println("-------- Prüfe Felder für "+checkUrls[i]+" --------");
- http.begin(checkUrls[i]);
- int httpCode = http.GET();
-
- if (httpCode == HTTP_CODE_OK) {
- String payload = http.getString();
- JsonDocument doc;
- DeserializationError error = deserializeJson(doc, payload);
- if (!error) {
- String* extraFields;
- String* extraFieldData;
- u16_t extraLength;
-
- if (i == 0) {
- extraFields = spoolExtra;
- extraFieldData = spoolExtraFields;
- extraLength = sizeof(spoolExtra) / sizeof(spoolExtra[0]);
- } else {
- extraFields = filamentExtra;
- extraFieldData = filamentExtraFields;
- extraLength = sizeof(filamentExtra) / sizeof(filamentExtra[0]);
- }
-
- for (uint8_t s = 0; s < extraLength; s++) {
- bool found = false;
- for (JsonObject field : doc.as()) {
- if (field["key"].is() && field["key"] == extraFields[s]) {
- Serial.println("Feld gefunden: " + extraFields[s]);
- found = true;
- break;
- }
+ if (i == 0) {
+ extraFields = spoolExtra;
+ extraFieldData = spoolExtraFields;
+ extraLength = sizeof(spoolExtra) / sizeof(spoolExtra[0]);
+ } else {
+ extraFields = filamentExtra;
+ extraFieldData = filamentExtraFields;
+ extraLength = sizeof(filamentExtra) / sizeof(filamentExtra[0]);
}
- if (!found) {
- Serial.println("Feld nicht gefunden: " + extraFields[s]);
- // Extrafeld hinzufügen
- http.begin(checkUrls[i] + "/" + extraFields[s]);
- http.addHeader("Content-Type", "application/json");
- int httpCode = http.POST(extraFieldData[s]);
+ for (uint8_t s = 0; s < extraLength; s++) {
+ bool found = false;
+ for (JsonObject field : doc.as()) {
+ if (field["key"].is() && field["key"] == extraFields[s]) {
+ Serial.println("Feld gefunden: " + extraFields[s]);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Serial.println("Feld nicht gefunden: " + extraFields[s]);
- if (httpCode > 0) {
- // Antwortscode und -nachricht abrufen
- String response = http.getString();
- //Serial.println("HTTP-Code: " + String(httpCode));
- //Serial.println("Antwort: " + response);
- if (httpCode != HTTP_CODE_OK) {
+ // Extrafeld hinzufügen
+ http.begin(checkUrls[i] + "/" + extraFields[s]);
+ http.addHeader("Content-Type", "application/json");
+ int httpCode = http.POST(extraFieldData[s]);
+ if (httpCode > 0) {
+ // Antwortscode und -nachricht abrufen
+ String response = http.getString();
+ //Serial.println("HTTP-Code: " + String(httpCode));
+ //Serial.println("Antwort: " + response);
+ if (httpCode != HTTP_CODE_OK) {
+
+ return false;
+ }
+ } else {
+ // Fehler beim Senden der Anfrage
+ Serial.println("Fehler beim Senden der Anfrage: " + String(http.errorToString(httpCode)));
return false;
}
- } else {
- // Fehler beim Senden der Anfrage
- Serial.println("Fehler beim Senden der Anfrage: " + String(http.errorToString(httpCode)));
- return false;
+ //http.end();
}
- //http.end();
+ yield();
+ vTaskDelay(100 / portTICK_PERIOD_MS);
}
- yield();
- vTaskDelay(100 / portTICK_PERIOD_MS);
}
+ doc.clear();
}
- doc.clear();
}
+
+ Serial.println("-------- ENDE Prüfe Felder --------");
+ Serial.println();
+
+ http.end();
+
+ spoolmanExtraFieldsChecked = true;
+ return true;
+ }else{
+ return true;
}
-
- Serial.println("-------- ENDE Prüfe Felder --------");
- Serial.println();
-
- http.end();
-
- return true;
}
-bool checkSpoolmanInstance(const String& url) {
+bool checkSpoolmanInstance() {
HTTPClient http;
- String healthUrl = url + apiUrl + "/health";
+ bool returnValue = false;
- Serial.print("Überprüfe Spoolman-Instanz unter: ");
- Serial.println(healthUrl);
+ // Only do the spoolman instance check if there is no active API request going on
+ if(spoolmanApiState == API_IDLE){
+ spoolmanApiState = API_TRANSMITTING;
+ String healthUrl = spoolmanUrl + apiUrl + "/health";
- http.begin(healthUrl);
- int httpCode = http.GET();
+ Serial.print("Checking spoolman instance: ");
+ Serial.println(healthUrl);
- if (httpCode > 0) {
- if (httpCode == HTTP_CODE_OK) {
- String payload = http.getString();
- JsonDocument doc;
- DeserializationError error = deserializeJson(doc, payload);
- if (!error && doc["status"].is()) {
- const char* status = doc["status"];
- http.end();
+ http.begin(healthUrl);
+ int httpCode = http.GET();
- if (!checkSpoolmanExtraFields()) {
- Serial.println("Fehler beim Überprüfen der Extrafelder.");
+ if (httpCode > 0) {
+ if (httpCode == HTTP_CODE_OK) {
+ String payload = http.getString();
+ JsonDocument doc;
+ DeserializationError error = deserializeJson(doc, payload);
+ if (!error && doc["status"].is()) {
+ const char* status = doc["status"];
+ http.end();
- // TBD
- oledShowMessage("Spoolman Error creating Extrafields");
- vTaskDelay(2000 / portTICK_PERIOD_MS);
-
- return false;
+ if (!checkSpoolmanExtraFields()) {
+ Serial.println("Fehler beim Überprüfen der Extrafelder.");
+
+ // TBD
+ oledShowMessage("Spoolman Error creating Extrafields");
+ vTaskDelay(2000 / portTICK_PERIOD_MS);
+
+ return false;
+ }
+
+ spoolmanApiState = API_IDLE;
+ oledShowTopRow();
+ spoolmanConnected = true;
+ returnValue = strcmp(status, "healthy") == 0;
+ }else{
+ spoolmanConnected = false;
}
- spoolmanApiState = API_IDLE;
- oledShowTopRow();
- spoolmanConnected = true;
- return strcmp(status, "healthy") == 0;
+ doc.clear();
+ }else{
+ spoolmanConnected = false;
}
-
- doc.clear();
+ } else {
+ spoolmanConnected = false;
+ Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode));
}
- } else {
- Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode));
+ http.end();
+ returnValue = false;
+ spoolmanApiState = API_IDLE;
+ }else{
+ // If the check is skipped, return the previous status
+ Serial.println("Skipping spoolman healthcheck, API is active.");
+ returnValue = spoolmanConnected;
}
- http.end();
- return false;
+ Serial.println("Healthcheck completed!");
+ return returnValue;
}
bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, const String& octoTk) {
@@ -639,12 +670,13 @@ bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octo_url, con
preferences.end();
//TBD: This could be handled nicer in the future
+ spoolmanExtraFieldsChecked = false;
spoolmanUrl = url;
octoEnabled = octoOn;
octoUrl = octo_url;
octoToken = octoTk;
- return true;
+ return checkSpoolmanInstance();
}
String loadSpoolmanUrl() {
@@ -664,15 +696,10 @@ String loadSpoolmanUrl() {
bool initSpoolman() {
oledShowProgressBar(3, 7, DISPLAY_BOOT_TEXT, "Spoolman init");
spoolmanUrl = loadSpoolmanUrl();
- spoolmanUrl.trim();
- if (spoolmanUrl == "") {
- Serial.println("Keine Spoolman-URL gefunden.");
- return false;
- }
-
- bool success = checkSpoolmanInstance(spoolmanUrl);
+
+ bool success = checkSpoolmanInstance();
if (!success) {
- Serial.println("Spoolman nicht erreichbar.");
+ Serial.println("Spoolman not available");
return false;
}
diff --git a/src/api.h b/src/api.h
index 23fb6d8..4ad427f 100644
--- a/src/api.h
+++ b/src/api.h
@@ -29,7 +29,7 @@ extern String octoUrl;
extern String octoToken;
extern bool spoolmanConnected;
-bool checkSpoolmanInstance(const String& url);
+bool checkSpoolmanInstance();
bool saveSpoolmanUrl(const String& url, bool octoOn, const String& octoWh, const String& octoTk);
String loadSpoolmanUrl(); // Neue Funktion zum Laden der URL
bool checkSpoolmanExtraFields(); // Neue Funktion zum Überprüfen der Extrafelder
diff --git a/src/config.cpp b/src/config.cpp
index 359031a..60a8803 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -16,7 +16,6 @@ const uint8_t LOADCELL_DOUT_PIN = 16; //16;
const uint8_t LOADCELL_SCK_PIN = 17; //17;
const uint8_t calVal_eepromAdress = 0;
const uint16_t SCALE_LEVEL_WEIGHT = 500;
-uint16_t defaultScaleCalibrationValue = 430;
// ***** HX711
// ***** TTP223 (Touch Sensor)
diff --git a/src/config.h b/src/config.h
index 88c57c0..cd79e38 100644
--- a/src/config.h
+++ b/src/config.h
@@ -3,36 +3,39 @@
#include
-#define BAMBU_DEFAULT_AUTOSEND_TIME 60
+#define BAMBU_DEFAULT_AUTOSEND_TIME 60
+#define NVS_NAMESPACE_API "api"
+#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl"
+#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled"
+#define NVS_KEY_OCTOPRINT_URL "octoUrl"
+#define NVS_KEY_OCTOPRINT_TOKEN "octoToken"
-#define NVS_NAMESPACE_API "api"
-#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl"
-#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled"
-#define NVS_KEY_OCTOPRINT_URL "octoUrl"
-#define NVS_KEY_OCTOPRINT_TOKEN "octoToken"
+#define NVS_NAMESPACE_BAMBU "bambu"
+#define NVS_KEY_BAMBU_IP "bambuIp"
+#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode"
+#define NVS_KEY_BAMBU_SERIAL "bambuSerial"
+#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable"
+#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime"
-#define NVS_NAMESPACE_BAMBU "bambu"
-#define NVS_KEY_BAMBU_IP "bambuIp"
-#define NVS_KEY_BAMBU_ACCESSCODE "bambuCode"
-#define NVS_KEY_BAMBU_SERIAL "bambuSerial"
-#define NVS_KEY_BAMBU_AUTOSEND_ENABLE "autosendEnable"
-#define NVS_KEY_BAMBU_AUTOSEND_TIME "autosendTime"
+#define NVS_NAMESPACE_SCALE "scale"
+#define NVS_KEY_CALIBRATION "cal_value"
+#define NVS_KEY_AUTOTARE "auto_tare"
+#define SCALE_DEFAULT_CALIBRATION_VALUE 430.0f;
-#define NVS_NAMESPACE_SCALE "scale"
-#define NVS_KEY_CALIBRATION "cal_value"
-#define NVS_KEY_AUTOTARE "auto_tare"
+#define BAMBU_USERNAME "bblp"
-#define BAMBU_USERNAME "bblp"
-
-#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
-#define SCREEN_ADDRESS 0x3CU // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
-#define SCREEN_WIDTH 128U
-#define SCREEN_HEIGHT 64U
-#define SCREEN_TOP_BAR_HEIGHT 16U
-#define SCREEN_PROGRESS_BAR_HEIGHT 12U
-#define DISPLAY_BOOT_TEXT "FilaMan"
+#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
+#define SCREEN_ADDRESS 0x3CU // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
+#define SCREEN_WIDTH 128U
+#define SCREEN_HEIGHT 64U
+#define SCREEN_TOP_BAR_HEIGHT 16U
+#define SCREEN_PROGRESS_BAR_HEIGHT 12U
+#define DISPLAY_BOOT_TEXT "FilaMan"
+#define WIFI_CHECK_INTERVAL 60000U
+#define DISPLAY_UPDATE_INTERVAL 1000U
+#define SPOOLMAN_HEALTHCHECK_INTERVAL 60000U
extern const uint8_t PN532_IRQ;
extern const uint8_t PN532_RESET;
diff --git a/src/main.cpp b/src/main.cpp
index f160e95..2b75b6c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -97,7 +97,8 @@ int16_t lastWeight = 0;
// WIFI check variables
unsigned long lastWifiCheckTime = 0;
-const unsigned long wifiCheckInterval = 60000; // Überprüfe alle 60 Sekunden (60000 ms)
+unsigned long lastTopRowUpdateTime = 0;
+unsigned long lastSpoolmanHealcheckTime = 0;
// Button debounce variables
unsigned long lastButtonPress = 0;
@@ -115,17 +116,23 @@ void loop() {
}
// Überprüfe regelmäßig die WLAN-Verbindung
- if (intervalElapsed(currentMillis, lastWifiCheckTime, wifiCheckInterval))
+ if (intervalElapsed(currentMillis, lastWifiCheckTime, WIFI_CHECK_INTERVAL))
{
checkWiFiConnection();
}
// Periodic display update
- if (intervalElapsed(currentMillis, lastWifiCheckTime, 1000))
+ if (intervalElapsed(currentMillis, lastTopRowUpdateTime, DISPLAY_UPDATE_INTERVAL))
{
oledShowTopRow();
}
+ // Periodic spoolman health check
+ if (intervalElapsed(currentMillis, lastSpoolmanHealcheckTime, SPOOLMAN_HEALTHCHECK_INTERVAL))
+ {
+ checkSpoolmanInstance();
+ }
+
// Wenn Bambu auto set Spool aktiv
if (bambuCredentials.autosend_enable && autoSetToBambuSpoolId > 0)
{
@@ -156,94 +163,93 @@ void loop() {
}
}
- // Wenn Waage nicht Kalibriert
- if (scaleCalibrated == 3)
+ // If scale is not calibrated, only show a warning
+ if (!scaleCalibrated)
{
- oledShowMessage("Scale not calibrated!");
- vTaskDelay(5000 / portTICK_PERIOD_MS);
- yield();
- esp_task_wdt_reset();
-
- return;
- }
-
- // Ausgabe der Waage auf Display
- if(pauseMainTask == 0)
- {
- if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0)))
- {
- (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
+ // Do not show the warning if the calibratin process is onging
+ if(!scaleCalibrationActive){
+ oledShowMessage("Scale not calibrated");
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
}
- mainTaskWasPaused = false;
- }
- else
- {
- mainTaskWasPaused = true;
- }
-
-
- // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird
- if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING)
- {
- lastWeightReadTime = currentMillis;
-
- // Prüfen ob die Waage korrekt genullt ist
- // Abweichung von 2g ignorieren
- if (autoTare && (weight > 2 && weight < 7) || weight < -2)
+ }else{
+ // Ausgabe der Waage auf Display
+ if(pauseMainTask == 0)
{
- scale_tare_counter++;
+ if (mainTaskWasPaused || (weight != lastWeight && nfcReaderState == NFC_IDLE && (!bambuCredentials.autosend_enable || autoSetToBambuSpoolId == 0)))
+ {
+ (weight < 2) ? ((weight < -2) ? oledShowMessage("!! -0") : oledShowWeight(0)) : oledShowWeight(weight);
+ }
+ mainTaskWasPaused = false;
}
else
{
- scale_tare_counter = 0;
+ mainTaskWasPaused = true;
}
- // Prüfen ob das Gewicht gleich bleibt und dann senden
- if (abs(weight - lastWeight) <= 2 && weight > 5)
+
+ // Wenn Timer abgelaufen und nicht gerade ein RFID-Tag geschrieben wird
+ if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState < NFC_WRITING)
{
- weigthCouterToApi++;
- }
- else
+ lastWeightReadTime = currentMillis;
+
+ // Prüfen ob die Waage korrekt genullt ist
+ // Abweichung von 2g ignorieren
+ if (autoTare && (weight > 2 && weight < 7) || weight < -2)
+ {
+ scale_tare_counter++;
+ }
+ else
+ {
+ scale_tare_counter = 0;
+ }
+
+ // Prüfen ob das Gewicht gleich bleibt und dann senden
+ if (abs(weight - lastWeight) <= 2 && weight > 5)
+ {
+ weigthCouterToApi++;
+ }
+ else
+ {
+ weigthCouterToApi = 0;
+ weightSend = 0;
+ }
+ }
+
+ // reset weight counter after writing tag
+ // TBD: what exactly is the logic behind this?
+ if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS)
{
weigthCouterToApi = 0;
- weightSend = 0;
}
- }
+
+ lastWeight = weight;
- // reset weight counter after writing tag
- // TBD: what exactly is the logic behind this?
- if (currentMillis - lastWeightReadTime >= weightReadInterval && nfcReaderState != NFC_IDLE && nfcReaderState != NFC_READ_SUCCESS)
- {
- weigthCouterToApi = 0;
- }
-
- lastWeight = weight;
+ // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden
+ if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS && tagProcessed == false && spoolmanApiState == API_IDLE) {
+ // set the current tag as processed to prevent it beeing processed again
+ tagProcessed = true;
- // Wenn ein Tag mit SM id erkannte wurde und der Waage Counter anspricht an SM Senden
- if (activeSpoolId != "" && weigthCouterToApi > 3 && weightSend == 0 && nfcReaderState == NFC_READ_SUCCESS && tagProcessed == false && spoolmanApiState == API_IDLE) {
- // set the current tag as processed to prevent it beeing processed again
- tagProcessed = true;
-
- if (updateSpoolWeight(activeSpoolId, weight))
- {
- weightSend = 1;
-
+ if (updateSpoolWeight(activeSpoolId, weight))
+ {
+ weightSend = 1;
+
+ }
+ else
+ {
+ oledShowIcon("failed");
+ vTaskDelay(2000 / portTICK_PERIOD_MS);
+ }
}
- else
- {
- oledShowIcon("failed");
- vTaskDelay(2000 / portTICK_PERIOD_MS);
- }
- }
- if(sendOctoUpdate && spoolmanApiState == API_IDLE){
- autoSetToBambuSpoolId = activeSpoolId.toInt();
+ if(sendOctoUpdate && spoolmanApiState == API_IDLE){
+ autoSetToBambuSpoolId = activeSpoolId.toInt();
- if(octoEnabled)
- {
- updateSpoolOcto(autoSetToBambuSpoolId);
+ if(octoEnabled)
+ {
+ updateSpoolOcto(autoSetToBambuSpoolId);
+ }
+ sendOctoUpdate = false;
}
- sendOctoUpdate = false;
}
esp_task_wdt_reset();
diff --git a/src/nfc.cpp b/src/nfc.cpp
index fe1a486..5a8bdc1 100644
--- a/src/nfc.cpp
+++ b/src/nfc.cpp
@@ -8,6 +8,7 @@
#include "esp_task_wdt.h"
#include "scale.h"
#include "bambu.h"
+#include "main.h"
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
@@ -20,6 +21,8 @@ String lastSpoolId = "";
String nfcJsonData = "";
bool tagProcessed = false;
volatile bool pauseBambuMqttTask = false;
+volatile bool nfcReadingTaskSuspendRequest = false;
+volatile bool nfcReadingTaskSuspendState = false;
struct NfcWriteParameterType {
bool tagType;
@@ -238,8 +241,6 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage) {
Serial.println("SPOOL-ID gefunden: " + doc["sm_id"].as());
activeSpoolId = doc["sm_id"].as();
lastSpoolId = activeSpoolId;
-
- Serial.println("Api state: " + String(spoolmanApiState));
}
else if(doc["location"].is() && doc["location"] != "")
{
@@ -278,19 +279,21 @@ void writeJsonToTag(void *parameter) {
Serial.println(params->payload);
nfcReaderState = NFC_WRITING;
- vTaskSuspend(RfidReaderTask);
- vTaskDelay(50 / portTICK_PERIOD_MS);
+
+ // First request the reading task to be suspended and than wait until it responds
+ nfcReadingTaskSuspendRequest = true;
+ while(nfcReadingTaskSuspendState == false){
+ vTaskDelay(100 / portTICK_PERIOD_MS);
+ }
//pauseBambuMqttTask = true;
// aktualisieren der Website wenn sich der Status ändert
sendNfcData();
vTaskDelay(100 / portTICK_PERIOD_MS);
- Serial.println("CP 1");
// Wait 10sec for tag
uint8_t success = 0;
String uidString = "";
for (uint16_t i = 0; i < 20; i++) {
- Serial.println("CP 2");
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength;
// yield before potentially waiting for 400ms
@@ -298,7 +301,6 @@ void writeJsonToTag(void *parameter) {
esp_task_wdt_reset();
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400);
if (success) {
- Serial.println("CP 3.1");
for (uint8_t i = 0; i < uidLength; i++) {
//TBD: Rework to remove all the string operations
uidString += String(uid[i], HEX);
@@ -308,8 +310,6 @@ void writeJsonToTag(void *parameter) {
}
foundNfcTag(nullptr, success);
break;
- }else{
- Serial.println("CP 3.2");
}
yield();
@@ -372,7 +372,7 @@ void writeJsonToTag(void *parameter) {
sendWriteResult(nullptr, success);
sendNfcData();
- vTaskResume(RfidReaderTask);
+ nfcReadingTaskSuspendRequest = false;
pauseBambuMqttTask = false;
vTaskDelete(NULL);
@@ -384,7 +384,7 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) {
parameters->payload = strdup(payload);
// Task nicht mehrfach starten
- if (nfcReaderState == NFC_IDLE) {
+ if (nfcReaderState == NFC_IDLE || nfcReaderState == NFC_READ_ERROR || nfcReaderState == NFC_READ_SUCCESS) {
oledShowProgressBar(0, 1, "Write Tag", "Place tag now");
// Erstelle die Task
xTaskCreate(
@@ -405,15 +405,16 @@ void scanRfidTask(void * parameter) {
Serial.println("RFID Task gestartet");
for(;;) {
// Wenn geschrieben wird Schleife aussetzen
- if (nfcReaderState != NFC_WRITING)
+ if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest && !booting)
{
+ nfcReadingTaskSuspendState = false;
yield();
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength;
- success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000);
+ success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500);
foundNfcTag(nullptr, success);
@@ -430,8 +431,8 @@ void scanRfidTask(void * parameter) {
oledShowProgressBar(0, octoEnabled?5:4, "Reading", "Detecting tag");
- vTaskDelay(500 / portTICK_PERIOD_MS);
-
+ //vTaskDelay(500 / portTICK_PERIOD_MS);
+
if (uidLength == 7)
{
uint16_t tagSize = readTagSize();
@@ -487,7 +488,7 @@ void scanRfidTask(void * parameter) {
}
}
- if (!success && nfcReaderState != NFC_IDLE)
+ if (!success && nfcReaderState != NFC_IDLE && !nfcReadingTaskSuspendRequest)
{
nfcReaderState = NFC_IDLE;
//uidString = "";
@@ -500,6 +501,12 @@ void scanRfidTask(void * parameter) {
// aktualisieren der Website wenn sich der Status ändert
sendNfcData();
}
+ else
+ {
+ nfcReadingTaskSuspendState = true;
+ Serial.println("NFC Reading disabled");
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+ }
yield();
}
}
diff --git a/src/scale.cpp b/src/scale.cpp
index 4be30c7..201618d 100644
--- a/src/scale.cpp
+++ b/src/scale.cpp
@@ -17,8 +17,9 @@ uint8_t weigthCouterToApi = 0;
uint8_t scale_tare_counter = 0;
bool scaleTareRequest = false;
uint8_t pauseMainTask = 0;
-uint8_t scaleCalibrated = 1;
+bool scaleCalibrated;
bool autoTare = true;
+bool scaleCalibrationActive = false;
// ##### Funktionen für Waage #####
uint8_t setAutoTare(bool autoTareValue) {
@@ -88,7 +89,13 @@ void start_scale(bool touchSensorConnected) {
// NVS lesen
Preferences preferences;
preferences.begin(NVS_NAMESPACE_SCALE, true); // true = readonly
- calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION, defaultScaleCalibrationValue);
+ if(preferences.isKey(NVS_KEY_CALIBRATION)){
+ calibrationValue = preferences.getFloat(NVS_KEY_CALIBRATION);
+ scaleCalibrated = true;
+ }else{
+ calibrationValue = SCALE_DEFAULT_CALIBRATION_VALUE;
+ scaleCalibrated = false;
+ }
// auto Tare
// Wenn Touch Sensor verbunden, dann autoTare auf false setzen
@@ -103,18 +110,6 @@ void start_scale(bool touchSensorConnected) {
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
- if (isnan(calibrationValue) || calibrationValue < 1) {
- calibrationValue = defaultScaleCalibrationValue;
- scaleCalibrated = 0;
-
- oledShowMessage("Scale not calibrated!");
- for (uint16_t i = 0; i < 50000; i++) {
- yield();
- vTaskDelay(pdMS_TO_TICKS(1));
- esp_task_wdt_reset();
- }
- }
-
oledShowProgressBar(6, 7, DISPLAY_BOOT_TEXT, "Tare scale");
for (uint16_t i = 0; i < 2000; i++) {
yield();
@@ -152,6 +147,8 @@ uint8_t calibrate_scale() {
uint8_t returnState = 0;
float newCalibrationValue;
+ scaleCalibrationActive = true;
+
vTaskSuspend(RfidReaderTask);
vTaskSuspend(ScaleTask);
@@ -228,6 +225,7 @@ uint8_t calibrate_scale() {
esp_task_wdt_reset();
}
+ scaleCalibrated = true;
returnState = 1;
}
else
@@ -262,6 +260,7 @@ uint8_t calibrate_scale() {
vTaskResume(ScaleTask);
pauseBambuMqttTask = false;
pauseMainTask = 0;
+ scaleCalibrationActive = false;
return returnState;
}
diff --git a/src/scale.h b/src/scale.h
index 96f59a4..c38583a 100644
--- a/src/scale.h
+++ b/src/scale.h
@@ -15,8 +15,9 @@ extern uint8_t weigthCouterToApi;
extern uint8_t scale_tare_counter;
extern uint8_t scaleTareRequest;
extern uint8_t pauseMainTask;
-extern uint8_t scaleCalibrated;
+extern bool scaleCalibrated;
extern bool autoTare;
+extern bool scaleCalibrationActive;
extern TaskHandle_t ScaleTask;