Merge pull request #45 from janecker/nfc_write_improvements

Nfc write improvements
This commit is contained in:
2025-08-10 14:38:11 +02:00
committed by GitHub
9 changed files with 428 additions and 377 deletions

View File

@@ -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 += `<p><strong>Spoolman ID:</strong> ${data.sm_id || 'No Spoolman ID'}</p>`;
html += `<p><strong>Spoolman ID:</strong> ${data.sm_id} (<a href="${spoolmanUrl}/spool/show/${data.sm_id}">Open in Spoolman</a>)</p>`;
}
else if(data.location)
{
@@ -618,6 +622,7 @@ function updateNfcData(data) {
}
function writeNfcTag() {
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.');
@@ -666,9 +671,11 @@ function writeNfcTag() {
} else {
alert('Not connected to Server. Please check connection.');
}
}
}
function writeLocationNfcTag() {
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.');
@@ -679,6 +686,7 @@ function writeLocationNfcTag() {
location: String(selectedText)
};
if (socket?.readyState === WebSocket.OPEN) {
const writeButton = document.getElementById("writeLocationNfcButton");
writeButton.classList.add("writing");
@@ -691,6 +699,7 @@ function writeLocationNfcTag() {
} else {
alert('Not connected to Server. Please check connection.');
}
}
}
function handleWriteNfcTagResponse(success) {

View File

@@ -5,7 +5,7 @@
#include <Preferences.h>
#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,7 +326,8 @@ uint8_t updateSpoolLocation(String spoolId, String location){
params->spoolsUrl = spoolsUrl;
params->updatePayload = updatePayload;
if(spoolmanApiState == API_IDLE){
if(apiTask == nullptr){
// Erstelle die Task
BaseType_t result = xTaskCreate(
sendToApi, // Task-Funktion
@@ -327,9 +335,8 @@ uint8_t updateSpoolLocation(String spoolId, String location){
6144, // Stackgröße in Bytes
(void*)params, // Parameter
0, // Priorität
NULL // Task-Handle (nicht benötigt)
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,6 +442,8 @@ bool updateSpoolBambuData(String payload) {
// #### Spoolman init
bool checkSpoolmanExtraFields() {
// Only check extra fields if they have not been checked before
if(!spoolmanExtraFieldsChecked){
HTTPClient http;
String checkUrls[] = {
spoolmanUrl + apiUrl + "/field/spool",
@@ -582,14 +591,23 @@ bool checkSpoolmanExtraFields() {
http.end();
spoolmanExtraFieldsChecked = true;
return true;
}else{
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: ");
// 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";
Serial.print("Checking spoolman instance: ");
Serial.println(healthUrl);
http.begin(healthUrl);
@@ -617,16 +635,29 @@ bool checkSpoolmanInstance(const String& url) {
spoolmanApiState = API_IDLE;
oledShowTopRow();
spoolmanConnected = true;
return strcmp(status, "healthy") == 0;
returnValue = strcmp(status, "healthy") == 0;
}else{
spoolmanConnected = false;
}
doc.clear();
}else{
spoolmanConnected = false;
}
} else {
spoolmanConnected = false;
Serial.println("Error contacting spoolman instance! HTTP Code: " + String(httpCode));
}
http.end();
return false;
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;
}
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;
}

View File

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

View File

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

View File

@@ -5,7 +5,6 @@
#define BAMBU_DEFAULT_AUTOSEND_TIME 60
#define NVS_NAMESPACE_API "api"
#define NVS_KEY_SPOOLMAN_URL "spoolmanUrl"
#define NVS_KEY_OCTOPRINT_ENABLED "octoEnabled"
@@ -22,6 +21,7 @@
#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 BAMBU_USERNAME "bblp"
@@ -33,6 +33,9 @@
#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;

View File

@@ -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,17 +163,15 @@ 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;
// Do not show the warning if the calibratin process is onging
if(!scaleCalibrationActive){
oledShowMessage("Scale not calibrated");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}else{
// Ausgabe der Waage auf Display
if(pauseMainTask == 0)
{
@@ -245,6 +250,7 @@ void loop() {
}
sendOctoUpdate = false;
}
}
esp_task_wdt_reset();
}

View File

@@ -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<String>());
activeSpoolId = doc["sm_id"].as<String>();
lastSpoolId = activeSpoolId;
Serial.println("Api state: " + String(spoolmanApiState));
}
else if(doc["location"].is<String>() && 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,7 +431,7 @@ 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)
{
@@ -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();
}
}

View File

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

View File

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