Compare commits
	
		
			7 Commits
		
	
	
		
			v1.5.12-be
			...
			v1.5.12-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0d3503f4f1 | |||
| 1460c6e5f9 | |||
| fef7e5aa4b | |||
| bda8c3dd98 | |||
| 8702469020 | |||
| 2a0f999f3b | |||
| c89adb6256 | 
							
								
								
									
										13
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,18 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## [1.5.12-beta16] - 2025-08-29 | ||||||
|  | ### Changed | ||||||
|  | - update platformio.ini for beta version v1.5.12-beta16 | ||||||
|  | - Refactor NFC interface handling and improve error diagnostics | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## [1.5.12-beta15] - 2025-08-29 | ||||||
|  | ### Changed | ||||||
|  | - update platformio.ini for beta version v1.5.12-beta15 | ||||||
|  | - enhance NFC write operation diagnostics and improve error handling | ||||||
|  | - enhance NFC write operation handling and prevent tag operations during write | ||||||
|  |  | ||||||
|  |  | ||||||
| ## [1.5.12-beta14] - 2025-08-29 | ## [1.5.12-beta14] - 2025-08-29 | ||||||
| ### Changed | ### Changed | ||||||
| - update platformio.ini for beta version v1.5.12-beta14 | - update platformio.ini for beta version v1.5.12-beta14 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| ; https://docs.platformio.org/page/projectconf.html | ; https://docs.platformio.org/page/projectconf.html | ||||||
|  |  | ||||||
| [common] | [common] | ||||||
| version = "1.5.12-beta14" | version = "1.5.12-beta16" | ||||||
| to_old_version = "1.5.0" | to_old_version = "1.5.0" | ||||||
|  |  | ||||||
| ## | ## | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								src/api.cpp
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								src/api.cpp
									
									
									
									
									
								
							| @@ -9,18 +9,6 @@ | |||||||
