diff --git a/data/rfid.html b/data/rfid.html index 9709e92..5721f70 100644 --- a/data/rfid.html +++ b/data/rfid.html @@ -88,7 +88,7 @@ try { // API Aufruf zum Erstellen des Benutzers - const response = await fetch(`/api/users`, { + const response = await fetch(`/api/users/insert`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -109,10 +109,7 @@ // Formular zurücksetzen clearForm(); - - // Daten neu laden - await loadUserData(); - + // UID Feld fokussieren für nächsten Eintrag setTimeout(() => { document.getElementById('uid').focus(); @@ -214,7 +211,7 @@ async function readRFIDUID() { const readBtn = document.getElementById('readUidBtn'); const uidInput = document.getElementById('uid'); - + // Button Status ändern readBtn.disabled = true; readBtn.className = 'read-uid-btn reading'; @@ -223,7 +220,7 @@ try { // API Aufruf zum RFID Reader const response = await fetch(`/api/rfid/read`, { - method: 'POST', + method: 'GET', headers: { 'Content-Type': 'application/json', } @@ -233,17 +230,17 @@ if (result.success && result.uid) { // UID in das Eingabefeld setzen - uidInput.value = result.uid.toUpperCase(); + uidInput.value = result.uid.match(/.{1,2}/g).join(':').toUpperCase(); uidInput.focus(); - + // Visuelles Feedback uidInput.style.borderColor = '#28a745'; setTimeout(() => { uidInput.style.borderColor = '#e1e5e9'; }, 2000); - + showSuccessMessage('UID erfolgreich gelesen!'); - + // Automatisch zum nächsten Feld springen setTimeout(() => { document.getElementById('vorname').focus(); @@ -253,7 +250,7 @@ // Fehler beim Lesen const errorMsg = result.error || 'Keine UID gefunden'; showErrorMessage(`RFID Fehler: ${errorMsg}`); - + // UID Feld rot markieren uidInput.style.borderColor = '#dc3545'; setTimeout(() => { @@ -264,13 +261,13 @@ } catch (error) { console.error('Fehler beim Lesen der UID:', error); showErrorMessage('Verbindungsfehler zum RFID Reader. Bitte prüfen Sie die Verbindung.'); - + // UID Feld rot markieren uidInput.style.borderColor = '#dc3545'; setTimeout(() => { uidInput.style.borderColor = '#e1e5e9'; }, 3000); - + } finally { // Button Status zurücksetzen readBtn.disabled = false; diff --git a/platformio.ini b/platformio.ini index 8b70908..5262536 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,7 +14,6 @@ default_envs = esp32dev [env] platform = https://github.com/platformio/platform-espressif32.git framework = arduino -lib_deps = esp32async/ESPAsyncWebServer@^3.7.7 lib_compat_mode = strict [env:wemos_d1_mini32] diff --git a/src/databasebackend.h b/src/databasebackend.h index 22f1b87..704ab08 100644 --- a/src/databasebackend.h +++ b/src/databasebackend.h @@ -81,6 +81,43 @@ UserData checkUser(const String& uid) { return userData; } +//Function to enter user data into the database +bool enterUserData(const String& uid, const String& firstname, const String& lastname, int alter) { + if (!backendOnline()) { + Serial.println("No internet connection, cannot enter user data."); + return false; + } + + HTTPClient http; + http.begin(String(BACKEND_SERVER) + "/api/users/insert"); + http.addHeader("Content-Type", "application/json"); + http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN); + + // Create JSON payload + StaticJsonDocument<256> requestDoc; + requestDoc["uid"] = uid; + requestDoc["vorname"] = firstname; + requestDoc["nachname"] = lastname; + requestDoc["alter"] = alter; + + String requestBody; + serializeJson(requestDoc, requestBody); + + int httpCode = http.POST(requestBody); + + if (httpCode == HTTP_CODE_CREATED) { + Serial.println("User data entered successfully."); + http.end(); + return true; + } else { + Serial.printf("Failed to enter user data, HTTP code: %d\n", httpCode); + http.end(); + return false; + } +} + + + // Keep this for backward compatibility bool userExists(const String& uid) { return checkUser(uid).exists; diff --git a/src/master.cpp b/src/master.cpp index cf96831..a97188a 100644 --- a/src/master.cpp +++ b/src/master.cpp @@ -19,7 +19,7 @@ #include #include #include - +#include const char* firmwareversion = "1.0.0"; // Version der Firmware @@ -249,8 +249,9 @@ void setup() { setupTimeAPI(server); setupLicenceAPI(server); setupDebugAPI(server); - setupBackendRoutes(server);// Speichere WLAN-Einstellungen, falls noch nicht vorhanden - + setupBackendRoutes(server); + setupRFIDRoute(server); + // Gespeicherte Daten laden loadButtonConfig(); @@ -264,6 +265,7 @@ void setup() { setupWebSocket(); setupLED(); setupMqttServer(); // MQTT Server initialisieren + setupRFID(); } @@ -272,4 +274,5 @@ void loop() { checkAutoReset(); loopMqttServer(); // MQTT Server in der Loop aufrufen loopWebSocket(); + loopRFID(); // RFID Loop aufrufen } diff --git a/src/rfid.h b/src/rfid.h index a840930..89c5837 100644 --- a/src/rfid.h +++ b/src/rfid.h @@ -1,141 +1,289 @@ #pragma once #include -#include #include #include #include // RFID Konfiguration -#define SS_PIN 21 -#define RST_PIN 22 -MFRC522 mfrc522(SS_PIN, RST_PIN); +#define RST_PIN 21 // Configurable, see typical pin layout above +#define SS_PIN 5 // Configurable, see typical pin layout above -// Webserver auf Port 80 -WebServer server(80); -// Struktur für Benutzerdaten -struct User { - String uid; - String vorname; - String nachname; - int alter; - unsigned long timestamp; -}; +MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance +std::map blockedUIDs; // Map to store blocked UIDs and their timestamps +const unsigned long BLOCK_DURATION = 10 * 1000; // 10 Seconds in milliseconds + +// Neue Variablen für API-basiertes Lesen +bool rfidReadRequested = false; +String lastReadUID = ""; +bool rfidReadSuccess = false; +unsigned long rfidReadStartTime = 0; +const unsigned long RFID_READ_TIMEOUT = 10000; // 10 Sekunden Timeout für API Requests + void setupRFID() { // SPI und RFID initialisieren - SPI.begin(); - mfrc522.PCD_Init(); - + SPI.begin(); // Init SPI bus + mfrc522.PCD_Init(); // Init MFRC522 + delay(4); // Optional delay. Some boards need more time after init to be ready + mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details } -void setupRoutes() { - // CORS Header für alle Anfragen - server.onNotFound([]() { - if (server.method() == HTTP_OPTIONS) { - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.sendHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); - server.sendHeader("Access-Control-Allow-Headers", "Content-Type"); - server.send(200); - } else { - server.send(404, "text/plain", "Not Found"); - } - }); - - // API: RFID UID lesen - server.on("/api/rfid/read", HTTP_POST, []() { - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.sendHeader("Content-Type", "application/json"); - - String uid = readRFIDCard(); - - DynamicJsonDocument doc(200); - - if (uid != "") { - doc["success"] = true; - doc["uid"] = uid; - Serial.println("UID gelesen: " + uid); - } else { - doc["success"] = false; - doc["error"] = "Keine RFID Karte gefunden"; - } - - String response; - serializeJson(doc, response); - server.send(200, "application/json", response); - }); - - // API: Neuen Benutzer erstellen - server.on("/api/users", HTTP_POST, []() { - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.sendHeader("Content-Type", "application/json"); - - DynamicJsonDocument doc(1024); - DeserializationError error = deserializeJson(doc, server.arg("plain")); - - if (error) { - DynamicJsonDocument errorDoc(200); - errorDoc["success"] = false; - errorDoc["error"] = "Ungültige JSON Daten"; - String response; - serializeJson(errorDoc, response); - server.send(400, "application/json", response); - return; - } - - // Daten aus JSON extrahieren - String uid = doc["uid"].as(); - String vorname = doc["vorname"].as(); - String nachname = doc["nachname"].as(); - int alter = doc["alter"].as(); - - - // Prüfen ob UID bereits existiert - - - - // Benutzer hinzufügen - // Erfolgreiche Antwort - DynamicJsonDocument successDoc(200); - successDoc["success"] = true; - successDoc["message"] = "Benutzer erfolgreich gespeichert"; - String response; - serializeJson(successDoc, response); - server.send(201, "application/json", response); - - Serial.println("Neuer Benutzer: " + vorname + " " + nachname + " (UID: " + uid + ")"); - }); -} - -// RFID Karte lesen -String readRFIDCard() { - // Prüfen ob neue Karte vorhanden +void handleAutomaticRFID() { if (!mfrc522.PICC_IsNewCardPresent()) { - return ""; + return; + } + + // Select one of the cards + if (!mfrc522.PICC_ReadCardSerial()) { + return; + } + + // Read the UID + String uid = ""; + for (byte i = 0; i < mfrc522.uid.size; i++) { + if (i > 0) + uid += ":"; + if (mfrc522.uid.uidByte[i] < 0x10) + uid += "0"; + uid += String(mfrc522.uid.uidByte[i], HEX); + } + + // Check if the UID is blocked + unsigned long currentTime = millis(); + if (blockedUIDs.find(uid) != blockedUIDs.end()) { + if (currentTime - blockedUIDs[uid] < BLOCK_DURATION) { + Serial.print(F("UID blocked for 10 seconds. Remaining time: ")); + Serial.print((BLOCK_DURATION - (currentTime - blockedUIDs[uid])) / 1000); + Serial.println(F(" seconds.")); + Serial.println(uid); + return; + } else { + // Remove the UID from the blocked list if the block duration has passed + blockedUIDs.erase(uid); + } + } + + // Process the UID + Serial.print(F("UID: ")); + Serial.println(uid); + + // Block the UID for 10 seconds + blockedUIDs[uid] = currentTime; + //show the remaining time for the block + Serial.print(F("UID blocked for 10 seconds. Remaining time: ")); + Serial.print((BLOCK_DURATION - (currentTime - blockedUIDs[uid])) / 1000); + Serial.println(F(" seconds.")); + + // Halt the card + mfrc522.PICC_HaltA(); +} + +// Neue Funktion für API-basiertes RFID Lesen +void handleAPIRFIDRead() { + unsigned long currentTime = millis(); + + // Timeout prüfen + if (currentTime - rfidReadStartTime > RFID_READ_TIMEOUT) { + Serial.println("RFID API Timeout - keine Karte erkannt"); + rfidReadRequested = false; + rfidReadSuccess = false; + lastReadUID = ""; + return; + } + + // Prüfen ob neue Karte vorhanden ist + if (!mfrc522.PICC_IsNewCardPresent()) { + return; } // Karte auswählen if (!mfrc522.PICC_ReadCardSerial()) { - return ""; + return; } - // UID zusammensetzen + // UID für API lesen (ohne Doppelpunkt-Trenner, Großbuchstaben) String uid = ""; for (byte i = 0; i < mfrc522.uid.size; i++) { - if (i > 0) uid += ":"; - if (mfrc522.uid.uidByte[i] < 0x10) uid += "0"; + if (mfrc522.uid.uidByte[i] < 0x10) { + uid += "0"; // Leading Zero für einstellige Hex-Werte + } uid += String(mfrc522.uid.uidByte[i], HEX); } + + // UID in Großbuchstaben konvertieren uid.toUpperCase(); - // Karte deaktivieren - mfrc522.PICC_HaltA(); + Serial.println("RFID API UID gelesen: " + uid); - return uid; + // Ergebnis speichern + lastReadUID = uid; + rfidReadSuccess = true; + rfidReadRequested = false; + + // Karte "halt" setzen + mfrc522.PICC_HaltA(); + mfrc522.PCD_StopCrypto1(); } + +// API Funktion: RFID Lesevorgang starten +void startRFIDRead() { + Serial.println("RFID API Lesevorgang gestartet..."); + rfidReadRequested = true; + rfidReadSuccess = false; + lastReadUID = ""; + rfidReadStartTime = millis(); +} + +// API Funktion: Prüfen ob Lesevorgang abgeschlossen +bool isRFIDReadComplete() { + return !rfidReadRequested; +} + +// API Funktion: Ergebnis des Lesevorgangs abrufen +String getRFIDReadResult(bool& success) { + success = rfidReadSuccess; + return lastReadUID; +} + +void setupRFIDRoute(AsyncWebServer& server) { + server.on("/api/rfid/read", HTTP_GET, [](AsyncWebServerRequest *request) { + Serial.println("api/rfid/read"); + + // Start RFID-Lesevorgang + startRFIDRead(); + unsigned long startTime = millis(); + + // Warten, bis eine UID gelesen wird oder Timeout eintritt + while (!isRFIDReadComplete()) { + if (millis() - startTime > RFID_READ_TIMEOUT) { + break; + } + delay(10); // Kurze Pause, um die CPU nicht zu blockieren + } + + DynamicJsonDocument response(200); + + if (rfidReadSuccess && lastReadUID.length() > 0) { + response["success"] = true; + response["uid"] = lastReadUID; + response["message"] = "UID erfolgreich gelesen"; + } else { + response["success"] = false; + response["error"] = "Keine RFID Karte erkannt oder Timeout"; + response["uid"] = ""; + } + + String jsonString; + serializeJson(response, jsonString); + request->send(200, "application/json", jsonString); + }); + +server.on("/api/users/insert", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, [](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { + Serial.println("/api/users/insert"); + + // Parse the incoming JSON payload + DynamicJsonDocument doc(512); + DeserializationError error = deserializeJson(doc, data, len); + + DynamicJsonDocument response(200); + + if (error) { + Serial.println("Fehler beim Parsen der JSON-Daten"); + response["success"] = false; + response["error"] = "Ungültige JSON-Daten"; + } else { + // Extract user data from the JSON payload + String uid = doc["uid"] | ""; + String vorname = doc["vorname"] | ""; + String nachname = doc["nachname"] | ""; + int alter = doc["alter"] | 0; + + // Validate the data + if (uid.isEmpty() || vorname.isEmpty() || nachname.isEmpty() || alter <= 0) { + Serial.println("Ungültige Eingabedaten"); + response["success"] = false; + response["error"] = "Ungültige Eingabedaten"; + } else { + // Process the data using the enterUserData function + Serial.println("Benutzerdaten empfangen:"); + Serial.println("UID: " + uid); + Serial.println("Vorname: " + vorname); + Serial.println("Nachname: " + nachname); + Serial.println("Alter: " + String(alter)); + + bool dbSuccess = enterUserData(uid, vorname, nachname, alter); + + if (dbSuccess) { + response["success"] = true; + response["message"] = "Benutzer erfolgreich gespeichert"; + } else { + response["success"] = false; + response["error"] = "Fehler beim Speichern in der Datenbank"; + } + } + } + + // Send the response back to the client + String jsonString; + serializeJson(response, jsonString); + request->send(200, "application/json", jsonString); +}); + + + + + + + +} + + + +// API Funktion: RFID Reader Status prüfen +bool checkRFIDReaderStatus() { + byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); + + // Bekannte MFRC522 Versionen: 0x91, 0x92 + if (version == 0x91 || version == 0x92) { + Serial.println("RFID Reader OK (Version: 0x" + String(version, HEX) + ")"); + return true; + } else { + Serial.println("RFID Reader Fehler (Version: 0x" + String(version, HEX) + ")"); + return false; + } +} + +// Hilfsfunktion: Blockierte UIDs aufräumen +void cleanupBlockedUIDs() { + unsigned long currentTime = millis(); + + // Iterator für sicheres Löschen während der Iteration + for (auto it = blockedUIDs.begin(); it != blockedUIDs.end();) { + if (currentTime - it->second >= BLOCK_DURATION) { + it = blockedUIDs.erase(it); + } else { + ++it; + } + } +} + +void loopRFID(){ + // Originale Funktionalität für automatisches Lesen + if (!rfidReadRequested) { + handleAutomaticRFID(); + } + + // API-basiertes Lesen verarbeiten + if (rfidReadRequested) { + handleAPIRFIDRead(); + } +} + +