RFID message ins backend geht, websocket fürs frontend
This commit is contained in:
@@ -150,6 +150,35 @@ html {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.swimmer-name {
|
||||
font-size: clamp(1.5rem, 3.5vw, 2.2rem);
|
||||
font-weight: bold;
|
||||
margin-bottom: clamp(15px, 2vh, 25px);
|
||||
padding: clamp(8px, 1.5vh, 12px) clamp(12px, 2vw, 18px);
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 15px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(5px);
|
||||
animation: fadeIn 0.5s ease-in;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.time-display {
|
||||
font-size: clamp(3rem, 9vw, 10rem);
|
||||
font-weight: bold;
|
||||
@@ -280,6 +309,11 @@ html {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.swimmer-name {
|
||||
font-size: clamp(1.2rem, 4vw, 1.8rem);
|
||||
margin-bottom: clamp(10px, 1.5vh, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
@@ -299,4 +333,9 @@ html {
|
||||
.timer-container {
|
||||
padding: 0 2vw;
|
||||
}
|
||||
}
|
||||
|
||||
.swimmer-name {
|
||||
font-size: clamp(1rem, 4vw, 1.5rem);
|
||||
padding: clamp(6px, 1vh, 10px) clamp(8px, 1.5vw, 12px);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="index.css" />
|
||||
<link rel="icon" type="image/x-icon" href="/pictures/favicon.ico">
|
||||
|
||||
<title>NinjaCross Timer</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<body>
|
||||
<a href="/about" class="logo" title="Über NinjaCross Timer">
|
||||
<img src="/pictures/logo.png" alt="NinjaCross Logo" />
|
||||
</a>
|
||||
@@ -29,12 +29,14 @@
|
||||
|
||||
<div class="timer-container">
|
||||
<div class="lane">
|
||||
<div id="name1" class="swimmer-name" style="display: none;"></div>
|
||||
<h2>🏊♀️ Bahn 1</h2>
|
||||
<div id="time1" class="time-display">00.00</div>
|
||||
<div id="status1" class="status ready">Bereit</div>
|
||||
</div>
|
||||
|
||||
<div class="lane">
|
||||
<div id="name2" class="swimmer-name" style="display: none;"></div>
|
||||
<h2>🏊♂️ Bahn 2</h2>
|
||||
<div id="time2" class="time-display">00.00</div>
|
||||
<div id="status2" class="status ready">Bereit</div>
|
||||
@@ -64,6 +66,37 @@
|
||||
let lastSync = Date.now();
|
||||
let learningMode = false;
|
||||
let learningButton = "";
|
||||
let name1 = "";
|
||||
let name2 = "";
|
||||
const ws = new WebSocket(`ws://${window.location.host}/ws`);
|
||||
|
||||
// Handle WebSocket events
|
||||
ws.onopen = () => {
|
||||
console.log("WebSocket connected");
|
||||
};
|
||||
ws.onclose = () => {
|
||||
console.log("WebSocket disconnected");
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
console.log("WebSocket message received:", event.data);
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
if (data.firstname && data.lastname && data.lane) {
|
||||
if (data.lane === "start1") {
|
||||
name1 = `${data.firstname} ${data.lastname}`;
|
||||
} else if (data.lane === "start2") {
|
||||
name2 = `${data.firstname} ${data.lastname}`;
|
||||
}
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error processing WebSocket message:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function formatTime(seconds) {
|
||||
if (seconds === 0) return "00.00";
|
||||
@@ -83,7 +116,6 @@
|
||||
display2 += (now - lastSync) / 1000;
|
||||
}
|
||||
|
||||
|
||||
document.getElementById("time1").textContent = formatTime(display1);
|
||||
const s1 = document.getElementById("status1");
|
||||
s1.className = `status ${status1}`;
|
||||
@@ -109,6 +141,24 @@
|
||||
document.getElementById("best2").textContent =
|
||||
best2 > 0 ? formatTime(best2) + "s" : "--.-";
|
||||
|
||||
// Namen anzeigen/verstecken - verbesserte Logik
|
||||
const name1Element = document.getElementById("name1");
|
||||
const name2Element = document.getElementById("name2");
|
||||
|
||||
if (name1 && name1.trim() !== "") {
|
||||
name1Element.textContent = name1;
|
||||
name1Element.style.display = "block";
|
||||
} else {
|
||||
name1Element.style.display = "none";
|
||||
}
|
||||
|
||||
if (name2 && name2.trim() !== "") {
|
||||
name2Element.textContent = name2;
|
||||
name2Element.style.display = "block";
|
||||
} else {
|
||||
name2Element.style.display = "none";
|
||||
}
|
||||
|
||||
// Lernmodus
|
||||
const learningDisplay = document.getElementById("learning-display");
|
||||
if (learningMode) {
|
||||
@@ -139,7 +189,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
// Sync with backend every 2 seconds
|
||||
// Sync with backend every 1 second
|
||||
setInterval(syncFromBackend, 1000);
|
||||
|
||||
// Smooth update every 50ms
|
||||
|
||||
BIN
data/pictures/favicon.ico
Normal file
BIN
data/pictures/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -4,6 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="rfid.css" />
|
||||
<link rel="icon" type="image/x-icon" href="/pictures/favicon.ico">
|
||||
|
||||
<title>RFID Daten Eingabe</title>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<!-- Meta Tags -->
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/x-icon" href="/pictures/favicon.ico">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link rel="stylesheet" href="settings.css" />
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "helper.h"
|
||||
#include <debug.h>
|
||||
#include <map>
|
||||
#include <databasebackend.h>
|
||||
#include <webserverrouter.h>
|
||||
|
||||
struct TimestampData {
|
||||
uint64_t lastMessageTimestamp; // Timestamp from the device
|
||||
@@ -35,52 +37,6 @@ typedef struct {
|
||||
|
||||
PicoMQTT::Server mqtt;
|
||||
|
||||
void processHeartbeat(const char* topic, const char* payload) {
|
||||
String macAddress = String(topic).substring(15);
|
||||
|
||||
StaticJsonDocument<200> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
|
||||
if (error) {
|
||||
Serial.printf("JSON parsing failed for MAC %s: %s\n", macAddress.c_str(), error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t messageTimestamp = doc["timestamp"] | 0;
|
||||
uint64_t currentLocalTime = getCurrentTimestampMs();
|
||||
|
||||
// Update timestamps for current device
|
||||
if (deviceTimestamps.count(macAddress) > 0) {
|
||||
TimestampData& data = deviceTimestamps[macAddress];
|
||||
uint64_t messageDiff = messageTimestamp - data.lastMessageTimestamp;
|
||||
uint64_t localDiff = currentLocalTime - data.lastLocalTimestamp;
|
||||
data.drift = localDiff - messageDiff;
|
||||
}
|
||||
|
||||
// Calculate drift relative to all other devices
|
||||
Serial.printf("\nDrift analysis for device %s:\n", macAddress.c_str());
|
||||
Serial.println("----------------------------------------");
|
||||
|
||||
for (const auto& device : deviceTimestamps) {
|
||||
if (device.first != macAddress) { // Skip comparing to self
|
||||
int64_t timeDiff = messageTimestamp - device.second.lastMessageTimestamp;
|
||||
int64_t relativeDrift = timeDiff - (currentLocalTime - device.second.lastLocalTimestamp);
|
||||
|
||||
Serial.printf("Relative to %s:\n", device.first.c_str());
|
||||
Serial.printf(" Time difference: %lld ms\n", timeDiff);
|
||||
Serial.printf(" Relative drift: %lld ms\n", relativeDrift);
|
||||
Serial.println("----------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
// Update stored timestamps for current device
|
||||
deviceTimestamps[macAddress] = {
|
||||
messageTimestamp,
|
||||
currentLocalTime,
|
||||
deviceTimestamps[macAddress].drift
|
||||
};
|
||||
}
|
||||
|
||||
void readButtonJSON(const char * topic, const char * payload) {
|
||||
|
||||
if(strcmp(topic, "aquacross/button/press") == 0){
|
||||
@@ -133,22 +89,99 @@ void readButtonJSON(const char * topic, const char * payload) {
|
||||
}
|
||||
}
|
||||
|
||||
void readRFIDfromButton(const char * topic, const char * payload) {
|
||||
// Create a JSON document to hold the button press data
|
||||
StaticJsonDocument<256> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (!error) {
|
||||
const char* mac = doc["buttonmac"] | "unknown";
|
||||
const char* uid = doc["uid"] | "unknown";
|
||||
|
||||
Serial.printf("RFID Read from Button:\n");
|
||||
Serial.printf(" Button MAC: %s\n", mac);
|
||||
Serial.printf(" UID: %s\n", uid);
|
||||
|
||||
// Convert buttonmac to byte array for comparison
|
||||
auto macBytes = macStringToBytes(mac);
|
||||
|
||||
// Check if the buttonmac matches buttonConfigs.start1.mac
|
||||
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
||||
// Fetch user data
|
||||
UserData userData = checkUser(uid);
|
||||
if (userData.exists) {
|
||||
// Log user data
|
||||
Serial.printf("User found for start1: %s %s, Alter: %d\n",
|
||||
userData.firstname.c_str(),
|
||||
userData.lastname.c_str(),
|
||||
userData.alter);
|
||||
|
||||
// Create JSON message to send to the frontend
|
||||
StaticJsonDocument<128> messageDoc;
|
||||
messageDoc["firstname"] = userData.firstname;
|
||||
messageDoc["lastname"] = userData.lastname;
|
||||
messageDoc["lane"] = "start1"; // Add lane information
|
||||
|
||||
String message;
|
||||
serializeJson(messageDoc, message);
|
||||
|
||||
// Push the message to the frontend
|
||||
pushUpdateToFrontend(message);
|
||||
Serial.printf("Pushed user data for start1 to frontend: %s\n", message.c_str());
|
||||
} else {
|
||||
Serial.println("User not found for UID: " + String(uid));
|
||||
}
|
||||
}
|
||||
// Check if the buttonmac matches buttonConfigs.start2.mac
|
||||
else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
||||
// Fetch user data
|
||||
UserData userData = checkUser(uid);
|
||||
if (userData.exists) {
|
||||
// Log user data
|
||||
Serial.printf("User found for start2: %s %s, Alter: %d\n",
|
||||
userData.firstname.c_str(),
|
||||
userData.lastname.c_str(),
|
||||
userData.alter);
|
||||
|
||||
// Create JSON message to send to the frontend
|
||||
StaticJsonDocument<128> messageDoc;
|
||||
messageDoc["firstname"] = userData.firstname;
|
||||
messageDoc["lastname"] = userData.lastname;
|
||||
messageDoc["lane"] = "start2"; // Add lane information
|
||||
|
||||
String message;
|
||||
serializeJson(messageDoc, message);
|
||||
|
||||
// Push the message to the frontend
|
||||
pushUpdateToFrontend(message);
|
||||
Serial.printf("Pushed user data for start2 to frontend: %s\n", message.c_str());
|
||||
} else {
|
||||
Serial.println("User not found for UID: " + String(uid));
|
||||
}
|
||||
} else {
|
||||
Serial.println("Button MAC does not match start1.mac or start2.mac");
|
||||
}
|
||||
} else {
|
||||
Serial.println("Failed to parse RFID JSON");
|
||||
}
|
||||
}
|
||||
|
||||
void setupMqttServer() {
|
||||
|
||||
// Set up the MQTT server with the desired port
|
||||
// Subscribe to a topic pattern and attach a callback
|
||||
mqtt.subscribe("#", [](const char * topic, const char * payload) {
|
||||
if (strncmp(topic, "heartbeat/alive/", 15) == 0) {
|
||||
processHeartbeat(topic, payload);
|
||||
} else if (strcmp(topic, "aquacross/button/press") == 0) {
|
||||
//Message received callback
|
||||
//Serial.printf("Received message on topic '%s': %s\n", topic, payload);
|
||||
if (strcmp(topic, "aquacross/button/press") == 0) {
|
||||
readButtonJSON(topic, payload);
|
||||
} else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) {
|
||||
readRFIDfromButton(topic, payload);
|
||||
// Handle RFID read messages
|
||||
|
||||
}
|
||||
updateStatusLED(3);
|
||||
});
|
||||
|
||||
// Add the button subscription
|
||||
|
||||
// Start the MQTT server
|
||||
mqtt.begin();
|
||||
|
||||
@@ -168,6 +201,7 @@ void loopMqttServer() {
|
||||
mqtt.publish("sync/time", timeStr);
|
||||
lastPublish = millis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sendMQTTMessage(const char * topic, const char * message) {
|
||||
@@ -187,3 +221,5 @@ void sendMQTTJSONMessage(const char * topic, const JsonDocument & doc) {
|
||||
Serial.printf("Published JSON message to topic '%s': %s\n", topic, jsonString.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "master.h"
|
||||
@@ -17,34 +18,76 @@ bool backendOnline() {
|
||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||
|
||||
int httpCode = http.GET();
|
||||
bool isOnline = (httpCode == HTTP_CODE_OK);
|
||||
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
return true;
|
||||
if (isOnline) {
|
||||
Serial.println("Database server connection successful");
|
||||
} else {
|
||||
return false;
|
||||
Serial.printf("Database server connection failed, error: %d\n", httpCode);
|
||||
}
|
||||
|
||||
http.end();
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
bool userExists(const String& userId) {
|
||||
struct UserData {
|
||||
String uid;
|
||||
String firstname;
|
||||
String lastname;
|
||||
int alter;
|
||||
bool exists;
|
||||
};
|
||||
|
||||
// UserData checkUser(const String& uid) is defined only once to avoid redefinition errors.
|
||||
UserData checkUser(const String& uid) {
|
||||
|
||||
UserData userData = {"", "", "", 0, false};
|
||||
|
||||
if (!backendOnline()) {
|
||||
Serial.println("No internet connection, cannot check user existence.");
|
||||
return false;
|
||||
Serial.println("No internet connection, cannot check user.");
|
||||
return userData;
|
||||
}
|
||||
|
||||
HTTPClient http;
|
||||
http.begin(String(BACKEND_SERVER) + "/api/users/" + userId);
|
||||
http.begin(String(BACKEND_SERVER) + "/api/users/find");
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||
|
||||
//Post request to check if user exists
|
||||
int httpCode = http.POST("");
|
||||
// Create JSON payload
|
||||
StaticJsonDocument<200> requestDoc;
|
||||
requestDoc["uid"] = uid;
|
||||
String requestBody;
|
||||
serializeJson(requestDoc, requestBody);
|
||||
|
||||
int httpCode = http.POST(requestBody);
|
||||
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
String payload = http.getString();
|
||||
StaticJsonDocument<512> responseDoc;
|
||||
DeserializationError error = deserializeJson(responseDoc, payload);
|
||||
|
||||
if (!error) {
|
||||
userData.uid = responseDoc["uid"].as<String>();
|
||||
userData.firstname = responseDoc["firstname"].as<String>();
|
||||
userData.lastname = responseDoc["lastname"].as<String>();
|
||||
userData.alter = responseDoc["alter"] | 0;
|
||||
userData.exists = true;
|
||||
}
|
||||
} else {
|
||||
Serial.printf("User check failed, HTTP code: %d\n", httpCode);
|
||||
}
|
||||
|
||||
http.end();
|
||||
return userData;
|
||||
}
|
||||
|
||||
// Keep this for backward compatibility
|
||||
bool userExists(const String& uid) {
|
||||
return checkUser(uid).exists;
|
||||
}
|
||||
|
||||
void setupBackendRoutes(AsyncWebServer& server) {
|
||||
|
||||
server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
|
||||
DynamicJsonDocument doc(64);
|
||||
|
||||
@@ -162,10 +162,26 @@ void saveWifiSettings() {
|
||||
}
|
||||
|
||||
void loadWifiSettings() {
|
||||
preferences.begin("wifi", true);
|
||||
ssidSTA = preferences.getString("ssid", "").c_str();
|
||||
passwordSTA = preferences.getString("password", "").c_str();
|
||||
preferences.end();
|
||||
preferences.begin("wifi", true);
|
||||
|
||||
// Speicher freigeben, falls bereits zugewiesen
|
||||
if (ssidSTA) {
|
||||
free(ssidSTA);
|
||||
}
|
||||
if (passwordSTA) {
|
||||
free(passwordSTA);
|
||||
}
|
||||
|
||||
// Neue Werte laden und dynamisch zuweisen
|
||||
String ssid = preferences.getString("ssid", "");
|
||||
String password = preferences.getString("password", "");
|
||||
ssidSTA = strdup(ssid.c_str());
|
||||
passwordSTA = strdup(password.c_str());
|
||||
|
||||
preferences.end();
|
||||
|
||||
// Debug-Ausgabe
|
||||
Serial.printf("WLAN-Einstellungen geladen: SSID=%s, Passwort=%s\n", ssidSTA, passwordSTA);
|
||||
}
|
||||
|
||||
int checkLicence() {
|
||||
@@ -179,7 +195,6 @@ String getTimerDataJSON() {
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// Bahn 1
|
||||
if (timerData.isRunning1) {
|
||||
doc["time1"] = (currentTime - timerData.startTime1) / 1000.0;
|
||||
@@ -234,7 +249,7 @@ void setup() {
|
||||
setupTimeAPI(server);
|
||||
setupLicenceAPI(server);
|
||||
setupDebugAPI(server);
|
||||
setupBackendRoutes(server);
|
||||
setupBackendRoutes(server);// Speichere WLAN-Einstellungen, falls noch nicht vorhanden
|
||||
|
||||
|
||||
// Gespeicherte Daten laden
|
||||
@@ -246,6 +261,7 @@ void setup() {
|
||||
setupOTA(&server);
|
||||
|
||||
setupRoutes();
|
||||
setupWebSocket();
|
||||
setupLED();
|
||||
setupMqttServer(); // MQTT Server initialisieren
|
||||
|
||||
@@ -255,4 +271,5 @@ void setup() {
|
||||
void loop() {
|
||||
checkAutoReset();
|
||||
loopMqttServer(); // MQTT Server in der Loop aufrufen
|
||||
loopWebSocket();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <WebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
@@ -21,10 +22,6 @@ struct User {
|
||||
unsigned long timestamp;
|
||||
};
|
||||
|
||||
// Array für Benutzer (max 100 Benutzer)
|
||||
User users[100];
|
||||
int userCount = 0;
|
||||
|
||||
void setupRFID() {
|
||||
|
||||
// SPI und RFID initialisieren
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "master.h"
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <AsyncWebSocket.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
|
||||
#include <buttonassigh.h>
|
||||
#include <wificlass.h>
|
||||
|
||||
AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
|
||||
void setupRoutes(){
|
||||
// Web Server Routes
|
||||
|
||||
// Attach WebSocket to the server
|
||||
server.addHandler(&ws);
|
||||
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
request->send(SPIFFS, "/index.html", "text/html");
|
||||
});
|
||||
@@ -166,34 +173,35 @@ void setupRoutes(){
|
||||
});
|
||||
|
||||
// Setze WLAN-Name und Passwort (POST)
|
||||
server.on("/api/set-wifi", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
server.on("/api/set-wifi", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
Serial.println("/api/set-wifi called");
|
||||
String ssid, password;
|
||||
if (request->hasParam("ssid", true)) {
|
||||
ssid = request->getParam("ssid", true)->value();
|
||||
ssid = request->getParam("ssid", true)->value();
|
||||
}
|
||||
if (request->hasParam("password", true)) {
|
||||
password = request->getParam("password", true)->value();
|
||||
password = request->getParam("password", true)->value();
|
||||
}
|
||||
if (ssid.length() > 0) {
|
||||
// Hier speichern wir die neuen Werte (z.B. in Preferences oder global)
|
||||
// Beispiel: strcpy(ssidSTA, ssid.c_str());
|
||||
// Beispiel: strcpy(passwordSTA, password.c_str());
|
||||
// In deinem Projekt ggf. persistent speichern!
|
||||
// Hier als global (unsicher, nach Neustart verloren!):
|
||||
ssidSTA = strdup(ssid.c_str());
|
||||
passwordSTA = strdup(password.c_str());
|
||||
// Rückmeldung
|
||||
DynamicJsonDocument doc(64);
|
||||
doc["success"] = true;
|
||||
String result;
|
||||
serializeJson(doc, result);
|
||||
request->send(200, "application/json", result);
|
||||
Serial.println("WiFi-Settings updated (nur bis zum Neustart aktiv!)");
|
||||
// Speicher freigeben, bevor neue Werte zugewiesen werden
|
||||
free(ssidSTA);
|
||||
free(passwordSTA);
|
||||
|
||||
// Neue Werte zuweisen
|
||||
ssidSTA = strdup(ssid.c_str());
|
||||
passwordSTA = strdup(password.c_str());
|
||||
|
||||
// Rückmeldung
|
||||
DynamicJsonDocument doc(64);
|
||||
doc["success"] = true;
|
||||
String result;
|
||||
serializeJson(doc, result);
|
||||
request->send(200, "application/json", result);
|
||||
Serial.println("WiFi-Settings updated (nur bis zum Neustart aktiv!)");
|
||||
} else {
|
||||
request->send(400, "application/json", "{\"success\":false,\"error\":\"SSID fehlt\"}");
|
||||
request->send(400, "application/json", "{\"success\":false,\"error\":\"SSID fehlt\"}");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Liefert aktuelle WLAN-Einstellungen (GET)
|
||||
server.on("/api/get-wifi", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
@@ -211,3 +219,24 @@ void setupRoutes(){
|
||||
Serial.println("Web Server gestartet");
|
||||
|
||||
}
|
||||
|
||||
void setupWebSocket() {
|
||||
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
||||
if (type == WS_EVT_CONNECT) {
|
||||
Serial.printf("WebSocket client connected: %u\n", client->id());
|
||||
} else if (type == WS_EVT_DISCONNECT) {
|
||||
Serial.printf("WebSocket client disconnected: %u\n", client->id());
|
||||
} else if (type == WS_EVT_DATA) {
|
||||
// Handle incoming WebSocket messages if needed
|
||||
Serial.printf("WebSocket message received: %s\n", (char *)data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void pushUpdateToFrontend(const String &message) {
|
||||
ws.textAll(message); // Send the message to all connected clients
|
||||
}
|
||||
|
||||
void loopWebSocket() {
|
||||
ws.cleanupClients(); // Clean up disconnected clients
|
||||
}
|
||||
@@ -13,8 +13,8 @@ String uniqueSSID;
|
||||
const char* ssidAP;
|
||||
const char* passwordAP = nullptr;
|
||||
|
||||
const char* ssidSTA = "Obiwlankenobi";
|
||||
const char* passwordSTA = "Delfine1!";
|
||||
char* ssidSTA = strdup("Obiwlankenobi");
|
||||
char* passwordSTA = strdup("Delfine1!");
|
||||
|
||||
PrettyOTA OTAUpdates;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user