| #include <time.h> | #include <time.h> | ||||||
| volatile spoolmanApiStateType spoolmanApiState = API_IDLE; | volatile spoolmanApiStateType spoolmanApiState = API_IDLE; | ||||||
|  |  | ||||||
| // Returns current date and time in ISO8601 format |  | ||||||
| String getCurrentDateISO8601() { |  | ||||||
|     struct tm timeinfo; |  | ||||||
|     if(!getLocalTime(&timeinfo)) { |  | ||||||
|         Serial.println("Failed to obtain time"); |  | ||||||
|         return "1970-01-01T00:00:00Z"; |  | ||||||
|     } |  | ||||||
|     char timeStringBuff[25]; |  | ||||||
|     strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%SZ", &timeinfo); |  | ||||||
|     return String(timeStringBuff); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //bool spoolman_connected = false; | //bool spoolman_connected = false; | ||||||
| String spoolmanUrl = ""; | String spoolmanUrl = ""; | ||||||
| bool octoEnabled = false; | bool octoEnabled = false; | ||||||
| @@ -627,7 +615,6 @@ uint16_t createVendor(String vendor) { | |||||||
|     JsonDocument vendorDoc; |     JsonDocument vendorDoc; | ||||||
|     vendorDoc["name"] = vendor; |     vendorDoc["name"] = vendor; | ||||||
|     vendorDoc["comment"] = "automatically generated"; |     vendorDoc["comment"] = "automatically generated"; | ||||||
|     vendorDoc["empty_spool_weight"] = 180; |  | ||||||
|     vendorDoc["external_id"] = vendor; |     vendorDoc["external_id"] = vendor; | ||||||
|  |  | ||||||
|     String vendorPayload; |     String vendorPayload; | ||||||
| @@ -748,34 +735,34 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) { | |||||||
|  |  | ||||||
|     // Create JSON payload for filament creation |     // Create JSON payload for filament creation | ||||||
|     JsonDocument filamentDoc; |     JsonDocument filamentDoc; | ||||||
|     filamentDoc["name"] = payload["color_name"].as<String>(); |     filamentDoc["name"] = payload["cn"].as<String>(); | ||||||
|     filamentDoc["vendor_id"] = String(vendorId); |     filamentDoc["vendor_id"] = String(vendorId); | ||||||
|     filamentDoc["material"] = payload["type"].as<String>(); |     filamentDoc["material"] = payload["t"].as<String>(); | ||||||
|     filamentDoc["density"] = (payload["density"].is<String>() && payload["density"].as<String>().length() > 0) ? payload["density"].as<String>() : "1.24"; |     filamentDoc["density"] = (payload["de"].is<String>() && payload["de"].as<String>().length() > 0) ? payload["de"].as<String>() : "1.24"; | ||||||
|     filamentDoc["diameter"] = (payload["diameter"].is<String>() && payload["diameter"].as<String>().length() > 0) ? payload["diameter"].as<String>() : "1.75"; |     filamentDoc["diameter"] = (payload["di"].is<String>() && payload["di"].as<String>().length() > 0) ? payload["di"].as<String>() : "1.75"; | ||||||
|     filamentDoc["weight"] = String(weight); |     filamentDoc["weight"] = String(weight); | ||||||
|     filamentDoc["spool_weight"] = payload["spool_weight"].as<String>(); |     filamentDoc["spool_weight"] = payload["sw"].as<String>(); | ||||||
|     filamentDoc["article_number"] = payload["artnr"].as<String>(); |     filamentDoc["article_number"] = payload["an"].as<String>(); | ||||||
|     filamentDoc["settings_extruder_temp"] = payload["extruder_temp"].is<String>() ? payload["extruder_temp"].as<String>() : ""; |     filamentDoc["settings_extruder_temp"] = payload["et"].is<String>() ? payload["et"].as<String>() : ""; | ||||||
|     filamentDoc["settings_bed_temp"] = payload["bed_temp"].is<String>() ? payload["bed_temp"].as<String>() : ""; |     filamentDoc["settings_bed_temp"] = payload["bt"].is<String>() ? payload["bt"].as<String>() : ""; | ||||||
|  |  | ||||||
|     if (payload["artnr"].is<String>()) |     if (payload["an"].is<String>()) | ||||||
|     { |     { | ||||||
|         filamentDoc["external_id"] = payload["artnr"].as<String>(); |         filamentDoc["external_id"] = payload["an"].as<String>(); | ||||||
|         filamentDoc["comment"] = payload["url"].is<String>() ? payload["url"].as<String>() + payload["artnr"].as<String>() : "automatically generated"; |         filamentDoc["comment"] = payload["u"].is<String>() ? payload["u"].as<String>() + payload["an"].as<String>() : "automatically generated"; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         filamentDoc["comment"] = payload["url"].is<String>() ? payload["url"].as<String>() : "automatically generated"; |         filamentDoc["comment"] = payload["u"].is<String>() ? payload["u"].as<String>() : "automatically generated"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (payload["multi_color_hexes"].is<String>()) { |     if (payload["mc"].is<String>()) { | ||||||
|         filamentDoc["multi_color_hexes"] = payload["multi_color_hexes"].as<String>(); |         filamentDoc["multi_color_hexes"] = payload["mc"].as<String>(); | ||||||
|         filamentDoc["multi_color_direction"] = payload["multi_color_direction"].is<String>() ? payload["multi_color_direction"].as<String>() : ""; |         filamentDoc["multi_color_direction"] = payload["mcd"].is<String>() ? payload["mcd"].as<String>() : ""; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         filamentDoc["color_hex"] = (payload["color_hex"].is<String>() && payload["color_hex"].as<String>().length() >= 6) ? payload["color_hex"].as<String>() : "FFFFFF"; |         filamentDoc["color_hex"] = (payload["c"].is<String>() && payload["c"].as<String>().length() >= 6) ? payload["c"].as<String>() : "FFFFFF"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     String filamentPayload; |     String filamentPayload; | ||||||
| @@ -883,17 +870,14 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo | |||||||
|     String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; |     String spoolsUrl = spoolmanUrl + apiUrl + "/spool"; | ||||||
|     Serial.print("Create spool with URL: "); |     Serial.print("Create spool with URL: "); | ||||||
|     Serial.println(spoolsUrl); |     Serial.println(spoolsUrl); | ||||||
|     //String currentDate = getCurrentDateISO8601(); |  | ||||||
|  |  | ||||||
|     // Create JSON payload for spool creation |     // Create JSON payload for spool creation | ||||||
|     JsonDocument spoolDoc; |     JsonDocument spoolDoc; | ||||||
|     //spoolDoc["first_used"] = String(currentDate); |  | ||||||
|     //spoolDoc["last_used"] = String(currentDate); |  | ||||||
|     spoolDoc["filament_id"] = String(filamentId); |     spoolDoc["filament_id"] = String(filamentId); | ||||||
|     spoolDoc["initial_weight"] = weight > 10 ? String(weight-payload["spool_weight"].as<int>()) : "1000"; |     spoolDoc["initial_weight"] = weight > 10 ? String(weight - payload["sw"].as<int>()) : "1000"; | ||||||
|     spoolDoc["spool_weight"] = (payload["spool_weight"].is<String>() && payload["spool_weight"].as<String>().length() > 0) ? payload["spool_weight"].as<String>() : "180"; |     spoolDoc["spool_weight"] = (payload["sw"].is<String>() && payload["sw"].as<String>().length() > 0) ? payload["sw"].as<String>() : "180"; | ||||||
|     spoolDoc["remaining_weight"] = (payload["weight"].is<String>() && payload["weight"].as<String>().length() > 0) ? payload["weight"].as<String>() : "1000"; |     spoolDoc["remaining_weight"] = spoolDoc["initial_weight"]; | ||||||
|     spoolDoc["lot_nr"] = (payload["lotnr"].is<String>() && payload["lotnr"].as<String>().length() > 0) ? payload["lotnr"].as<String>() : ""; |     spoolDoc["lot_nr"] = (payload["an"].is<String>() && payload["an"].as<String>().length() > 0) ? payload["an"].as<String>() : ""; | ||||||
|     spoolDoc["comment"] = "automatically generated"; |     spoolDoc["comment"] = "automatically generated"; | ||||||
|     spoolDoc["extra"]["nfc_id"] = "\"" + uidString + "\""; |     spoolDoc["extra"]["nfc_id"] = "\"" + uidString + "\""; | ||||||
|  |  | ||||||
| @@ -942,13 +926,15 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo | |||||||
|     // Create optimized JSON structure with sm_id at the beginning for fast-path detection |     // Create optimized JSON structure with sm_id at the beginning for fast-path detection | ||||||
|     JsonDocument optimizedPayload; |     JsonDocument optimizedPayload; | ||||||
|     optimizedPayload["sm_id"] = String(createdSpoolId);  // Place sm_id first for fast scanning |     optimizedPayload["sm_id"] = String(createdSpoolId);  // Place sm_id first for fast scanning | ||||||
|  |     optimizedPayload["b"] = payload["b"].as<String>(); | ||||||
|  |     optimizedPayload["cn"] = payload["an"].as<String>(); | ||||||
|      |      | ||||||
|     // Copy all other fields from original payload (excluding sm_id if it exists) |     // Copy all other fields from original payload (excluding sm_id if it exists) | ||||||
|     for (JsonPair kv : payload.as<JsonObject>()) { |     //for (JsonPair kv : payload.as<JsonObject>()) { | ||||||
|         if (strcmp(kv.key().c_str(), "sm_id") != 0) {  // Skip sm_id to avoid duplication |     //    if (strcmp(kv.key().c_str(), "sm_id") != 0) {  // Skip sm_id to avoid duplication | ||||||
|             optimizedPayload[kv.key()] = kv.value(); |     //        optimizedPayload[kv.key()] = kv.value(); | ||||||
|         } |     //    } | ||||||
|     } |     //} | ||||||
|      |      | ||||||
|     String payloadString; |     String payloadString; | ||||||
|     serializeJson(optimizedPayload, payloadString); |     serializeJson(optimizedPayload, payloadString); | ||||||
|   | |||||||
							
								
								
									
										750
									
								
								src/nfc.cpp
									
									
									
									
									
								
							
							
						
						
									
										750
									
								
								src/nfc.cpp
									
									
									
									
									
								
							| @@ -23,6 +23,7 @@ bool tagProcessed = false; | |||||||
| volatile bool pauseBambuMqttTask = false; | volatile bool pauseBambuMqttTask = false; | ||||||
| volatile bool nfcReadingTaskSuspendRequest = false; | volatile bool nfcReadingTaskSuspendRequest = false; | ||||||
| volatile bool nfcReadingTaskSuspendState = false; | volatile bool nfcReadingTaskSuspendState = false; | ||||||
|  | volatile bool nfcWriteInProgress = false; // Prevent any tag operations during write | ||||||
|  |  | ||||||
| struct NfcWriteParameterType { | struct NfcWriteParameterType { | ||||||
|   bool tagType; |   bool tagType; | ||||||
| @@ -408,49 +409,212 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|  |  | ||||||
|   Serial.println("✓ Payload passt in den Tag - Schreibvorgang wird fortgesetzt"); |   Serial.println("✓ Payload passt in den Tag - Schreibvorgang wird fortgesetzt"); | ||||||
|  |  | ||||||
|   // STEP 1: Read current tag content for debugging |   // STEP 1: NFC Interface Reset and Reinitialization | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|   Serial.println("=== SCHRITT 1: AKTUELLER TAG-INHALT ==="); |   Serial.println("=== SCHRITT 1: NFC-INTERFACE RESET UND NEUINITIALISIERUNG ==="); | ||||||
|   uint8_t currentContent[64]; // Read first 16 pages |  | ||||||
|   memset(currentContent, 0, 64); |  | ||||||
|    |    | ||||||
|   for (uint8_t page = 4; page < 20; page++) { |   // First, check if the NFC interface is working at all | ||||||
|     uint8_t pageData[4]; |   Serial.println("Teste aktuellen NFC-Interface-Zustand..."); | ||||||
|     if (nfc.ntag2xx_ReadPage(page, pageData)) { |    | ||||||
|       memcpy(¤tContent[(page-4)*4], pageData, 4); |   // Try to read capability container (which worked during detection) | ||||||
|       Serial.print("Seite "); |   uint8_t ccTest[4]; | ||||||
|       Serial.print(page); |   bool ccReadable = nfc.ntag2xx_ReadPage(3, ccTest); | ||||||
|       Serial.print(": "); |   Serial.print("Capability Container (Seite 3) lesbar: "); | ||||||
|  |   Serial.println(ccReadable ? "✓" : "❌"); | ||||||
|  |    | ||||||
|  |   if (!ccReadable) { | ||||||
|  |     Serial.println("❌ NFC-Interface ist nicht funktionsfähig - führe Reset durch"); | ||||||
|  |      | ||||||
|  |     // Perform NFC interface reset and reinitialization | ||||||
|  |     Serial.println("Führe NFC-Interface Reset durch..."); | ||||||
|  |      | ||||||
|  |     // Step 1: Try to reinitialize the NFC interface completely | ||||||
|  |     Serial.println("1. Neuinitialisierung des PN532..."); | ||||||
|  |      | ||||||
|  |     // Reinitialize the PN532 | ||||||
|  |     nfc.begin(); | ||||||
|  |     vTaskDelay(500 / portTICK_PERIOD_MS); // Give it time to initialize | ||||||
|  |      | ||||||
|  |     // Check firmware version to ensure communication is working | ||||||
|  |     uint32_t versiondata = nfc.getFirmwareVersion(); | ||||||
|  |     if (versiondata) { | ||||||
|  |       Serial.print("PN532 Firmware Version: 0x"); | ||||||
|  |       Serial.println(versiondata, HEX); | ||||||
|  |       Serial.println("✓ PN532 Kommunikation wiederhergestellt"); | ||||||
|  |     } else { | ||||||
|  |       Serial.println("❌ PN532 Kommunikation fehlgeschlagen"); | ||||||
|  |       oledShowMessage("NFC Reset failed"); | ||||||
|  |       vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // Step 2: Reconfigure SAM | ||||||
|  |     Serial.println("2. SAM-Konfiguration..."); | ||||||
|  |     nfc.SAMConfig(); | ||||||
|  |     vTaskDelay(200 / portTICK_PERIOD_MS); | ||||||
|  |      | ||||||
|  |     // Step 3: Re-detect the tag | ||||||
|  |     Serial.println("3. Tag-Wiedererkennung..."); | ||||||
|  |     uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; | ||||||
|  |     uint8_t uidLength; | ||||||
|  |     bool tagRedetected = false; | ||||||
|  |      | ||||||
|  |     for (int attempts = 0; attempts < 5; attempts++) { | ||||||
|  |       Serial.print("Tag-Erkennungsversuch "); | ||||||
|  |       Serial.print(attempts + 1); | ||||||
|  |       Serial.print("/5... "); | ||||||
|  |        | ||||||
|  |       if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000)) { | ||||||
|  |         Serial.println("✓"); | ||||||
|  |         tagRedetected = true; | ||||||
|  |         break; | ||||||
|  |       } else { | ||||||
|  |         Serial.println("❌"); | ||||||
|  |         vTaskDelay(300 / portTICK_PERIOD_MS); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (!tagRedetected) { | ||||||
|  |       Serial.println("❌ Tag konnte nach Reset nicht wiedererkannt werden"); | ||||||
|  |       oledShowMessage("Tag lost after reset"); | ||||||
|  |       vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     Serial.println("✓ Tag erfolgreich wiedererkannt"); | ||||||
|  |      | ||||||
|  |     // Step 4: Test basic page reading | ||||||
|  |     Serial.println("4. Test der Grundfunktionalität..."); | ||||||
|  |     vTaskDelay(200 / portTICK_PERIOD_MS); // Give interface time to stabilize | ||||||
|  |      | ||||||
|  |     ccReadable = nfc.ntag2xx_ReadPage(3, ccTest); | ||||||
|  |     Serial.print("Capability Container nach Reset lesbar: "); | ||||||
|  |     Serial.println(ccReadable ? "✓" : "❌"); | ||||||
|  |      | ||||||
|  |     if (!ccReadable) { | ||||||
|  |       Serial.println("❌ NFC-Interface funktioniert nach Reset immer noch nicht"); | ||||||
|  |       oledShowMessage("NFC still broken"); | ||||||
|  |       vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     Serial.println("✓ NFC-Interface erfolgreich wiederhergestellt"); | ||||||
|  |   } else { | ||||||
|  |     Serial.println("✓ NFC-Interface ist funktionsfähig"); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   // Display CC content for debugging | ||||||
|  |   if (ccReadable) { | ||||||
|  |     Serial.print("CC Inhalt: "); | ||||||
|  |     for (int i = 0; i < 4; i++) { | ||||||
|  |       if (ccTest[i] < 0x10) Serial.print("0"); | ||||||
|  |       Serial.print(ccTest[i], HEX); | ||||||
|  |       Serial.print(" "); | ||||||
|  |     } | ||||||
|  |     Serial.println(); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   Serial.println("=== SCHRITT 2: INTERFACE-FUNKTIONSTEST ==="); | ||||||
|  |    | ||||||
|  |   // Test a few critical pages to ensure stable operation | ||||||
|  |   uint8_t testData[4]; | ||||||
|  |   bool basicPagesReadable = true; | ||||||
|  |    | ||||||
|  |   for (uint8_t testPage = 0; testPage <= 6; testPage++) { | ||||||
|  |     bool readable = nfc.ntag2xx_ReadPage(testPage, testData); | ||||||
|  |     Serial.print("Seite "); | ||||||
|  |     Serial.print(testPage); | ||||||
|  |     Serial.print(": "); | ||||||
|  |     if (readable) { | ||||||
|  |       Serial.print("✓ - "); | ||||||
|       for (int i = 0; i < 4; i++) { |       for (int i = 0; i < 4; i++) { | ||||||
|         if (pageData[i] < 0x10) Serial.print("0"); |         if (testData[i] < 0x10) Serial.print("0"); | ||||||
|         Serial.print(pageData[i], HEX); |         Serial.print(testData[i], HEX); | ||||||
|         Serial.print(" "); |         Serial.print(" "); | ||||||
|       } |       } | ||||||
|       Serial.println(); |       Serial.println(); | ||||||
|     } else { |     } else { | ||||||
|       Serial.print("Fehler beim Lesen von Seite "); |       Serial.println("❌ - Nicht lesbar"); | ||||||
|       Serial.println(page); |       if (testPage >= 3 && testPage <= 6) { // Critical pages for NDEF | ||||||
|  |         basicPagesReadable = false; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|  |     vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between reads | ||||||
|   } |   } | ||||||
|   Serial.println("========================================="); |  | ||||||
|    |    | ||||||
|   // STEP 2: Simple write test - write one test page |   if (!basicPagesReadable) { | ||||||
|  |     Serial.println("❌ KRITISCHER FEHLER: Grundlegende NDEF-Seiten nicht lesbar!"); | ||||||
|  |     Serial.println("Tag oder Interface ist defekt"); | ||||||
|  |     oledShowMessage("Tag/Interface defect"); | ||||||
|  |     vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   Serial.println("✓ Alle kritischen Seiten sind lesbar"); | ||||||
|  |   Serial.println("==================================================="); | ||||||
|  |  | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|   Serial.println("=== SCHRITT 2: SCHREIBTEST ==="); |   Serial.println("=== SCHRITT 3: SCHREIBBEREITSCHAFTSTEST ==="); | ||||||
|   uint8_t testPage[4] = {0xAA, 0xBB, 0xCC, 0xDD}; // Test pattern |  | ||||||
|    |    | ||||||
|   if (!nfc.ntag2xx_WritePage(10, testPage)) { // Use page 10 for test |   // Test write capabilities before attempting the full write | ||||||
|     Serial.println("FEHLER: Einfacher Schreibtest fehlgeschlagen!"); |   Serial.println("Teste Schreibfähigkeiten des Tags..."); | ||||||
|  |    | ||||||
|  |   uint8_t testPage[4] = {0xAA, 0xBB, 0xCC, 0xDD}; // Test pattern | ||||||
|  |   uint8_t originalPage[4]; // Store original content | ||||||
|  |    | ||||||
|  |   // First, read original content of test page | ||||||
|  |   if (!nfc.ntag2xx_ReadPage(10, originalPage)) { | ||||||
|  |     Serial.println("FEHLER: Kann Testseite nicht lesen für Backup"); | ||||||
|  |     oledShowMessage("Test page read error"); | ||||||
|  |     vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   Serial.print("Original Inhalt Seite 10: "); | ||||||
|  |   for (int i = 0; i < 4; i++) { | ||||||
|  |     if (originalPage[i] < 0x10) Serial.print("0"); | ||||||
|  |     Serial.print(originalPage[i], HEX); | ||||||
|  |     Serial.print(" "); | ||||||
|  |   } | ||||||
|  |   Serial.println(); | ||||||
|  |    | ||||||
|  |   // Perform write test | ||||||
|  |   if (!nfc.ntag2xx_WritePage(10, testPage)) { | ||||||
|  |     Serial.println("FEHLER: Schreibtest fehlgeschlagen!"); | ||||||
|     Serial.println("Tag ist möglicherweise schreibgeschützt oder defekt"); |     Serial.println("Tag ist möglicherweise schreibgeschützt oder defekt"); | ||||||
|     oledShowMessage("Tag write protected?"); |      | ||||||
|  |     // Additional diagnostics | ||||||
|  |     Serial.println("=== ERWEITERTE SCHREIBTEST-DIAGNOSE ==="); | ||||||
|  |      | ||||||
|  |     // Check if tag is still present | ||||||
|  |     uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; | ||||||
|  |     uint8_t uidLength; | ||||||
|  |     bool tagStillPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000); | ||||||
|  |     Serial.print("Tag noch erkannt: "); | ||||||
|  |     Serial.println(tagStillPresent ? "✓" : "❌"); | ||||||
|  |      | ||||||
|  |     if (!tagStillPresent) { | ||||||
|  |       Serial.println("URSACHE: Tag wurde während Schreibtest entfernt!"); | ||||||
|  |       oledShowMessage("Tag removed"); | ||||||
|  |     } else { | ||||||
|  |       Serial.println("URSACHE: Tag ist vorhanden aber nicht beschreibbar"); | ||||||
|  |       Serial.println("Möglicherweise: Schreibschutz, Defekt, oder Interface-Problem"); | ||||||
|  |       oledShowMessage("Tag write protected?"); | ||||||
|  |     } | ||||||
|  |     Serial.println("=========================================="); | ||||||
|  |      | ||||||
|     vTaskDelay(3000 / portTICK_PERIOD_MS); |     vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   // Verify test write |   // Verify test write | ||||||
|   uint8_t readBack[4]; |   uint8_t readBack[4]; | ||||||
|  |   vTaskDelay(20 / portTICK_PERIOD_MS); // Wait for write to complete | ||||||
|  |    | ||||||
|   if (!nfc.ntag2xx_ReadPage(10, readBack)) { |   if (!nfc.ntag2xx_ReadPage(10, readBack)) { | ||||||
|     Serial.println("FEHLER: Kann Testdaten nicht zurücklesen!"); |     Serial.println("FEHLER: Kann Testdaten nicht zurücklesen!"); | ||||||
|  |     oledShowMessage("Test verify failed"); | ||||||
|  |     vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|    |    | ||||||
| @@ -477,12 +641,20 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   Serial.println("✓ Schreibtest erfolgreich - Tag ist beschreibbar"); |   // Restore original content | ||||||
|   Serial.println("================================"); |   Serial.println("Stelle ursprünglichen Inhalt wieder her..."); | ||||||
|  |   if (!nfc.ntag2xx_WritePage(10, originalPage)) { | ||||||
|  |     Serial.println("WARNUNG: Konnte ursprünglichen Inhalt nicht wiederherstellen!"); | ||||||
|  |   } else { | ||||||
|  |     Serial.println("✓ Ursprünglicher Inhalt wiederhergestellt"); | ||||||
|  |   } | ||||||
|    |    | ||||||
|   // STEP 3: NDEF initialization with verification |   Serial.println("✓ Schreibtest erfolgreich - Tag ist voll funktionsfähig"); | ||||||
|  |   Serial.println("======================================================"); | ||||||
|  |  | ||||||
|  |   // STEP 4: NDEF initialization with verification | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|   Serial.println("=== SCHRITT 3: NDEF-INITIALISIERUNG ==="); |   Serial.println("=== SCHRITT 4: NDEF-INITIALISIERUNG ==="); | ||||||
|   if (!initializeNdefStructure()) { |   if (!initializeNdefStructure()) { | ||||||
|     Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); |     Serial.println("FEHLER: Konnte NDEF-Struktur nicht initialisieren!"); | ||||||
|     oledShowMessage("NDEF init failed"); |     oledShowMessage("NDEF init failed"); | ||||||
| @@ -513,6 +685,42 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|   Serial.println("✓ NDEF-Struktur initialisiert und verifiziert"); |   Serial.println("✓ NDEF-Struktur initialisiert und verifiziert"); | ||||||
|   Serial.println("=========================================="); |   Serial.println("=========================================="); | ||||||
|  |  | ||||||
|  |   // STEP 5: Allow interface to stabilize before major write operation | ||||||
|  |   Serial.println(); | ||||||
|  |   Serial.println("=== SCHRITT 5: NFC-INTERFACE STABILISIERUNG ==="); | ||||||
|  |   Serial.println("Stabilisiere NFC-Interface vor Hauptschreibvorgang..."); | ||||||
|  |    | ||||||
|  |   // Give the interface time to fully settle after NDEF initialization | ||||||
|  |   vTaskDelay(200 / portTICK_PERIOD_MS); | ||||||
|  |    | ||||||
|  |   // Test interface stability with a simple read | ||||||
|  |   uint8_t stabilityTest[4]; | ||||||
|  |   bool interfaceStable = false; | ||||||
|  |   for (int attempts = 0; attempts < 3; attempts++) { | ||||||
|  |     if (nfc.ntag2xx_ReadPage(4, stabilityTest)) { | ||||||
|  |       Serial.print("Interface stability test "); | ||||||
|  |       Serial.print(attempts + 1); | ||||||
|  |       Serial.println("/3: ✓"); | ||||||
|  |       interfaceStable = true; | ||||||
|  |       break; | ||||||
|  |     } else { | ||||||
|  |       Serial.print("Interface stability test "); | ||||||
|  |       Serial.print(attempts + 1); | ||||||
|  |       Serial.println("/3: ❌"); | ||||||
|  |       vTaskDelay(100 / portTICK_PERIOD_MS); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   if (!interfaceStable) { | ||||||
|  |     Serial.println("FEHLER: NFC-Interface ist nicht stabil genug für Schreibvorgang"); | ||||||
|  |     oledShowMessage("NFC Interface unstable"); | ||||||
|  |     vTaskDelay(3000 / portTICK_PERIOD_MS); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   Serial.println("✓ NFC-Interface ist stabil - Schreibvorgang kann beginnen"); | ||||||
|  |   Serial.println("========================================================="); | ||||||
|  |  | ||||||
|   // Allocate memory for the complete TLV structure |   // Allocate memory for the complete TLV structure | ||||||
|   uint8_t* tlvData = (uint8_t*) malloc(totalTlvSize); |   uint8_t* tlvData = (uint8_t*) malloc(totalTlvSize); | ||||||
|   if (tlvData == NULL) { |   if (tlvData == NULL) { | ||||||
| @@ -573,7 +781,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|   uint16_t totalBytes = offset + 1; |   uint16_t totalBytes = offset + 1; | ||||||
|  |  | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|   Serial.println("=== SCHRITT 4: SCHREIBE NEUE NDEF-DATEN ==="); |   Serial.println("=== SCHRITT 6: SCHREIBE NEUE NDEF-DATEN ==="); | ||||||
|   Serial.print("Schreibe "); |   Serial.print("Schreibe "); | ||||||
|   Serial.print(totalBytes); |   Serial.print(totalBytes); | ||||||
|   Serial.print(" Bytes in "); |   Serial.print(" Bytes in "); | ||||||
| @@ -597,8 +805,26 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|     // Copy data to page buffer |     // Copy data to page buffer | ||||||
|     memcpy(pageBuffer, &tlvData[bytesWritten], bytesToWrite); |     memcpy(pageBuffer, &tlvData[bytesWritten], bytesToWrite); | ||||||
|  |  | ||||||
|     // Write page to tag |     // Write page to tag with retry mechanism | ||||||
|     if (!nfc.ntag2xx_WritePage(pageNumber, pageBuffer)) { |     bool writeSuccess = false; | ||||||
|  |     for (int writeAttempt = 0; writeAttempt < 3; writeAttempt++) { | ||||||
|  |       if (nfc.ntag2xx_WritePage(pageNumber, pageBuffer)) { | ||||||
|  |         writeSuccess = true; | ||||||
|  |         break; | ||||||
|  |       } else { | ||||||
|  |         Serial.print("Schreibversuch "); | ||||||
|  |         Serial.print(writeAttempt + 1); | ||||||
|  |         Serial.print("/3 für Seite "); | ||||||
|  |         Serial.print(pageNumber); | ||||||
|  |         Serial.println(" fehlgeschlagen"); | ||||||
|  |          | ||||||
|  |         if (writeAttempt < 2) { | ||||||
|  |           vTaskDelay(50 / portTICK_PERIOD_MS); // Wait before retry | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!writeSuccess) { | ||||||
|       Serial.print("FEHLER beim Schreiben der Seite "); |       Serial.print("FEHLER beim Schreiben der Seite "); | ||||||
|       Serial.println(pageNumber); |       Serial.println(pageNumber); | ||||||
|       Serial.print("Möglicherweise Page-Limit erreicht für "); |       Serial.print("Möglicherweise Page-Limit erreicht für "); | ||||||
| @@ -623,35 +849,52 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|     Serial.print("... "); |     Serial.print("... "); | ||||||
|      |      | ||||||
|     uint8_t verifyBuffer[4]; |     uint8_t verifyBuffer[4]; | ||||||
|     vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay before verification |     vTaskDelay(20 / portTICK_PERIOD_MS); // Increased delay before verification | ||||||
|      |      | ||||||
|     if (nfc.ntag2xx_ReadPage(pageNumber, verifyBuffer)) { |     // Verification with retry mechanism | ||||||
|       bool writeSuccess = true; |     bool verifySuccess = false; | ||||||
|       for (int i = 0; i < bytesToWrite; i++) { |     for (int verifyAttempt = 0; verifyAttempt < 3; verifyAttempt++) { | ||||||
|         if (verifyBuffer[i] != pageBuffer[i]) { |       if (nfc.ntag2xx_ReadPage(pageNumber, verifyBuffer)) { | ||||||
|           writeSuccess = false; |         bool writeMatches = true; | ||||||
|           Serial.println(); |         for (int i = 0; i < bytesToWrite; i++) { | ||||||
|           Serial.print("VERIFIKATIONSFEHLER bei Byte "); |           if (verifyBuffer[i] != pageBuffer[i]) { | ||||||
|           Serial.print(i); |             writeMatches = false; | ||||||
|           Serial.print(" - Erwartet: 0x"); |             Serial.println(); | ||||||
|           Serial.print(pageBuffer[i], HEX); |             Serial.print("VERIFIKATIONSFEHLER bei Byte "); | ||||||
|           Serial.print(", Gelesen: 0x"); |             Serial.print(i); | ||||||
|           Serial.println(verifyBuffer[i], HEX); |             Serial.print(" - Erwartet: 0x"); | ||||||
|  |             Serial.print(pageBuffer[i], HEX); | ||||||
|  |             Serial.print(", Gelesen: 0x"); | ||||||
|  |             Serial.println(verifyBuffer[i], HEX); | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         if (writeMatches) { | ||||||
|  |           verifySuccess = true; | ||||||
|           break; |           break; | ||||||
|  |         } else if (verifyAttempt < 2) { | ||||||
|  |           Serial.print("Verifikationsversuch "); | ||||||
|  |           Serial.print(verifyAttempt + 1); | ||||||
|  |           Serial.println("/3 fehlgeschlagen, wiederhole..."); | ||||||
|  |           vTaskDelay(30 / portTICK_PERIOD_MS); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         Serial.print("Verifikations-Read-Versuch "); | ||||||
|  |         Serial.print(verifyAttempt + 1); | ||||||
|  |         Serial.println("/3 fehlgeschlagen"); | ||||||
|  |         if (verifyAttempt < 2) { | ||||||
|  |           vTaskDelay(30 / portTICK_PERIOD_MS); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|      |      | ||||||
|       if (!writeSuccess) { |     if (!verifySuccess) { | ||||||
|         Serial.println("❌ SCHREIBVORGANG FEHLGESCHLAGEN!"); |       Serial.println("❌ SCHREIBVORGANG/VERIFIKATION FEHLGESCHLAGEN!"); | ||||||
|         free(tlvData); |  | ||||||
|         return 0; |  | ||||||
|       } else { |  | ||||||
|         Serial.println("✓"); |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       Serial.println("❌ Kann Seite nicht zur Verifikation lesen!"); |  | ||||||
|       free(tlvData); |       free(tlvData); | ||||||
|       return 0; |       return 0; | ||||||
|  |     } else { | ||||||
|  |       Serial.println("✓"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Serial.print("Seite "); |     Serial.print("Seite "); | ||||||
| @@ -668,7 +911,7 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|     pageNumber++; |     pageNumber++; | ||||||
|      |      | ||||||
|     yield(); |     yield(); | ||||||
|     vTaskDelay(5 / portTICK_PERIOD_MS); // Small delay between page writes |     vTaskDelay(10 / portTICK_PERIOD_MS); // Slightly increased delay between page writes | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   free(tlvData); |   free(tlvData); | ||||||
| @@ -695,12 +938,72 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|   Serial.println("%"); |   Serial.println("%"); | ||||||
|   Serial.println("✓ Bestehende Daten wurden überschrieben"); |   Serial.println("✓ Bestehende Daten wurden überschrieben"); | ||||||
|    |    | ||||||
|  |   // CRITICAL: Allow NFC interface to stabilize after write operation | ||||||
|  |   Serial.println(); | ||||||
|  |   Serial.println("=== SCHRITT 7: NFC-INTERFACE STABILISIERUNG NACH SCHREIBVORGANG ==="); | ||||||
|  |   Serial.println("Stabilisiere NFC-Interface nach Schreibvorgang..."); | ||||||
|  |    | ||||||
|  |   // Give the tag and interface time to settle after write operation | ||||||
|  |   vTaskDelay(300 / portTICK_PERIOD_MS); // Increased stabilization time | ||||||
|  |    | ||||||
|  |   // Test if the interface is still responsive | ||||||
|  |   uint8_t postWriteTest[4]; | ||||||
|  |   bool interfaceResponsive = false; | ||||||
|  |    | ||||||
|  |   for (int stabilityAttempt = 0; stabilityAttempt < 5; stabilityAttempt++) { | ||||||
|  |     Serial.print("Post-write interface test "); | ||||||
|  |     Serial.print(stabilityAttempt + 1); | ||||||
|  |     Serial.print("/5... "); | ||||||
|  |      | ||||||
|  |     if (nfc.ntag2xx_ReadPage(3, postWriteTest)) { // Read capability container | ||||||
|  |       Serial.println("✓"); | ||||||
|  |       interfaceResponsive = true; | ||||||
|  |       break; | ||||||
|  |     } else { | ||||||
|  |       Serial.println("❌"); | ||||||
|  |        | ||||||
|  |       if (stabilityAttempt < 4) { | ||||||
|  |         Serial.println("Warte und versuche Interface zu stabilisieren..."); | ||||||
|  |         vTaskDelay(200 / portTICK_PERIOD_MS); | ||||||
|  |          | ||||||
|  |         // Try to re-establish communication with a simple tag presence check | ||||||
|  |         uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; | ||||||
|  |         uint8_t uidLength; | ||||||
|  |         bool tagStillPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000); | ||||||
|  |         Serial.print("Tag presence check: "); | ||||||
|  |         Serial.println(tagStillPresent ? "✓" : "❌"); | ||||||
|  |          | ||||||
|  |         if (!tagStillPresent) { | ||||||
|  |           Serial.println("Tag wurde während/nach Schreibvorgang entfernt!"); | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   if (!interfaceResponsive) { | ||||||
|  |     Serial.println("WARNUNG: NFC-Interface reagiert nach Schreibvorgang nicht mehr stabil"); | ||||||
|  |     Serial.println("Schreibvorgang war erfolgreich, aber Interface benötigt möglicherweise Reset"); | ||||||
|  |   } else { | ||||||
|  |     Serial.println("✓ NFC-Interface ist nach Schreibvorgang stabil"); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   Serial.println("=================================================================="); | ||||||
|  |    | ||||||
|   // CRITICAL: Verify the write by reading back the data |   // CRITICAL: Verify the write by reading back the data | ||||||
|   Serial.println(); |   Serial.println(); | ||||||
|   Serial.println("=== WRITE VERIFICATION ==="); |   Serial.println("=== WRITE VERIFICATION ==="); | ||||||
|    |    | ||||||
|   // Wait a moment for tag to stabilize |   // Wait a moment for tag to stabilize | ||||||
|   vTaskDelay(100 / portTICK_PERIOD_MS); |   vTaskDelay(200 / portTICK_PERIOD_MS); // Increased stabilization time | ||||||
|  |    | ||||||
|  |   // Only proceed with verification if interface is responsive | ||||||
|  |   if (!interfaceResponsive) { | ||||||
|  |     Serial.println("SKIPPING VERIFICATION: Interface not responsive"); | ||||||
|  |     Serial.println("❌ WRITE COMPLETED but VERIFICATION SKIPPED"); | ||||||
|  |     Serial.println("❌ Cannot guarantee data integrity"); | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|    |    | ||||||
|   // Read back the written data to verify |   // Read back the written data to verify | ||||||
|   uint8_t verifyBuffer[totalBytes]; |   uint8_t verifyBuffer[totalBytes]; | ||||||
| @@ -712,7 +1015,27 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|    |    | ||||||
|   while (verifyBytesRead < totalBytes && verifyPage <= maxWritablePage) { |   while (verifyBytesRead < totalBytes && verifyPage <= maxWritablePage) { | ||||||
|     uint8_t pageData[4]; |     uint8_t pageData[4]; | ||||||
|     if (!nfc.ntag2xx_ReadPage(verifyPage, pageData)) { |      | ||||||
|  |     // Verification read with retry mechanism | ||||||
|  |     bool pageReadSuccess = false; | ||||||
|  |     for (int readAttempt = 0; readAttempt < 3; readAttempt++) { | ||||||
|  |       if (nfc.ntag2xx_ReadPage(verifyPage, pageData)) { | ||||||
|  |         pageReadSuccess = true; | ||||||
|  |         break; | ||||||
|  |       } else { | ||||||
|  |         Serial.print("Verification read attempt "); | ||||||
|  |         Serial.print(readAttempt + 1); | ||||||
|  |         Serial.print("/3 for page "); | ||||||
|  |         Serial.print(verifyPage); | ||||||
|  |         Serial.println(" failed"); | ||||||
|  |          | ||||||
|  |         if (readAttempt < 2) { | ||||||
|  |           vTaskDelay(50 / portTICK_PERIOD_MS); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (!pageReadSuccess) { | ||||||
|       Serial.print("VERIFICATION FAILED: Cannot read page "); |       Serial.print("VERIFICATION FAILED: Cannot read page "); | ||||||
|       Serial.println(verifyPage); |       Serial.println(verifyPage); | ||||||
|       verificationSuccess = false; |       verificationSuccess = false; | ||||||
| @@ -725,6 +1048,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|      |      | ||||||
|     verifyBytesRead += bytesToCopy; |     verifyBytesRead += bytesToCopy; | ||||||
|     verifyPage++; |     verifyPage++; | ||||||
|  |      | ||||||
|  |     vTaskDelay(10 / portTICK_PERIOD_MS); // Small delay between verification reads | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   if (verificationSuccess && verifyBytesRead >= totalBytes) { |   if (verificationSuccess && verifyBytesRead >= totalBytes) { | ||||||
| @@ -799,6 +1124,8 @@ uint8_t ntag2xx_WriteNDEF(const char *payload) { | |||||||
|       if (!jsonFound) { |       if (!jsonFound) { | ||||||
|         Serial.println("WARNING: No valid JSON found in verified data!"); |         Serial.println("WARNING: No valid JSON found in verified data!"); | ||||||
|         verificationSuccess = false; |         verificationSuccess = false; | ||||||
|  |       } else { | ||||||
|  |         Serial.println("✓ JSON extracted and validated successfully"); | ||||||
|       } |       } | ||||||
|        |        | ||||||
|     } else { |     } else { | ||||||
| @@ -1040,7 +1367,7 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { | |||||||
|       } |       } | ||||||
|       // Brand Filament not registered to Spoolman |       // Brand Filament not registered to Spoolman | ||||||
|       else if ((!doc["sm_id"].is<String>() || (doc["sm_id"].is<String>() && (doc["sm_id"] == "0" || doc["sm_id"] == ""))) |       else if ((!doc["sm_id"].is<String>() || (doc["sm_id"].is<String>() && (doc["sm_id"] == "0" || doc["sm_id"] == ""))) | ||||||
|               && doc["brand"].is<String>() && doc["artnr"].is<String>()) |               && doc["b"].is<String>() && doc["an"].is<String>()) | ||||||
|       { |       { | ||||||
|         doc["sm_id"] = "0"; // Ensure sm_id is set to 0 |         doc["sm_id"] = "0"; // Ensure sm_id is set to 0 | ||||||
|         // If no sm_id is present but the brand is Brand Filament then |         // If no sm_id is present but the brand is Brand Filament then | ||||||
| @@ -1065,65 +1392,208 @@ bool decodeNdefAndReturnJson(const byte* encodedMessage, String uidString) { | |||||||
| } | } | ||||||
|  |  | ||||||
| bool quickSpoolIdCheck(String uidString) { | bool quickSpoolIdCheck(String uidString) { | ||||||
|     // Fast-path: Read only first 2-3 pages to check for sm_id pattern |     // Fast-path: Read NDEF structure to quickly locate and check JSON payload | ||||||
|     // This dramatically speeds up known spool recognition |     // This dramatically speeds up known spool recognition | ||||||
|      |      | ||||||
|  |     // CRITICAL: Do not execute during write operations! | ||||||
|  |     if (nfcWriteInProgress) { | ||||||
|  |         Serial.println("FAST-PATH: Skipped during write operation"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |      | ||||||
|     Serial.println("=== FAST-PATH: Quick sm_id Check ==="); |     Serial.println("=== FAST-PATH: Quick sm_id Check ==="); | ||||||
|      |      | ||||||
|     // Read first 3 pages (12 bytes) after NDEF header (pages 4-6) |     // Read enough pages to cover NDEF header + beginning of payload (pages 4-8 = 20 bytes) | ||||||
|     uint8_t quickData[12]; |     uint8_t ndefData[20]; | ||||||
|     memset(quickData, 0, 12); |     memset(ndefData, 0, 20); | ||||||
|      |      | ||||||
|     for (uint8_t page = 4; page < 7; page++) { |     for (uint8_t page = 4; page < 9; page++) { | ||||||
|         if (!nfc.ntag2xx_ReadPage(page, quickData + (page - 4) * 4)) { |         if (!nfc.ntag2xx_ReadPage(page, ndefData + (page - 4) * 4)) { | ||||||
|             Serial.print("Failed to read page "); |             Serial.print("Failed to read page "); | ||||||
|             Serial.println(page); |             Serial.println(page); | ||||||
|             return false; // Fall back to full read |             return false; // Fall back to full read | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // Convert to string for pattern matching |     // Parse NDEF structure to find JSON payload start | ||||||
|     String quickCheck = ""; |     Serial.print("Raw NDEF data (first 20 bytes): "); | ||||||
|     for (int i = 0; i < 12; i++) { |     for (int i = 0; i < 20; i++) { | ||||||
|         if (quickData[i] >= 32 && quickData[i] <= 126) { |         if (ndefData[i] < 0x10) Serial.print("0"); | ||||||
|             quickCheck += (char)quickData[i]; |         Serial.print(ndefData[i], HEX); | ||||||
|  |         Serial.print(" "); | ||||||
|  |     } | ||||||
|  |     Serial.println(); | ||||||
|  |      | ||||||
|  |     // Look for NDEF TLV (0x03) at the beginning | ||||||
|  |     int tlvOffset = -1; | ||||||
|  |     for (int i = 0; i < 8; i++) { | ||||||
|  |         if (ndefData[i] == 0x03) { | ||||||
|  |             tlvOffset = i; | ||||||
|  |             Serial.print("Found NDEF TLV at offset: "); | ||||||
|  |             Serial.println(tlvOffset); | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     Serial.print("Quick data (first 12 bytes): "); |     if (tlvOffset == -1) { | ||||||
|     Serial.println(quickCheck); |         Serial.println("✗ FAST-PATH: No NDEF TLV found"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|      |      | ||||||
|     // Look for sm_id pattern at the beginning |     // Parse NDEF record to find JSON payload | ||||||
|     if (quickCheck.indexOf("\"sm_id\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") < 0) { |     int ndefRecordStart; | ||||||
|         Serial.println("✓ FAST-PATH: sm_id found in first bytes - known spool detected!"); |     if (ndefData[tlvOffset + 1] == 0xFF) { | ||||||
|  |         // Extended length format | ||||||
|  |         ndefRecordStart = tlvOffset + 4; | ||||||
|  |     } else { | ||||||
|  |         // Standard length format | ||||||
|  |         ndefRecordStart = tlvOffset + 2; | ||||||
|  |     } | ||||||
|      |      | ||||||
|         // Extract sm_id from quick data if possible |     if (ndefRecordStart >= 20) { | ||||||
|         int smIdStart = quickCheck.indexOf("\"sm_id\":\"") + 9; |         Serial.println("✗ FAST-PATH: NDEF record starts beyond read data"); | ||||||
|         int smIdEnd = quickCheck.indexOf("\"", smIdStart); |         return false; | ||||||
|  |     } | ||||||
|      |      | ||||||
|         if (smIdEnd > smIdStart) { |     // Parse NDEF record header | ||||||
|             String quickSpoolId = quickCheck.substring(smIdStart, smIdEnd); |     uint8_t recordHeader = ndefData[ndefRecordStart]; | ||||||
|  |     uint8_t typeLength = ndefData[ndefRecordStart + 1]; | ||||||
|  |      | ||||||
|  |     // Calculate payload offset | ||||||
|  |     uint8_t payloadLengthBytes = (recordHeader & 0x10) ? 1 : 4; // SR flag check | ||||||
|  |     uint8_t idLength = (recordHeader & 0x08) ? ndefData[ndefRecordStart + 2 + payloadLengthBytes + typeLength] : 0; // IL flag check | ||||||
|  |      | ||||||
|  |     int payloadOffset = ndefRecordStart + 1 + 1 + payloadLengthBytes + typeLength + idLength; | ||||||
|  |      | ||||||
|  |     Serial.print("NDEF Record Header: 0x"); | ||||||
|  |     Serial.print(recordHeader, HEX); | ||||||
|  |     Serial.print(", Type Length: "); | ||||||
|  |     Serial.print(typeLength); | ||||||
|  |     Serial.print(", Payload offset: "); | ||||||
|  |     Serial.println(payloadOffset); | ||||||
|  |      | ||||||
|  |     // Check if payload starts within our read data | ||||||
|  |     if (payloadOffset >= 20) { | ||||||
|  |         Serial.println("✗ FAST-PATH: JSON payload starts beyond quick read data - need more pages"); | ||||||
|  |          | ||||||
|  |         // Read additional pages to get to JSON payload | ||||||
|  |         uint8_t extraData[16]; // Read 4 more pages | ||||||
|  |         memset(extraData, 0, 16); | ||||||
|  |          | ||||||
|  |         for (uint8_t page = 9; page < 13; page++) { | ||||||
|  |             if (!nfc.ntag2xx_ReadPage(page, extraData + (page - 9) * 4)) { | ||||||
|  |                 Serial.print("Failed to read additional page "); | ||||||
|  |                 Serial.println(page); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // Combine data | ||||||
|  |         uint8_t combinedData[36]; | ||||||
|  |         memcpy(combinedData, ndefData, 20); | ||||||
|  |         memcpy(combinedData + 20, extraData, 16); | ||||||
|  |          | ||||||
|  |         // Extract JSON from combined data | ||||||
|  |         String jsonStart = ""; | ||||||
|  |         int jsonStartPos = payloadOffset; | ||||||
|  |         for (int i = 0; i < 36 - payloadOffset && i < 30; i++) { | ||||||
|  |             uint8_t currentByte = combinedData[payloadOffset + i]; | ||||||
|  |             if (currentByte >= 32 && currentByte <= 126) { | ||||||
|  |                 jsonStart += (char)currentByte; | ||||||
|  |             } | ||||||
|  |             // Stop at first brace to get just the beginning | ||||||
|  |             if (currentByte == '{' && i > 0) break; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         Serial.print("JSON start from extended read: "); | ||||||
|  |         Serial.println(jsonStart); | ||||||
|  |          | ||||||
|  |         // Check for sm_id pattern - look for non-zero sm_id values | ||||||
|  |         if (jsonStart.indexOf("\"sm_id\":\"") >= 0) { | ||||||
|  |             int smIdStart = jsonStart.indexOf("\"sm_id\":\"") + 9; | ||||||
|  |             int smIdEnd = jsonStart.indexOf("\"", smIdStart); | ||||||
|  |              | ||||||
|  |             if (smIdEnd > smIdStart && smIdEnd < jsonStart.length()) { | ||||||
|  |                 String quickSpoolId = jsonStart.substring(smIdStart, smIdEnd); | ||||||
|  |                 Serial.print("Found sm_id in extended read: "); | ||||||
|  |                 Serial.println(quickSpoolId); | ||||||
|  |                  | ||||||
|  |                 // Only process if sm_id is not "0" (known spool) | ||||||
|  |                 if (quickSpoolId != "0" && quickSpoolId.length() > 0) { | ||||||
|  |                     Serial.println("✓ FAST-PATH: Known spool detected!"); | ||||||
|  |                      | ||||||
|  |                     // Set as active spool immediately | ||||||
|  |                     activeSpoolId = quickSpoolId; | ||||||
|  |                     lastSpoolId = activeSpoolId; | ||||||
|  |                      | ||||||
|  |                     oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); | ||||||
|  |                     Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); | ||||||
|  |                     return true; | ||||||
|  |                 } else { | ||||||
|  |                     Serial.println("✗ FAST-PATH: sm_id is 0 - new brand filament, need full read"); | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         Serial.println("✗ FAST-PATH: No sm_id pattern in extended read"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // Extract JSON payload from the available data | ||||||
|  |     String quickJson = ""; | ||||||
|  |     for (int i = payloadOffset; i < 20 && i < payloadOffset + 15; i++) { | ||||||
|  |         uint8_t currentByte = ndefData[i]; | ||||||
|  |         if (currentByte >= 32 && currentByte <= 126) { | ||||||
|  |             quickJson += (char)currentByte; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     Serial.print("Quick JSON data: "); | ||||||
|  |     Serial.println(quickJson); | ||||||
|  |      | ||||||
|  |     // Look for sm_id pattern in the beginning of JSON - check for known vs new spools | ||||||
|  |     if (quickJson.indexOf("\"sm_id\":\"") >= 0) { | ||||||
|  |         Serial.println("✓ FAST-PATH: sm_id field found"); | ||||||
|  |          | ||||||
|  |         // Extract sm_id from quick data | ||||||
|  |         int smIdStart = quickJson.indexOf("\"sm_id\":\"") + 9; | ||||||
|  |         int smIdEnd = quickJson.indexOf("\"", smIdStart); | ||||||
|  |          | ||||||
|  |         if (smIdEnd > smIdStart && smIdEnd < quickJson.length()) { | ||||||
|  |             String quickSpoolId = quickJson.substring(smIdStart, smIdEnd); | ||||||
|             Serial.print("✓ Quick extracted sm_id: "); |             Serial.print("✓ Quick extracted sm_id: "); | ||||||
|             Serial.println(quickSpoolId); |             Serial.println(quickSpoolId); | ||||||
|              |              | ||||||
|             // Set as active spool immediately |             // Only process known spools (sm_id != "0") via fast path | ||||||
|             activeSpoolId = quickSpoolId; |             if (quickSpoolId != "0" && quickSpoolId.length() > 0) { | ||||||
|             lastSpoolId = activeSpoolId; |                 Serial.println("✓ FAST-PATH: Known spool detected!"); | ||||||
|                  |                  | ||||||
|             oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); |                 // Set as active spool immediately | ||||||
|             Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); |                 activeSpoolId = quickSpoolId; | ||||||
|             return true; // Skip full tag reading! |                 lastSpoolId = activeSpoolId; | ||||||
|  |                  | ||||||
|  |                 oledShowProgressBar(2, octoEnabled?5:4, "Known Spool", "Quick mode"); | ||||||
|  |                 Serial.println("✓ FAST-PATH SUCCESS: Known spool processed quickly"); | ||||||
|  |                 return true; | ||||||
|  |             } else { | ||||||
|  |                 Serial.println("✗ FAST-PATH: sm_id is 0 - new brand filament, need full read"); | ||||||
|  |                 return false; // sm_id="0" means new brand filament, needs full processing | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             Serial.println("✗ FAST-PATH: Could not extract complete sm_id value"); | ||||||
|  |             return false; // Need full read to get complete sm_id | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // Check for other quick patterns |     // Check for other patterns that require full read | ||||||
|     if (quickCheck.indexOf("\"location\":\"") >= 0) { |     if (quickJson.indexOf("\"location\":\"") >= 0) { | ||||||
|         Serial.println("✓ FAST-PATH: Location tag detected"); |         Serial.println("✓ FAST-PATH: Location tag detected"); | ||||||
|         return false; // Need full read for location processing |         return false; // Need full read for location processing | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     if (quickCheck.indexOf("\"brand\":\"") >= 0 && quickCheck.indexOf("\"sm_id\":\"0\"") >= 0) { |     if (quickJson.indexOf("\"brand\":\"") >= 0) { | ||||||
|         Serial.println("✓ FAST-PATH: New brand filament detected (sm_id:0)"); |         Serial.println("✓ FAST-PATH: Brand filament detected - may need full processing"); | ||||||
|         return false; // Need full read for brand filament creation |         return false; // Need full read for brand filament creation | ||||||
|     } |     } | ||||||
|      |      | ||||||
| @@ -1139,14 +1609,11 @@ void writeJsonToTag(void *parameter) { | |||||||
|   Serial.println(params->payload); |   Serial.println(params->payload); | ||||||
|  |  | ||||||
|   nfcReaderState = NFC_WRITING; |   nfcReaderState = NFC_WRITING; | ||||||
|  |   nfcWriteInProgress = true; // Block high-level tag operations during write | ||||||
|  |  | ||||||
|   // IMPORTANT: Do NOT suspend reading task during writing! |   // Do NOT suspend the reading task - we need NFC interface for verification | ||||||
|   // We need to be able to read during write verification |   // Just use nfcWriteInProgress to prevent scanning and fast-path operations | ||||||
|   // Just set the state to WRITING to prevent scan conflicts |   Serial.println("NFC Write Task starting - High-level operations blocked, low-level NFC available"); | ||||||
|   Serial.println("NFC Write Task starting - Reader remains active for verification"); |  | ||||||
|    |  | ||||||
|   // Small delay to ensure any ongoing operations complete |  | ||||||
|   vTaskDelay(100 / portTICK_PERIOD_MS); |  | ||||||
|  |  | ||||||
|   //pauseBambuMqttTask = true; |   //pauseBambuMqttTask = true; | ||||||
|   // aktualisieren der Website wenn sich der Status ändert |   // aktualisieren der Website wenn sich der Status ändert | ||||||
| @@ -1205,13 +1672,80 @@ void writeJsonToTag(void *parameter) { | |||||||
|         }else{ |         }else{ | ||||||
|           oledShowProgressBar(1, 1, "Write Tag", "Done!"); |           oledShowProgressBar(1, 1, "Write Tag", "Done!"); | ||||||
|         } |         } | ||||||
|         uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID |          | ||||||
|  |         // CRITICAL: Properly stabilize NFC interface after write operation | ||||||
|  |         Serial.println(); | ||||||
|  |         Serial.println("=== POST-WRITE NFC STABILIZATION ==="); | ||||||
|  |          | ||||||
|  |         // Wait for tag operations to complete | ||||||
|  |         vTaskDelay(500 / portTICK_PERIOD_MS); | ||||||
|  |          | ||||||
|  |         // Test tag presence and remove detection | ||||||
|  |         uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; | ||||||
|         uint8_t uidLength; |         uint8_t uidLength; | ||||||
|         yield(); |         int tagRemovalChecks = 0; | ||||||
|         esp_task_wdt_reset(); |          | ||||||
|         while (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 400)) { |         Serial.println("Warte bis Tag entfernt wird..."); | ||||||
|  |          | ||||||
|  |         // Monitor tag presence | ||||||
|  |         while (tagRemovalChecks < 10) { | ||||||
|           yield(); |           yield(); | ||||||
|  |           esp_task_wdt_reset(); | ||||||
|  |            | ||||||
|  |           bool tagPresent = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500); | ||||||
|  |            | ||||||
|  |           if (!tagPresent) { | ||||||
|  |             Serial.println("✓ Tag wurde entfernt - NFC bereit für nächsten Scan"); | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |            | ||||||
|  |           tagRemovalChecks++; | ||||||
|  |           Serial.print("Tag noch vorhanden ("); | ||||||
|  |           Serial.print(tagRemovalChecks); | ||||||
|  |           Serial.println("/10)"); | ||||||
|  |            | ||||||
|  |           vTaskDelay(500 / portTICK_PERIOD_MS); | ||||||
|         } |         } | ||||||
|  |          | ||||||
|  |         if (tagRemovalChecks >= 10) { | ||||||
|  |           Serial.println("WARNUNG: Tag wurde nicht entfernt - fahre trotzdem fort"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // Additional interface stabilization before resuming normal operations | ||||||
|  |         Serial.println("Stabilisiere NFC-Interface für normale Operationen..."); | ||||||
|  |         vTaskDelay(200 / portTICK_PERIOD_MS); | ||||||
|  |          | ||||||
|  |         // Test if interface is ready for normal scanning | ||||||
|  |         uint8_t interfaceTestBuffer[4]; | ||||||
|  |         bool interfaceReady = false; | ||||||
|  |          | ||||||
|  |         for (int testAttempt = 0; testAttempt < 3; testAttempt++) { | ||||||
|  |           // Try a simple interface operation (without requiring tag presence) | ||||||
|  |           Serial.print("Interface readiness test "); | ||||||
|  |           Serial.print(testAttempt + 1); | ||||||
|  |           Serial.print("/3... "); | ||||||
|  |            | ||||||
|  |           // Use a safe read operation that doesn't depend on tag presence | ||||||
|  |           // This tests if the PN532 chip itself is responsive | ||||||
|  |           uint32_t versiondata = nfc.getFirmwareVersion(); | ||||||
|  |           if (versiondata != 0) { | ||||||
|  |             Serial.println("✓"); | ||||||
|  |             interfaceReady = true; | ||||||
|  |             break; | ||||||
|  |           } else { | ||||||
|  |             Serial.println("❌"); | ||||||
|  |             vTaskDelay(100 / portTICK_PERIOD_MS); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         if (!interfaceReady) { | ||||||
|  |           Serial.println("WARNUNG: NFC-Interface reagiert nicht - könnte normale Scans beeinträchtigen"); | ||||||
|  |         } else { | ||||||
|  |           Serial.println("✓ NFC-Interface ist bereit für normale Scans"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         Serial.println("========================================="); | ||||||
|  |          | ||||||
|         vTaskResume(RfidReaderTask); |         vTaskResume(RfidReaderTask); | ||||||
|         vTaskDelay(500 / portTICK_PERIOD_MS);         |         vTaskDelay(500 / portTICK_PERIOD_MS);         | ||||||
|     }  |     }  | ||||||
| @@ -1234,9 +1768,8 @@ void writeJsonToTag(void *parameter) { | |||||||
|   sendWriteResult(nullptr, success); |   sendWriteResult(nullptr, success); | ||||||
|   sendNfcData(); |   sendNfcData(); | ||||||
|  |  | ||||||
|   // Since we didn't suspend reading, we don't need to re-enable it |   // Only reset the write protection flag - reading task was never suspended | ||||||
|   // Just reset the state back to IDLE |   nfcWriteInProgress = false; // Re-enable high-level tag operations | ||||||
|   Serial.println("NFC Write Task completed - Reader was never suspended"); |  | ||||||
|   pauseBambuMqttTask = false; |   pauseBambuMqttTask = false; | ||||||
|  |  | ||||||
|   free(params->payload); |   free(params->payload); | ||||||
| @@ -1271,8 +1804,8 @@ void startWriteJsonToTag(const bool isSpoolTag, const char* payload) { | |||||||
| void scanRfidTask(void * parameter) { | void scanRfidTask(void * parameter) { | ||||||
|   Serial.println("RFID Task gestartet"); |   Serial.println("RFID Task gestartet"); | ||||||
|   for(;;) { |   for(;;) { | ||||||
|     // Wenn geschrieben wird Schleife aussetzen |     // Skip scanning during write operations, but keep NFC interface active | ||||||
|     if (nfcReaderState != NFC_WRITING && !nfcReadingTaskSuspendRequest && !booting) |     if (nfcReaderState != NFC_WRITING && !nfcWriteInProgress && !nfcReadingTaskSuspendRequest && !booting) | ||||||
|     { |     { | ||||||
|       nfcReadingTaskSuspendState = false; |       nfcReadingTaskSuspendState = false; | ||||||
|       yield(); |       yield(); | ||||||
| @@ -1417,8 +1950,17 @@ void scanRfidTask(void * parameter) { | |||||||
|     else |     else | ||||||
|     { |     { | ||||||
|       nfcReadingTaskSuspendState = true; |       nfcReadingTaskSuspendState = true; | ||||||
|       Serial.println("NFC Reading disabled"); |        | ||||||
|       vTaskDelay(1000 / portTICK_PERIOD_MS); |       // Different behavior for write protection vs. full suspension | ||||||
|  |       if (nfcWriteInProgress) { | ||||||
|  |         // During write: Just pause scanning, don't disable NFC interface | ||||||
|  |         // Serial.println("NFC Scanning paused during write operation"); | ||||||
|  |         vTaskDelay(100 / portTICK_PERIOD_MS); // Shorter delay during write | ||||||
|  |       } else { | ||||||
|  |         // Full suspension requested | ||||||
|  |         Serial.println("NFC Reading disabled"); | ||||||
|  |         vTaskDelay(1000 / portTICK_PERIOD_MS); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     yield(); |     yield(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ extern String activeSpoolId; | |||||||
| extern String lastSpoolId; | extern String lastSpoolId; | ||||||
| extern volatile nfcReaderStateType nfcReaderState; | extern volatile nfcReaderStateType nfcReaderState; | ||||||
| extern volatile bool pauseBambuMqttTask; | extern volatile bool pauseBambuMqttTask; | ||||||
|  | extern volatile bool nfcWriteInProgress; | ||||||
| extern bool tagProcessed; | extern bool tagProcessed; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user