This commit is contained in:
Carsten Graf
2025-09-18 23:21:14 +02:00
parent 4f0fc68d41
commit 02a60d84cf
7 changed files with 123 additions and 101 deletions

View File

@@ -12,7 +12,7 @@ html {
body {
font-family: "Segoe UI", Arial, sans-serif;
background: linear-gradient(135deg, #49bae4 0%, #223c83 100%);
background: linear-gradient(0deg, #0d1733 0%, #223c83 100%);
height: 100vh;
width: 100vw;
display: flex;
@@ -38,8 +38,8 @@ body {
text-decoration: none;
display: block;
cursor: pointer;
padding-left: 5px;
padding-right: 5px;
padding: 5px;
background:rgba(255, 255, 255, 0.6);
}
.logo:hover {
@@ -367,8 +367,8 @@ body {
}
.status.ready {
background-color: rgba(34, 60, 131, 0.3);
border: 2px solid #223c83;
background-color: rgb(0 165 3 / 54%);
border: 2px solid #06ff00;
animation: pulse 1s infinite;
}
@@ -379,7 +379,7 @@ body {
}
.status.running {
background-color: rgba(245, 157, 15, 0.3);
background-color: rgb(255 91 0 / 65%);
border: 2px solid #f59d0f;
}

View File

@@ -6,7 +6,7 @@
body {
font-family: "Segoe UI", Arial, sans-serif;
background: linear-gradient(135deg, #49bae4 0%, #223c83 100%);
background: linear-gradient(0deg, #0d1733 0%, #223c83 100%);
min-height: 100vh;
padding: 20px;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "master.h"
#include <Arduino.h>
#include <ArduinoJson.h>
#include <ESPAsyncWebServer.h>
#include <HTTPClient.h>
#include <preferencemanager.h>
@@ -78,7 +79,7 @@ UserData checkUser(const String &uid) {
userData.firstname = responseDoc["firstname"].as<String>();
userData.lastname = responseDoc["lastname"].as<String>();
userData.alter = responseDoc["alter"] | 0;
userData.exists = responseDoc["exists"] | true;
userData.exists = responseDoc["exists"] | false;
}
} else {
Serial.printf("User check failed, HTTP code: %d\n", httpCode);
@@ -88,43 +89,6 @@ UserData checkUser(const String &uid) {
return userData;
}
// Fügt einen neuen Benutzer mit den angegebenen Daten in die Datenbank ein.
bool enterUserData(const String &uid, const String &firstname,
const String &lastname, const String &geburtsdatum,
int alter) {
if (!backendOnline()) {
Serial.println("No internet connection, cannot enter user data.");
return false;
}
HTTPClient http;
http.begin(String(BACKEND_SERVER) + "/v1/private/create-player");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
// Create JSON payload
StaticJsonDocument<256> requestDoc;
requestDoc["rfiduid"] = uid;
requestDoc["firstname"] = firstname;
requestDoc["lastname"] = lastname;
requestDoc["birthdate"] = geburtsdatum;
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;
}
}
// Holt alle Standorte aus der Datenbank und gibt sie als JSON-Dokument zurück.
JsonDocument getAllLocations() {
JsonDocument locations; // Allocate memory for the JSON document
@@ -159,6 +123,45 @@ JsonDocument getAllLocations() {
// (Kompatibilitätsfunktion).
bool userExists(const String &uid) { return checkUser(uid).exists; }
// Fügt einen neuen Benutzer in die Datenbank ein
bool enterUserData(const String &uid, const String &vorname,
const String &nachname, const String &geburtsdatum,
int alter) {
if (!backendOnline()) {
Serial.println("No internet connection, cannot enter user data.");
return false;
}
HTTPClient http;
http.begin(String(BACKEND_SERVER) + "/v1/private/users/insert");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
// Create JSON payload
StaticJsonDocument<512> requestDoc;
requestDoc["uid"] = uid;
requestDoc["firstname"] = vorname;
requestDoc["lastname"] = nachname;
requestDoc["geburtsdatum"] = geburtsdatum;
requestDoc["alter"] = alter;
String requestBody;
serializeJson(requestDoc, requestBody);
int httpCode = http.POST(requestBody);
bool success = (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED);
if (success) {
Serial.println("User data successfully entered into database");
} else {
Serial.printf("Failed to enter user data, HTTP code: %d\n", httpCode);
}
http.end();
return success;
}
// Richtet die HTTP-Routen für die Backend-API ein (z.B. Health-Check, User- und
// Location-Abfragen).
void setupBackendRoutes(AsyncWebServer &server) {

View File

@@ -21,7 +21,7 @@ struct TimerData1 {
bool isRunning = false;
bool isReady = true; // Status für Bahn 1
bool isArmed = false; // Status für Bahn 1 (armiert/nicht armiert)
char RFIDUID = "";
char RFIDUID[32] = "";
};
// Timer Struktur für Bahn 2
@@ -34,7 +34,7 @@ struct TimerData2 {
bool isRunning = false;
bool isReady = true; // Status für Bahn 2
bool isArmed = false; // Status für Bahn 2 (armiert/nicht armiert)
char RFIDUID = "";
char RFIDUID[32] = "";
};
// Button Konfiguration
@@ -69,9 +69,9 @@ int gamemode; // 0=Individual, 1=Wettkampf
bool startCompetition = false; // Flag, ob der Timer gestartet wurde
// Lane Configuration
int laneConfigType = 0; // 0=Identical, 1=Different
int lane1DifficultyType = 0; // 0=Light, 1=Heavy (difficulty)
int lane2DifficultyType = 0; // 0=Light, 1=Heavy (difficulty)
int laneConfigType = 0; // 0=Identical, 1=Different
int lane1DifficultyType = 0; // 0=Light, 1=Heavy (difficulty)
int lane2DifficultyType = 0; // 0=Light, 1=Heavy (difficulty)
// Function Declarations
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len);

View File

@@ -2,8 +2,8 @@
#include <Arduino.h>
#include <Preferences.h>
#include <master.h>
#include <licenceing.h>
#include <master.h>
// Persist and load button configuration
void saveButtonConfig() {
@@ -43,8 +43,8 @@ void saveSettings() {
preferences.putULong("maxTimeDisplay", maxTimeDisplay);
preferences.putUInt("gamemode", gamemode);
preferences.putUInt("laneConfigType", laneConfigType);
preferences.putUInt("lane1DifficultyType", lane1DifficultyType);
preferences.putUInt("lane2DifficultyType", lane2DifficultyType);
preferences.putUInt("lane1Diff", lane1DifficultyType);
preferences.putUInt("lane2Diff", lane2DifficultyType);
preferences.end();
}
@@ -54,8 +54,8 @@ void loadSettings() {
maxTimeDisplay = preferences.getULong("maxTimeDisplay", 20000);
gamemode = preferences.getUInt("gamemode", 0);
laneConfigType = preferences.getUInt("laneConfigType", 0);
lane1DifficultyType = preferences.getUInt("lane1DifficultyType", 0);
lane2DifficultyType = preferences.getUInt("lane2DifficultyType", 0);
lane1DifficultyType = preferences.getUInt("lane1Diff", 0);
lane2DifficultyType = preferences.getUInt("lane2Diff", 0);
preferences.end();
}

View File

@@ -1,9 +1,11 @@
#pragma once
#include "databasebackend.h"
#include <Arduino.h>
#include <ArduinoJson.h>
#include <MFRC522.h>
#include <SPI.h>
// RFID Konfiguration
#define RST_PIN 21 // Configurable, see typical pin layout above
#define SS_PIN 5 // Configurable, see typical pin layout above

View File

@@ -33,7 +33,6 @@ void setupRoutes() {
request->send(SPIFFS, "/settings.html", "text/html");
});
server.on("/firmware.bin", HTTP_GET, [](AsyncWebServerRequest *request) {
if (SPIFFS.exists("/firmware.bin")) {
request->send(SPIFFS, "/firmware.bin", "application/octet-stream");
@@ -313,51 +312,69 @@ void setupRoutes() {
});
// Lane Configuration API Routes
server.on("/api/set-lane-config", HTTP_POST, [](AsyncWebServerRequest *request) {
Serial.println("/api/set-lane-config called");
String body = request->getBody();
DynamicJsonDocument doc(256);
deserializeJson(doc, body);
if (doc.containsKey("type")) {
String laneType = doc["type"];
laneConfigType = (laneType == "identical") ? 0 : 1;
if (laneConfigType == 1 && doc.containsKey("lane1Difficulty") && doc.containsKey("lane2Difficulty")) {
String lane1Difficulty = doc["lane1Difficulty"];
String lane2Difficulty = doc["lane2Difficulty"];
lane1DifficultyType = (lane1Difficulty == "light") ? 0 : 1;
lane2DifficultyType = (lane2Difficulty == "light") ? 0 : 1;
}
Serial.printf("Lane configuration set - Type: %s, Lane1: %s, Lane2: %s\n",
laneType.c_str(),
(laneConfigType == 1) ? ((lane1DifficultyType == 0) ? "light" : "heavy") : "identical",
(laneConfigType == 1) ? ((lane2DifficultyType == 0) ? "light" : "heavy") : "identical");
DynamicJsonDocument response(64);
response["success"] = true;
String result;
serializeJson(response, result);
request->send(200, "application/json", result);
saveSettings();
} else {
request->send(400, "application/json", "{\"success\":false,\"error\":\"Lane type missing\"}");
}
});
server.on(
"/api/set-lane-config", HTTP_POST, [](AsyncWebServerRequest *request) {},
NULL,
[](AsyncWebServerRequest *request, uint8_t *data, size_t len,
size_t index, size_t total) {
Serial.println("/api/set-lane-config called");
server.on("/api/get-lane-config", HTTP_GET, [](AsyncWebServerRequest *request) {
DynamicJsonDocument doc(128);
doc["type"] = laneConfigType == 0 ? "identical" : "different";
if (laneConfigType == 1) {
doc["lane1Difficulty"] = lane1DifficultyType == 0 ? "light" : "heavy";
doc["lane2Difficulty"] = lane2DifficultyType == 0 ? "light" : "heavy";
}
String result;
serializeJson(doc, result);
request->send(200, "application/json", result);
});
DynamicJsonDocument doc(256);
DeserializationError error = deserializeJson(doc, data, len);
if (error) {
Serial.println("JSON parsing error");
request->send(400, "application/json",
"{\"success\":false,\"error\":\"Invalid JSON\"}");
return;
}
if (doc.containsKey("type")) {
String laneType = doc["type"];
laneConfigType = (laneType == "identical") ? 0 : 1;
if (laneConfigType == 1 && doc.containsKey("lane1Difficulty") &&
doc.containsKey("lane2Difficulty")) {
String lane1Difficulty = doc["lane1Difficulty"];
String lane2Difficulty = doc["lane2Difficulty"];
lane1DifficultyType = (lane1Difficulty == "light") ? 0 : 1;
lane2DifficultyType = (lane2Difficulty == "light") ? 0 : 1;
}
Serial.printf(
"Lane configuration set - Type: %s, Lane1: %s, Lane2: %s\n",
laneType.c_str(),
(laneConfigType == 1)
? ((lane1DifficultyType == 0) ? "light" : "heavy")
: "identical",
(laneConfigType == 1)
? ((lane2DifficultyType == 0) ? "light" : "heavy")
: "identical");
DynamicJsonDocument response(64);
response["success"] = true;
String result;
serializeJson(response, result);
request->send(200, "application/json", result);
saveSettings();
} else {
request->send(400, "application/json",
"{\"success\":false,\"error\":\"Lane type missing\"}");
}
});
server.on(
"/api/get-lane-config", HTTP_GET, [](AsyncWebServerRequest *request) {
DynamicJsonDocument doc(128);
doc["type"] = laneConfigType == 0 ? "identical" : "different";
if (laneConfigType == 1) {
doc["lane1Difficulty"] = lane1DifficultyType == 0 ? "light" : "heavy";
doc["lane2Difficulty"] = lane2DifficultyType == 0 ? "light" : "heavy";
}
String result;
serializeJson(doc, result);
request->send(200, "application/json", result);
});
// Statische Dateien
server.serveStatic("/", SPIFFS, "/");