RFID Master Working, Read the RFID and enter it into the database

This commit is contained in:
Carsten Graf
2025-06-08 14:44:41 +02:00
parent c35e857904
commit f2fe9ac13c
5 changed files with 308 additions and 124 deletions

View File

@@ -88,7 +88,7 @@
try { try {
// API Aufruf zum Erstellen des Benutzers // API Aufruf zum Erstellen des Benutzers
const response = await fetch(`/api/users`, { const response = await fetch(`/api/users/insert`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -110,9 +110,6 @@
// Formular zurücksetzen // Formular zurücksetzen
clearForm(); clearForm();
// Daten neu laden
await loadUserData();
// UID Feld fokussieren für nächsten Eintrag // UID Feld fokussieren für nächsten Eintrag
setTimeout(() => { setTimeout(() => {
document.getElementById('uid').focus(); document.getElementById('uid').focus();
@@ -223,7 +220,7 @@
try { try {
// API Aufruf zum RFID Reader // API Aufruf zum RFID Reader
const response = await fetch(`/api/rfid/read`, { const response = await fetch(`/api/rfid/read`, {
method: 'POST', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
} }
@@ -233,7 +230,7 @@
if (result.success && result.uid) { if (result.success && result.uid) {
// UID in das Eingabefeld setzen // UID in das Eingabefeld setzen
uidInput.value = result.uid.toUpperCase(); uidInput.value = result.uid.match(/.{1,2}/g).join(':').toUpperCase();
uidInput.focus(); uidInput.focus();
// Visuelles Feedback // Visuelles Feedback

View File

@@ -14,7 +14,6 @@ default_envs = esp32dev
[env] [env]
platform = https://github.com/platformio/platform-espressif32.git platform = https://github.com/platformio/platform-espressif32.git
framework = arduino framework = arduino
lib_deps = esp32async/ESPAsyncWebServer@^3.7.7
lib_compat_mode = strict lib_compat_mode = strict
[env:wemos_d1_mini32] [env:wemos_d1_mini32]

View File

@@ -81,6 +81,43 @@ UserData checkUser(const String& uid) {
return userData; 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 // Keep this for backward compatibility
bool userExists(const String& uid) { bool userExists(const String& uid) {
return checkUser(uid).exists; return checkUser(uid).exists;

View File

@@ -19,7 +19,7 @@
#include <webserverrouter.h> #include <webserverrouter.h>
#include <communication.h> #include <communication.h>
#include <databasebackend.h> #include <databasebackend.h>
#include <rfid.h>
const char* firmwareversion = "1.0.0"; // Version der Firmware const char* firmwareversion = "1.0.0"; // Version der Firmware
@@ -249,7 +249,8 @@ void setup() {
setupTimeAPI(server); setupTimeAPI(server);
setupLicenceAPI(server); setupLicenceAPI(server);
setupDebugAPI(server); setupDebugAPI(server);
setupBackendRoutes(server);// Speichere WLAN-Einstellungen, falls noch nicht vorhanden setupBackendRoutes(server);
setupRFIDRoute(server);
// Gespeicherte Daten laden // Gespeicherte Daten laden
@@ -264,6 +265,7 @@ void setup() {
setupWebSocket(); setupWebSocket();
setupLED(); setupLED();
setupMqttServer(); // MQTT Server initialisieren setupMqttServer(); // MQTT Server initialisieren
setupRFID();
} }
@@ -272,4 +274,5 @@ void loop() {
checkAutoReset(); checkAutoReset();
loopMqttServer(); // MQTT Server in der Loop aufrufen loopMqttServer(); // MQTT Server in der Loop aufrufen
loopWebSocket(); loopWebSocket();
loopRFID(); // RFID Loop aufrufen
} }

View File

@@ -1,141 +1,289 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include <WebServer.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <SPI.h> #include <SPI.h>
#include <MFRC522.h> #include <MFRC522.h>
// RFID Konfiguration // RFID Konfiguration
#define SS_PIN 21 #define RST_PIN 21 // Configurable, see typical pin layout above
#define RST_PIN 22 #define SS_PIN 5 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN);
// Webserver auf Port 80
WebServer server(80);
// Struktur für Benutzerdaten MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
struct User { std::map<String, unsigned long> blockedUIDs; // Map to store blocked UIDs and their timestamps
String uid; const unsigned long BLOCK_DURATION = 10 * 1000; // 10 Seconds in milliseconds
String vorname;
String nachname; // Neue Variablen für API-basiertes Lesen
int alter; bool rfidReadRequested = false;
unsigned long timestamp; 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() { void setupRFID() {
// SPI und RFID initialisieren // SPI und RFID initialisieren
SPI.begin(); SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); 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); void handleAutomaticRFID() {
if (!mfrc522.PICC_IsNewCardPresent()) {
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; return;
} }
// Daten aus JSON extrahieren // Select one of the cards
String uid = doc["uid"].as<String>(); if (!mfrc522.PICC_ReadCardSerial()) {
String vorname = doc["vorname"].as<String>(); return;
String nachname = doc["nachname"].as<String>(); }
int alter = doc["alter"].as<int>();
// 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);
}
// Prüfen ob UID bereits existiert // 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."));
// Benutzer hinzufügen // Halt the card
mfrc522.PICC_HaltA();
// 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 // Neue Funktion für API-basiertes RFID Lesen
String readRFIDCard() { void handleAPIRFIDRead() {
// Prüfen ob neue Karte vorhanden 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()) { if (!mfrc522.PICC_IsNewCardPresent()) {
return ""; return;
} }
// Karte auswählen // Karte auswählen
if (!mfrc522.PICC_ReadCardSerial()) { if (!mfrc522.PICC_ReadCardSerial()) {
return ""; return;
} }
// UID zusammensetzen // UID für API lesen (ohne Doppelpunkt-Trenner, Großbuchstaben)
String uid = ""; String uid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) { for (byte i = 0; i < mfrc522.uid.size; i++) {
if (i > 0) uid += ":"; if (mfrc522.uid.uidByte[i] < 0x10) {
if (mfrc522.uid.uidByte[i] < 0x10) uid += "0"; uid += "0"; // Leading Zero für einstellige Hex-Werte
}
uid += String(mfrc522.uid.uidByte[i], HEX); uid += String(mfrc522.uid.uidByte[i], HEX);
} }
// UID in Großbuchstaben konvertieren
uid.toUpperCase(); uid.toUpperCase();
// Karte deaktivieren Serial.println("RFID API UID gelesen: " + uid);
mfrc522.PICC_HaltA();
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();
}
}