Formatting all c files
This commit is contained in:
@@ -1,54 +1,57 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
|
void handleLearningMode(const uint8_t *mac) {
|
||||||
|
|
||||||
void handleLearningMode(const uint8_t* mac) {
|
|
||||||
// Prüfen ob MAC bereits einem anderen Button zugewiesen ist
|
// Prüfen ob MAC bereits einem anderen Button zugewiesen ist
|
||||||
if (buttonConfigs.start1.isAssigned && memcmp(buttonConfigs.start1.mac, mac, 6) == 0) {
|
if (buttonConfigs.start1.isAssigned &&
|
||||||
|
memcmp(buttonConfigs.start1.mac, mac, 6) == 0) {
|
||||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (buttonConfigs.stop1.isAssigned && memcmp(buttonConfigs.stop1.mac, mac, 6) == 0) {
|
if (buttonConfigs.stop1.isAssigned &&
|
||||||
|
memcmp(buttonConfigs.stop1.mac, mac, 6) == 0) {
|
||||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (buttonConfigs.start2.isAssigned && memcmp(buttonConfigs.start2.mac, mac, 6) == 0) {
|
if (buttonConfigs.start2.isAssigned &&
|
||||||
|
memcmp(buttonConfigs.start2.mac, mac, 6) == 0) {
|
||||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (buttonConfigs.stop2.isAssigned && memcmp(buttonConfigs.stop2.mac, mac, 6) == 0) {
|
if (buttonConfigs.stop2.isAssigned &&
|
||||||
|
memcmp(buttonConfigs.stop2.mac, mac, 6) == 0) {
|
||||||
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
Serial.println("Diese MAC ist bereits zugewiesen - wird ignoriert");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAC ist noch nicht zugewiesen, normal fortfahren
|
// MAC ist noch nicht zugewiesen, normal fortfahren
|
||||||
switch(learningStep) {
|
switch (learningStep) {
|
||||||
case 0: // Start1
|
case 0: // Start1
|
||||||
memcpy(buttonConfigs.start1.mac, mac, 6);
|
memcpy(buttonConfigs.start1.mac, mac, 6);
|
||||||
buttonConfigs.start1.isAssigned = true;
|
buttonConfigs.start1.isAssigned = true;
|
||||||
Serial.println("Start1 Button zugewiesen");
|
Serial.println("Start1 Button zugewiesen");
|
||||||
break;
|
break;
|
||||||
case 1: // Stop1
|
case 1: // Stop1
|
||||||
memcpy(buttonConfigs.stop1.mac, mac, 6);
|
memcpy(buttonConfigs.stop1.mac, mac, 6);
|
||||||
buttonConfigs.stop1.isAssigned = true;
|
buttonConfigs.stop1.isAssigned = true;
|
||||||
Serial.println("Stop1 Button zugewiesen");
|
Serial.println("Stop1 Button zugewiesen");
|
||||||
break;
|
break;
|
||||||
case 2: // Start2
|
case 2: // Start2
|
||||||
memcpy(buttonConfigs.start2.mac, mac, 6);
|
memcpy(buttonConfigs.start2.mac, mac, 6);
|
||||||
buttonConfigs.start2.isAssigned = true;
|
buttonConfigs.start2.isAssigned = true;
|
||||||
Serial.println("Start2 Button zugewiesen");
|
Serial.println("Start2 Button zugewiesen");
|
||||||
break;
|
break;
|
||||||
case 3: // Stop2
|
case 3: // Stop2
|
||||||
memcpy(buttonConfigs.stop2.mac, mac, 6);
|
memcpy(buttonConfigs.stop2.mac, mac, 6);
|
||||||
buttonConfigs.stop2.isAssigned = true;
|
buttonConfigs.stop2.isAssigned = true;
|
||||||
Serial.println("Stop2 Button zugewiesen");
|
Serial.println("Stop2 Button zugewiesen");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
learningStep++;
|
learningStep++;
|
||||||
if (learningStep >= 4) {
|
if (learningStep >= 4) {
|
||||||
learningMode = false;
|
learningMode = false;
|
||||||
@@ -59,41 +62,46 @@ void handleLearningMode(const uint8_t* mac) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleStartLearning() {
|
void handleStartLearning() {
|
||||||
learningMode = true;
|
learningMode = true;
|
||||||
|
|
||||||
// Count assigned buttons and set appropriate learning step
|
// Count assigned buttons and set appropriate learning step
|
||||||
int assignedButtons = 0;
|
int assignedButtons = 0;
|
||||||
if (buttonConfigs.start1.isAssigned) assignedButtons++;
|
if (buttonConfigs.start1.isAssigned)
|
||||||
if (buttonConfigs.stop1.isAssigned) assignedButtons++;
|
assignedButtons++;
|
||||||
if (buttonConfigs.start2.isAssigned) assignedButtons++;
|
if (buttonConfigs.stop1.isAssigned)
|
||||||
if (buttonConfigs.stop2.isAssigned) assignedButtons++;
|
assignedButtons++;
|
||||||
|
if (buttonConfigs.start2.isAssigned)
|
||||||
learningStep = assignedButtons;
|
assignedButtons++;
|
||||||
|
if (buttonConfigs.stop2.isAssigned)
|
||||||
Serial.printf("Learning mode started - %d buttons already assigned, continuing at step %d\n",
|
assignedButtons++;
|
||||||
assignedButtons, learningStep);
|
|
||||||
|
learningStep = assignedButtons;
|
||||||
|
|
||||||
|
Serial.printf("Learning mode started - %d buttons already assigned, "
|
||||||
|
"continuing at step %d\n",
|
||||||
|
assignedButtons, learningStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleLearningStatus() {
|
void handleLearningStatus() {
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
doc["active"] = learningMode;
|
doc["active"] = learningMode;
|
||||||
doc["step"] = learningStep;
|
doc["step"] = learningStep;
|
||||||
|
|
||||||
String response;
|
String response;
|
||||||
serializeJson(doc, response);
|
serializeJson(doc, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlearnButton() {
|
void unlearnButton() {
|
||||||
|
|
||||||
memset(buttonConfigs.start1.mac, 0, 6);
|
memset(buttonConfigs.start1.mac, 0, 6);
|
||||||
buttonConfigs.start1.isAssigned = false;
|
buttonConfigs.start1.isAssigned = false;
|
||||||
memset(buttonConfigs.stop1.mac, 0, 6);
|
memset(buttonConfigs.stop1.mac, 0, 6);
|
||||||
buttonConfigs.stop1.isAssigned = false;
|
buttonConfigs.stop1.isAssigned = false;
|
||||||
memset(buttonConfigs.start2.mac, 0, 6);
|
memset(buttonConfigs.start2.mac, 0, 6);
|
||||||
buttonConfigs.start2.isAssigned = false;
|
buttonConfigs.start2.isAssigned = false;
|
||||||
memset(buttonConfigs.stop2.mac, 0, 6);
|
memset(buttonConfigs.stop2.mac, 0, 6);
|
||||||
buttonConfigs.stop2.isAssigned = false;
|
buttonConfigs.stop2.isAssigned = false;
|
||||||
|
|
||||||
saveButtonConfig();
|
saveButtonConfig();
|
||||||
Serial.println("Buttons wurden verlernt.");
|
Serial.println("Buttons wurden verlernt.");
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
|
||||||
#include <PicoMQTT.h>
|
#include <PicoMQTT.h>
|
||||||
|
|
||||||
|
#include "buttonassigh.h"
|
||||||
|
#include "databasebackend.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "helper.h"
|
||||||
#include "statusled.h"
|
#include "statusled.h"
|
||||||
#include "timesync.h"
|
#include "timesync.h"
|
||||||
#include "buttonassigh.h"
|
|
||||||
#include "helper.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include <map>
|
|
||||||
#include "databasebackend.h"
|
|
||||||
#include "webserverrouter.h"
|
#include "webserverrouter.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
struct TimestampData {
|
struct TimestampData {
|
||||||
uint64_t lastMessageTimestamp; // Timestamp from the device
|
uint64_t lastMessageTimestamp; // Timestamp from the device
|
||||||
uint64_t lastLocalTimestamp; // Our local timestamp when message was received
|
uint64_t lastLocalTimestamp; // Our local timestamp when message was received
|
||||||
uint64_t drift; // Calculated drift
|
uint64_t drift; // Calculated drift
|
||||||
};
|
};
|
||||||
|
|
||||||
// Map to store timestamp data for each MAC address
|
// Map to store timestamp data for each MAC address
|
||||||
std::map<String, TimestampData> deviceTimestamps;
|
std::map<String, TimestampData> deviceTimestamps;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Datenstruktur für ESP-NOW Nachrichten
|
// Datenstruktur für ESP-NOW Nachrichten
|
||||||
// Datenstruktur für ESP-NOW Nachrichten
|
// Datenstruktur für ESP-NOW Nachrichten
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -37,293 +37,292 @@ typedef struct {
|
|||||||
|
|
||||||
PicoMQTT::Server mqtt;
|
PicoMQTT::Server mqtt;
|
||||||
|
|
||||||
void readButtonJSON(const char * topic, const char * payload) {
|
void readButtonJSON(const char *topic, const char *payload) {
|
||||||
|
|
||||||
const char* prefix = "aquacross/button/";
|
const char *prefix = "aquacross/button/";
|
||||||
size_t prefixLen = strlen(prefix);
|
size_t prefixLen = strlen(prefix);
|
||||||
if (strncmp(topic, prefix, prefixLen) != 0) {
|
if (strncmp(topic, prefix, prefixLen) != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAC aus dem Topic extrahieren
|
|
||||||
String buttonId = String(topic + prefixLen);
|
|
||||||
|
|
||||||
// Create a JSON document to parse the incoming message
|
// MAC aus dem Topic extrahieren
|
||||||
JsonDocument doc;
|
String buttonId = String(topic + prefixLen);
|
||||||
DeserializationError error = deserializeJson(doc, payload);
|
|
||||||
|
|
||||||
if (error) {
|
// Create a JSON document to parse the incoming message
|
||||||
Serial.print("JSON parsing failed: ");
|
JsonDocument doc;
|
||||||
Serial.println(error.c_str());
|
DeserializationError error = deserializeJson(doc, payload);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract values from JSON
|
if (error) {
|
||||||
int pressType = doc["type"] | 0;
|
Serial.print("JSON parsing failed: ");
|
||||||
uint64_t timestamp = doc["timestamp"] | 0ULL;
|
Serial.println(error.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Print received data
|
// Extract values from JSON
|
||||||
Serial.printf("Button Press Received:\n");
|
int pressType = doc["type"] | 0;
|
||||||
Serial.printf(" Type: %d\n", pressType);
|
uint64_t timestamp = doc["timestamp"] | 0ULL;
|
||||||
Serial.printf(" Button MAC: %s\n", buttonId.c_str());
|
|
||||||
Serial.printf(" Timestamp: %llu\n", timestamp);
|
|
||||||
|
|
||||||
|
// Print received data
|
||||||
auto macBytes = macStringToBytes(buttonId.c_str());
|
Serial.printf("Button Press Received:\n");
|
||||||
|
Serial.printf(" Type: %d\n", pressType);
|
||||||
|
Serial.printf(" Button MAC: %s\n", buttonId.c_str());
|
||||||
|
Serial.printf(" Timestamp: %llu\n", timestamp);
|
||||||
|
|
||||||
if (learningMode) {
|
auto macBytes = macStringToBytes(buttonId.c_str());
|
||||||
handleLearningMode(macBytes.data());
|
|
||||||
return;
|
if (learningMode) {
|
||||||
}
|
handleLearningMode(macBytes.data());
|
||||||
|
return;
|
||||||
// Button-Zuordnung prüfen und entsprechende Aktion ausführen
|
}
|
||||||
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0 && (pressType == 2)) {
|
|
||||||
handleStart1(timestamp);
|
// Button-Zuordnung prüfen und entsprechende Aktion ausführen
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 && (pressType == 1)) {
|
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0 &&
|
||||||
handleStop1(timestamp);
|
(pressType == 2)) {
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 && (pressType == 2)) {
|
handleStart1(timestamp);
|
||||||
handleStart2(timestamp);
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 &&
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 1)) {
|
(pressType == 1)) {
|
||||||
handleStop2(timestamp);
|
handleStop1(timestamp);
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 &&
|
||||||
|
(pressType == 2)) {
|
||||||
|
handleStart2(timestamp);
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 &&
|
||||||
|
(pressType == 1)) {
|
||||||
|
handleStop2(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flash status LED to indicate received message
|
||||||
|
updateStatusLED(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleHeartbeatTopic(const char *topic, const char *payload) {
|
||||||
|
// Topic-Format: heartbeat/alive/CC:DB:A7:2F:95:08
|
||||||
|
String topicStr(topic);
|
||||||
|
int lastSlash = topicStr.lastIndexOf('/');
|
||||||
|
if (lastSlash < 0)
|
||||||
|
return;
|
||||||
|
String macStr = topicStr.substring(lastSlash + 1);
|
||||||
|
|
||||||
|
auto macBytes = macStringToBytes(macStr.c_str());
|
||||||
|
|
||||||
|
String buttonType = "unknown";
|
||||||
|
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
||||||
|
buttonType = "start1";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0) {
|
||||||
|
buttonType = "stop1";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
||||||
|
buttonType = "start2";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0) {
|
||||||
|
buttonType = "stop2";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse payload for timestamp (optional, falls im Payload enthalten)
|
||||||
|
uint64_t timestamp = millis();
|
||||||
|
StaticJsonDocument<128> payloadDoc;
|
||||||
|
if (payload && strlen(payload) > 0 &&
|
||||||
|
deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
||||||
|
if (payloadDoc.containsKey("timestamp")) {
|
||||||
|
timestamp = payloadDoc["timestamp"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON bauen
|
||||||
|
StaticJsonDocument<128> doc;
|
||||||
|
doc["button"] = buttonType;
|
||||||
|
doc["mac"] = macStr;
|
||||||
|
doc["timestamp"] = timestamp;
|
||||||
|
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
pushUpdateToFrontend(
|
||||||
|
json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
||||||
|
// Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleBatteryTopic(const char *topic, const char *payload) {
|
||||||
|
int batteryLevel = 0;
|
||||||
|
String topicStr(topic);
|
||||||
|
int lastSlash = topicStr.lastIndexOf('/');
|
||||||
|
if (lastSlash < 0)
|
||||||
|
return;
|
||||||
|
String macStr = topicStr.substring(lastSlash + 1);
|
||||||
|
|
||||||
|
auto macBytes = macStringToBytes(macStr.c_str());
|
||||||
|
|
||||||
|
String buttonType = "unknown";
|
||||||
|
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
||||||
|
buttonType = "start1";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0) {
|
||||||
|
buttonType = "stop1";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
||||||
|
buttonType = "start2";
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0) {
|
||||||
|
buttonType = "stop2";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse payload for timestamp (optional, falls im Payload enthalten)
|
||||||
|
StaticJsonDocument<128> payloadDoc;
|
||||||
|
if (payload && strlen(payload) > 0 &&
|
||||||
|
deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
||||||
|
if (payloadDoc.containsKey("voltage")) {
|
||||||
|
batteryLevel = payloadDoc["voltage"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berechne die Prozentzahl des Batteriestands für eine 1S LIPO batteryLevel
|
||||||
|
// sind Volts
|
||||||
|
// Hier wird angenommen, dass 3.7V 100% entspricht und 3.0V 0%
|
||||||
|
batteryLevel =
|
||||||
|
batteryLevel * 1000; // Umwandlung von V in mV für genauere Berechnung
|
||||||
|
if (batteryLevel < 3200) {
|
||||||
|
batteryLevel = 0; // 0% bei 3.0V
|
||||||
|
} else if (batteryLevel > 3700) {
|
||||||
|
batteryLevel = 100; // 100% bei 3.7V
|
||||||
|
} else {
|
||||||
|
batteryLevel = map(batteryLevel, 3000, 3700, 0, 100); // Linear Mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON bauen
|
||||||
|
StaticJsonDocument<128> doc;
|
||||||
|
doc["button"] = buttonType;
|
||||||
|
doc["mac"] = macStr;
|
||||||
|
doc["batteryLevel"] = batteryLevel;
|
||||||
|
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
pushUpdateToFrontend(
|
||||||
|
json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
||||||
|
// Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flash status LED to indicate received message
|
|
||||||
updateStatusLED(3);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleHeartbeatTopic(const char* topic, const char* payload) {
|
|
||||||
// Topic-Format: heartbeat/alive/CC:DB:A7:2F:95:08
|
|
||||||
String topicStr(topic);
|
|
||||||
int lastSlash = topicStr.lastIndexOf('/');
|
|
||||||
if (lastSlash < 0) return;
|
|
||||||
String macStr = topicStr.substring(lastSlash + 1);
|
|
||||||
|
|
||||||
auto macBytes = macStringToBytes(macStr.c_str());
|
|
||||||
|
|
||||||
String buttonType = "unknown";
|
|
||||||
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
|
||||||
buttonType = "start1";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0) {
|
|
||||||
buttonType = "stop1";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
|
||||||
buttonType = "start2";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0) {
|
|
||||||
buttonType = "stop2";
|
|
||||||
}
|
}
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Parse payload for timestamp (optional, falls im Payload enthalten)
|
// Create JSON message to send to the frontend
|
||||||
uint64_t timestamp = millis();
|
StaticJsonDocument<128> messageDoc;
|
||||||
StaticJsonDocument<128> payloadDoc;
|
messageDoc["firstname"] = userData.firstname;
|
||||||
if (payload && strlen(payload) > 0 && deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
messageDoc["lastname"] = userData.lastname;
|
||||||
if (payloadDoc.containsKey("timestamp")) {
|
messageDoc["lane"] = "start2"; // Add lane information
|
||||||
timestamp = payloadDoc["timestamp"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON bauen
|
String message;
|
||||||
StaticJsonDocument<128> doc;
|
serializeJson(messageDoc, message);
|
||||||
doc["button"] = buttonType;
|
|
||||||
doc["mac"] = macStr;
|
|
||||||
doc["timestamp"] = timestamp;
|
|
||||||
|
|
||||||
String json;
|
// Push the message to the frontend
|
||||||
serializeJson(doc, json);
|
pushUpdateToFrontend(message);
|
||||||
pushUpdateToFrontend(json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
Serial.printf("Pushed user data for start2 to frontend: %s\n",
|
||||||
//Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
|
message.c_str());
|
||||||
}
|
} else {
|
||||||
|
Serial.println("User not found for UID: " + String(uid));
|
||||||
void handleBatteryTopic(const char* topic, const char* payload) {
|
}
|
||||||
int batteryLevel = 0;
|
|
||||||
String topicStr(topic);
|
|
||||||
int lastSlash = topicStr.lastIndexOf('/');
|
|
||||||
if (lastSlash < 0) return;
|
|
||||||
String macStr = topicStr.substring(lastSlash + 1);
|
|
||||||
|
|
||||||
auto macBytes = macStringToBytes(macStr.c_str());
|
|
||||||
|
|
||||||
String buttonType = "unknown";
|
|
||||||
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
|
||||||
buttonType = "start1";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0) {
|
|
||||||
buttonType = "stop1";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
|
||||||
buttonType = "start2";
|
|
||||||
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0) {
|
|
||||||
buttonType = "stop2";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse payload for timestamp (optional, falls im Payload enthalten)
|
|
||||||
StaticJsonDocument<128> payloadDoc;
|
|
||||||
if (payload && strlen(payload) > 0 && deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
|
||||||
if (payloadDoc.containsKey("voltage")) {
|
|
||||||
batteryLevel = payloadDoc["voltage"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Berechne die Prozentzahl des Batteriestands für eine 1S LIPO batteryLevel sind Volts
|
|
||||||
// Hier wird angenommen, dass 3.7V 100% entspricht und 3.0V 0%
|
|
||||||
batteryLevel = batteryLevel * 1000; // Umwandlung von V in mV für genauere Berechnung
|
|
||||||
if (batteryLevel < 3200) {
|
|
||||||
batteryLevel = 0; // 0% bei 3.0V
|
|
||||||
} else if (batteryLevel > 3700) {
|
|
||||||
batteryLevel = 100; // 100% bei 3.7V
|
|
||||||
} else {
|
} else {
|
||||||
batteryLevel = map(batteryLevel, 3000, 3700, 0, 100); // Linear Mapping
|
Serial.println("Button MAC does not match start1.mac or start2.mac");
|
||||||
}
|
|
||||||
|
|
||||||
// JSON bauen
|
|
||||||
StaticJsonDocument<128> doc;
|
|
||||||
doc["button"] = buttonType;
|
|
||||||
doc["mac"] = macStr;
|
|
||||||
doc["batteryLevel"] = batteryLevel;
|
|
||||||
|
|
||||||
String json;
|
|
||||||
serializeJson(doc, json);
|
|
||||||
pushUpdateToFrontend(json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
|
||||||
//Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Serial.println("Failed to parse RFID JSON");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupMqttServer() {
|
void setupMqttServer() {
|
||||||
|
|
||||||
// Set up the MQTT server with the desired port
|
// Set up the MQTT server with the desired port
|
||||||
// Subscribe to a topic pattern and attach a callback
|
// Subscribe to a topic pattern and attach a callback
|
||||||
mqtt.subscribe("#", [](const char * topic, const char * payload) {
|
mqtt.subscribe("#", [](const char *topic, const char *payload) {
|
||||||
//Message received callback
|
// Message received callback
|
||||||
//Serial.printf("Received message on topic '%s': %s\n", topic, payload);
|
// Serial.printf("Received message on topic '%s': %s\n", topic, payload);
|
||||||
if (strncmp(topic, "aquacross/button/", 17) == 0) {
|
if (strncmp(topic, "aquacross/button/", 17) == 0) {
|
||||||
readButtonJSON(topic, payload);
|
readButtonJSON(topic, payload);
|
||||||
}
|
} else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) {
|
||||||
else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) {
|
readRFIDfromButton(topic, payload);
|
||||||
readRFIDfromButton(topic, payload);
|
// Handle RFID read messages
|
||||||
// Handle RFID read messages
|
} else if (strncmp(topic, "aquacross/battery/", 17) == 0) {
|
||||||
}
|
handleBatteryTopic(topic, payload);
|
||||||
else if (strncmp(topic, "aquacross/battery/", 17) == 0) {
|
} else if (strncmp(topic, "heartbeat/alive/", 16) == 0) {
|
||||||
handleBatteryTopic(topic, payload);
|
handleHeartbeatTopic(topic, payload);
|
||||||
}
|
}
|
||||||
else if (strncmp(topic, "heartbeat/alive/", 16) == 0) {
|
updateStatusLED(3);
|
||||||
handleHeartbeatTopic(topic, payload);
|
});
|
||||||
}
|
|
||||||
updateStatusLED(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start the MQTT server
|
|
||||||
mqtt.begin();
|
|
||||||
|
|
||||||
Serial.println("MQTT server started on port 1883");
|
// Start the MQTT server
|
||||||
|
mqtt.begin();
|
||||||
|
|
||||||
|
Serial.println("MQTT server started on port 1883");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void loopMqttServer() {
|
void loopMqttServer() {
|
||||||
mqtt.loop();
|
mqtt.loop();
|
||||||
|
|
||||||
static unsigned long lastPublish = 0;
|
static unsigned long lastPublish = 0;
|
||||||
if (millis() - lastPublish > 5000) {
|
if (millis() - lastPublish > 5000) {
|
||||||
// Convert timestamp to string before publishing
|
// Convert timestamp to string before publishing
|
||||||
char timeStr[32];
|
char timeStr[32];
|
||||||
snprintf(timeStr, sizeof(timeStr), "%llu", getCurrentTimestampMs());
|
snprintf(timeStr, sizeof(timeStr), "%llu", getCurrentTimestampMs());
|
||||||
mqtt.publish("sync/time", timeStr);
|
mqtt.publish("sync/time", timeStr);
|
||||||
lastPublish = millis();
|
lastPublish = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMQTTMessage(const char * topic, const char * message) {
|
void sendMQTTMessage(const char *topic, const char *message) {
|
||||||
// Publish a message to the specified topic
|
// Publish a message to the specified topic
|
||||||
mqtt.publish(topic, message);
|
mqtt.publish(topic, message);
|
||||||
Serial.printf("Published message to topic '%s': %s\n", topic, message);
|
Serial.printf("Published message to topic '%s': %s\n", topic, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMQTTJSONMessage(const char * topic, const JsonDocument & doc) {
|
void sendMQTTJSONMessage(const char *topic, const JsonDocument &doc) {
|
||||||
String jsonString;
|
String jsonString;
|
||||||
serializeJson(doc, jsonString);
|
serializeJson(doc, jsonString);
|
||||||
|
|
||||||
// Publish the JSON string to the specified topic
|
// Publish the JSON string to the specified topic
|
||||||
auto publish = mqtt.begin_publish(topic, measureJson(doc));
|
auto publish = mqtt.begin_publish(topic, measureJson(doc));
|
||||||
serializeJson(doc, publish);
|
serializeJson(doc, publish);
|
||||||
publish.send();
|
publish.send();
|
||||||
Serial.printf("Published JSON message to topic '%s': %s\n", topic, jsonString.c_str());
|
Serial.printf("Published JSON message to topic '%s': %s\n", topic,
|
||||||
|
jsonString.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,191 +1,187 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "master.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include "master.h"
|
|
||||||
|
|
||||||
|
|
||||||
const char* BACKEND_SERVER = "http://db.reptilfpv.de:3000";
|
|
||||||
String BACKEND_TOKEN = licence; // Use the licence as the token for authentication
|
|
||||||
|
|
||||||
|
const char *BACKEND_SERVER = "http://db.reptilfpv.de:3000";
|
||||||
|
String BACKEND_TOKEN =
|
||||||
|
licence; // Use the licence as the token for authentication
|
||||||
|
|
||||||
bool backendOnline() {
|
bool backendOnline() {
|
||||||
|
|
||||||
Serial.println(licence);
|
Serial.println(licence);
|
||||||
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
Serial.println("No WiFi connection.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPClient http;
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
http.begin(String(BACKEND_SERVER) + "/api/health");
|
Serial.println("No WiFi connection.");
|
||||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
return false;
|
||||||
|
}
|
||||||
int httpCode = http.GET();
|
|
||||||
bool isOnline = (httpCode == HTTP_CODE_OK);
|
HTTPClient http;
|
||||||
|
http.begin(String(BACKEND_SERVER) + "/api/health");
|
||||||
if (isOnline) {
|
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||||
Serial.println("Database server connection successful");
|
|
||||||
} else {
|
int httpCode = http.GET();
|
||||||
Serial.printf("Database server connection failed, error: %d\n", httpCode);
|
bool isOnline = (httpCode == HTTP_CODE_OK);
|
||||||
}
|
|
||||||
|
if (isOnline) {
|
||||||
http.end();
|
Serial.println("Database server connection successful");
|
||||||
return isOnline;
|
} else {
|
||||||
|
Serial.printf("Database server connection failed, error: %d\n", httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
return isOnline;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UserData {
|
struct UserData {
|
||||||
String uid;
|
String uid;
|
||||||
String firstname;
|
String firstname;
|
||||||
String lastname;
|
String lastname;
|
||||||
int alter;
|
int alter;
|
||||||
bool exists;
|
bool exists;
|
||||||
};
|
};
|
||||||
|
|
||||||
// UserData checkUser(const String& uid) is defined only once to avoid redefinition errors.
|
// UserData checkUser(const String& uid) is defined only once to avoid
|
||||||
UserData checkUser(const String& uid) {
|
// redefinition errors.
|
||||||
|
UserData checkUser(const String &uid) {
|
||||||
|
|
||||||
UserData userData = {"", "", "", 0, false};
|
UserData userData = {"", "", "", 0, false};
|
||||||
|
|
||||||
if (!backendOnline()) {
|
|
||||||
Serial.println("No internet connection, cannot check user.");
|
|
||||||
return userData;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPClient http;
|
if (!backendOnline()) {
|
||||||
http.begin(String(BACKEND_SERVER) + "/api/users/find");
|
Serial.println("No internet connection, cannot check user.");
|
||||||
http.addHeader("Content-Type", "application/json");
|
|
||||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
|
||||||
|
|
||||||
// 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;
|
return userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPClient http;
|
||||||
|
http.begin(String(BACKEND_SERVER) + "/api/users/find");
|
||||||
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Function to enter user data into the database
|
// Function to enter user data into the database
|
||||||
bool enterUserData(const String& uid, const String& firstname, const String& lastname, const String& geburtsdatum, int alter) {
|
bool enterUserData(const String &uid, const String &firstname,
|
||||||
if (!backendOnline()) {
|
const String &lastname, const String &geburtsdatum,
|
||||||
Serial.println("No internet connection, cannot enter user data.");
|
int alter) {
|
||||||
return false;
|
if (!backendOnline()) {
|
||||||
}
|
Serial.println("No internet connection, cannot enter user data.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.begin(String(BACKEND_SERVER) + "/api/users/insert");
|
http.begin(String(BACKEND_SERVER) + "/api/users/insert");
|
||||||
http.addHeader("Content-Type", "application/json");
|
http.addHeader("Content-Type", "application/json");
|
||||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||||
|
|
||||||
// Create JSON payload
|
// Create JSON payload
|
||||||
StaticJsonDocument<256> requestDoc;
|
StaticJsonDocument<256> requestDoc;
|
||||||
requestDoc["uid"] = uid;
|
requestDoc["uid"] = uid;
|
||||||
requestDoc["vorname"] = firstname;
|
requestDoc["vorname"] = firstname;
|
||||||
requestDoc["nachname"] = lastname;
|
requestDoc["nachname"] = lastname;
|
||||||
requestDoc["geburtsdatum"] = geburtsdatum;
|
requestDoc["geburtsdatum"] = geburtsdatum;
|
||||||
requestDoc["alter"] = alter;
|
requestDoc["alter"] = alter;
|
||||||
|
|
||||||
String requestBody;
|
String requestBody;
|
||||||
serializeJson(requestDoc, requestBody);
|
serializeJson(requestDoc, requestBody);
|
||||||
|
|
||||||
int httpCode = http.POST(requestBody);
|
int httpCode = http.POST(requestBody);
|
||||||
|
|
||||||
if (httpCode == HTTP_CODE_CREATED) {
|
if (httpCode == HTTP_CODE_CREATED) {
|
||||||
Serial.println("User data entered successfully.");
|
Serial.println("User data entered successfully.");
|
||||||
http.end();
|
http.end();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("Failed to enter user data, HTTP code: %d\n", httpCode);
|
Serial.printf("Failed to enter user data, HTTP code: %d\n", httpCode);
|
||||||
http.end();
|
http.end();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonDocument getAllLocations() {
|
JsonDocument getAllLocations() {
|
||||||
JsonDocument locations; // Allocate memory for the JSON document
|
JsonDocument locations; // Allocate memory for the JSON document
|
||||||
|
|
||||||
if (!backendOnline()) {
|
if (!backendOnline()) {
|
||||||
Serial.println("No internet connection, cannot fetch locations.");
|
Serial.println("No internet connection, cannot fetch locations.");
|
||||||
return locations; // Return an empty document
|
return locations; // Return an empty document
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPClient http;
|
||||||
|
http.begin(String(BACKEND_SERVER) + "/api/location/");
|
||||||
|
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
||||||
|
|
||||||
|
int httpCode = http.GET();
|
||||||
|
|
||||||
|
if (httpCode == HTTP_CODE_OK) {
|
||||||
|
String payload = http.getString();
|
||||||
|
DeserializationError error = deserializeJson(locations, payload);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
Serial.println("Failed to parse locations JSON.");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to fetch locations, HTTP code: %d\n", httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
HTTPClient http;
|
http.end();
|
||||||
http.begin(String(BACKEND_SERVER) + "/api/location/");
|
return locations; // Return the populated JSON document
|
||||||
http.addHeader("Authorization", String("Bearer ") + BACKEND_TOKEN);
|
|
||||||
|
|
||||||
int httpCode = http.GET();
|
|
||||||
|
|
||||||
if (httpCode == HTTP_CODE_OK) {
|
|
||||||
String payload = http.getString();
|
|
||||||
DeserializationError error = deserializeJson(locations, payload);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
Serial.println("Failed to parse locations JSON.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Serial.printf("Failed to fetch locations, HTTP code: %d\n", httpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
http.end();
|
|
||||||
return locations; // Return the populated JSON document
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Routes from the Frontend into here and then into DB backend.
|
||||||
|
|
||||||
//Routes from the Frontend into here and then into DB backend.
|
void setupBackendRoutes(AsyncWebServer &server) {
|
||||||
|
|
||||||
void setupBackendRoutes(AsyncWebServer& server) {
|
server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
DynamicJsonDocument doc(64);
|
||||||
server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) {
|
doc["status"] = backendOnline() ? "connected" : "disconnected";
|
||||||
|
String response;
|
||||||
DynamicJsonDocument doc(64);
|
serializeJson(doc, response);
|
||||||
doc["status"] = backendOnline() ? "connected" : "disconnected";
|
request->send(200, "application/json", response);
|
||||||
String response;
|
});
|
||||||
serializeJson(doc, response);
|
|
||||||
request->send(200, "application/json", response);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/api/users", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/api/users", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (!backendOnline()) {
|
if (!backendOnline()) {
|
||||||
request->send(503, "application/json", "{\"error\":\"Database not connected\"}");
|
request->send(503, "application/json",
|
||||||
return;
|
"{\"error\":\"Database not connected\"}");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
// Handle user retrieval logic here
|
|
||||||
});
|
|
||||||
//Location routes /api/location/
|
|
||||||
server.on("/api/location/", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
||||||
|
|
||||||
|
// Handle user retrieval logic here
|
||||||
|
});
|
||||||
|
// Location routes /api/location/
|
||||||
|
server.on("/api/location/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
String result;
|
String result;
|
||||||
serializeJson(getAllLocations(), result);
|
serializeJson(getAllLocations(), result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add more routes as needed
|
||||||
|
|
||||||
// Add more routes as needed
|
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/debug.h
42
src/debug.h
@@ -1,49 +1,41 @@
|
|||||||
// Zeit-bezogene Variablen und Includes
|
// Zeit-bezogene Variablen und Includes
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <master.h>
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <time.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <master.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
#include "communication.h"
|
#include "communication.h"
|
||||||
|
|
||||||
|
void setupDebugAPI(AsyncWebServer &server);
|
||||||
|
|
||||||
|
void setupDebugAPI(AsyncWebServer &server) {
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
void setupDebugAPI(AsyncWebServer& server);
|
server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
void setupDebugAPI(AsyncWebServer& server) {
|
|
||||||
|
|
||||||
//DEBUG
|
|
||||||
server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
||||||
handleStart1(0);
|
handleStart1(0);
|
||||||
request->send(200, "text/plain", "handleStart1() called");
|
request->send(200, "text/plain", "handleStart1() called");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/debug/stop1", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/debug/stop1", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStop1(0);
|
handleStop1(0);
|
||||||
request->send(200, "text/plain", "handleStop1() called");
|
request->send(200, "text/plain", "handleStop1() called");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/debug/start2", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/debug/start2", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStart2(0);
|
handleStart2(0);
|
||||||
request->send(200, "text/plain", "handleStart2() called");
|
request->send(200, "text/plain", "handleStart2() called");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/debug/stop2", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/debug/stop2", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStop2(0);
|
handleStop2(0);
|
||||||
request->send(200, "text/plain", "handleStop2() called");
|
request->send(200, "text/plain", "handleStop2() called");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Serial.println("Debug-API initialisiert");
|
||||||
|
|
||||||
Serial.println("Debug-API initialisiert");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEBUG END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//DEBUG END
|
|
||||||
13
src/helper.h
13
src/helper.h
@@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
std::array<uint8_t, 6> macStringToBytes(const char* macStr) {
|
|
||||||
std::array<uint8_t, 6> bytes;
|
std::array<uint8_t, 6> macStringToBytes(const char *macStr) {
|
||||||
sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
std::array<uint8_t, 6> bytes;
|
||||||
&bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]);
|
sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &bytes[0], &bytes[1],
|
||||||
return bytes;
|
&bytes[2], &bytes[3], &bytes[4], &bytes[5]);
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
138
src/licenceing.h
138
src/licenceing.h
@@ -1,102 +1,106 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "mbedtls/md.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <Preferences.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
#include <master.h>
|
#include <master.h>
|
||||||
#include <Preferences.h>
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include "mbedtls/md.h"
|
|
||||||
|
|
||||||
const char* secret = "542ff224606c61fb3024e22f76ef9ac8";
|
|
||||||
|
const char *secret = "542ff224606c61fb3024e22f76ef9ac8";
|
||||||
|
|
||||||
// Preferences für persistente Speicherung
|
// Preferences für persistente Speicherung
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
|
|
||||||
String licence;
|
String licence;
|
||||||
|
|
||||||
//Prototype für Funktionen
|
// Prototype für Funktionen
|
||||||
String getUniqueDeviceID();
|
String getUniqueDeviceID();
|
||||||
String hmacSHA256(const String& key, const String& message);
|
String hmacSHA256(const String &key, const String &message);
|
||||||
bool checkLicense(const String& deviceID, const String& licenseKey);
|
bool checkLicense(const String &deviceID, const String &licenseKey);
|
||||||
void setupLicenceAPI(AsyncWebServer& server);
|
void setupLicenceAPI(AsyncWebServer &server);
|
||||||
void saveLicenceToPrefs();
|
void saveLicenceToPrefs();
|
||||||
void loadLicenceFromPrefs();
|
void loadLicenceFromPrefs();
|
||||||
|
|
||||||
|
|
||||||
String getUniqueDeviceID() {
|
String getUniqueDeviceID() {
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
esp_wifi_get_mac(WIFI_IF_STA, mac); // Use STA MAC for uniqueness
|
esp_wifi_get_mac(WIFI_IF_STA, mac); // Use STA MAC for uniqueness
|
||||||
char id[13];
|
char id[13];
|
||||||
sprintf(id, "%02X%02X%02X%02X%02X%02X",
|
sprintf(id, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3],
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[4], mac[5]);
|
||||||
return String(id);
|
return String(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
String hmacSHA256(const String& key, const String& message) {
|
String hmacSHA256(const String &key, const String &message) {
|
||||||
byte hmacResult[32];
|
byte hmacResult[32];
|
||||||
mbedtls_md_context_t ctx;
|
mbedtls_md_context_t ctx;
|
||||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||||
|
|
||||||
mbedtls_md_init(&ctx);
|
mbedtls_md_init(&ctx);
|
||||||
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
||||||
mbedtls_md_setup(&ctx, md_info, 1);
|
mbedtls_md_setup(&ctx, md_info, 1);
|
||||||
mbedtls_md_hmac_starts(&ctx, (const unsigned char*)key.c_str(), key.length());
|
mbedtls_md_hmac_starts(&ctx, (const unsigned char *)key.c_str(),
|
||||||
mbedtls_md_hmac_update(&ctx, (const unsigned char*)message.c_str(), message.length());
|
key.length());
|
||||||
mbedtls_md_hmac_finish(&ctx, hmacResult);
|
mbedtls_md_hmac_update(&ctx, (const unsigned char *)message.c_str(),
|
||||||
mbedtls_md_free(&ctx);
|
message.length());
|
||||||
|
mbedtls_md_hmac_finish(&ctx, hmacResult);
|
||||||
|
mbedtls_md_free(&ctx);
|
||||||
|
|
||||||
String result = "";
|
String result = "";
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
char buf[3];
|
char buf[3];
|
||||||
sprintf(buf, "%02X", hmacResult[i]);
|
sprintf(buf, "%02X", hmacResult[i]);
|
||||||
result += buf;
|
result += buf;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLicenseTier(const String &deviceID, const String &licenseKey) {
|
||||||
|
for (int tier = 1; tier <= 4; ++tier) {
|
||||||
|
String data = deviceID + ":" + String(tier);
|
||||||
|
String expected = hmacSHA256(secret, data);
|
||||||
|
if (licenseKey.equalsIgnoreCase(expected)) {
|
||||||
|
return tier; // Found matching tier
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return 0; // No valid tier found
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLicenseTier(const String& deviceID, const String& licenseKey) {
|
void setupLicenceAPI(AsyncWebServer &server) {
|
||||||
for (int tier = 1; tier <= 4; ++tier) {
|
|
||||||
String data = deviceID + ":" + String(tier);
|
|
||||||
String expected = hmacSHA256(secret, data);
|
|
||||||
if (licenseKey.equalsIgnoreCase(expected)) {
|
|
||||||
return tier; // Found matching tier
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0; // No valid tier found
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupLicenceAPI(AsyncWebServer& server) {
|
server.on("/api/get-licence", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
Serial.println("Received request to get licence");
|
||||||
server.on("/api/get-licence", HTTP_GET, [](AsyncWebServerRequest *request){
|
loadLicenceFromPrefs();
|
||||||
Serial.println("Received request to get licence");
|
String deviceID = getUniqueDeviceID();
|
||||||
loadLicenceFromPrefs();
|
int tier = getLicenseTier(deviceID, licence);
|
||||||
String deviceID = getUniqueDeviceID();
|
String json = "{\"licence\":\"" + licence +
|
||||||
int tier = getLicenseTier(deviceID, licence);
|
"\","
|
||||||
String json = "{\"licence\":\"" + licence + "\","
|
"\"valid\":" +
|
||||||
"\"valid\":" + String(tier > 0 ? "true" : "false") +
|
String(tier > 0 ? "true" : "false") +
|
||||||
",\"tier\":" + String(tier) + "}";
|
",\"tier\":" + String(tier) + "}";
|
||||||
request->send(200, "application/json", json);
|
request->send(200, "application/json", json);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/set-licence", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/set-licence", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
Serial.println("Received request to set licence");
|
Serial.println("Received request to set licence");
|
||||||
if (request->hasParam("licence", true)) {
|
if (request->hasParam("licence", true)) {
|
||||||
licence = request->getParam("licence", true)->value();
|
licence = request->getParam("licence", true)->value();
|
||||||
Serial.println("Received request to set licence " + licence);
|
Serial.println("Received request to set licence " + licence);
|
||||||
saveLicenceToPrefs(); // eigene Funktion
|
saveLicenceToPrefs(); // eigene Funktion
|
||||||
request->send(200, "application/json", "{\"success\":true}");
|
request->send(200, "application/json", "{\"success\":true}");
|
||||||
} else {
|
} else {
|
||||||
request->send(400, "application/json", "{\"success\":false}");
|
request->send(400, "application/json", "{\"success\":false}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Serial.println("Licence API setup complete");
|
Serial.println("Licence API setup complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveLicenceToPrefs() {
|
void saveLicenceToPrefs() {
|
||||||
preferences.begin("key", false);
|
preferences.begin("key", false);
|
||||||
preferences.putString("key", licence);
|
preferences.putString("key", licence);
|
||||||
preferences.end();
|
preferences.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLicenceFromPrefs() {
|
void loadLicenceFromPrefs() {
|
||||||
|
|||||||
129
src/master.cpp
129
src/master.cpp
@@ -1,28 +1,30 @@
|
|||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <SPIFFS.h>
|
|
||||||
#include <esp_now.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <AsyncTCP.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <PrettyOTA.h>
|
#include <PrettyOTA.h>
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#include <esp_now.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
#include <AsyncTCP.h>
|
|
||||||
|
|
||||||
#include <timesync.h>
|
|
||||||
#include <licenceing.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <wificlass.h>
|
|
||||||
#include <webserverrouter.h>
|
|
||||||
#include <communication.h>
|
#include <communication.h>
|
||||||
#include <databasebackend.h>
|
#include <databasebackend.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <licenceing.h>
|
||||||
#include <rfid.h>
|
#include <rfid.h>
|
||||||
|
#include <timesync.h>
|
||||||
|
#include <webserverrouter.h>
|
||||||
|
#include <wificlass.h>
|
||||||
|
|
||||||
const char* firmwareversion = "1.0.0"; // Version der Firmware
|
|
||||||
|
|
||||||
|
const char *firmwareversion = "1.0.0"; // Version der Firmware
|
||||||
|
|
||||||
void handleStart1(uint64_t timestamp = 0) {
|
void handleStart1(uint64_t timestamp = 0) {
|
||||||
if (!timerData.isRunning1 && timerData.isReady1) {
|
if (!timerData.isRunning1 && timerData.isReady1) {
|
||||||
@@ -46,7 +48,8 @@ void handleStop1(uint64_t timestamp = 0) {
|
|||||||
timerData.bestTime1 = currentTime;
|
timerData.bestTime1 = currentTime;
|
||||||
saveBestTimes();
|
saveBestTimes();
|
||||||
}
|
}
|
||||||
Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime/1000.0) + "s");
|
Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime / 1000.0) +
|
||||||
|
"s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,66 +75,70 @@ void handleStop2(uint64_t timestamp = 0) {
|
|||||||
timerData.bestTime2 = currentTime;
|
timerData.bestTime2 = currentTime;
|
||||||
saveBestTimes();
|
saveBestTimes();
|
||||||
}
|
}
|
||||||
Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime/1000.0) + "s");
|
Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime / 1000.0) +
|
||||||
|
"s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAutoReset() {
|
void checkAutoReset() {
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
if (timerData.isRunning1 && (currentTime - timerData.localStartTime1 > maxTimeBeforeReset)) {
|
if (timerData.isRunning1 &&
|
||||||
|
(currentTime - timerData.localStartTime1 > maxTimeBeforeReset)) {
|
||||||
timerData.isRunning1 = false;
|
timerData.isRunning1 = false;
|
||||||
timerData.startTime1 = 0;
|
timerData.startTime1 = 0;
|
||||||
Serial.println("Bahn 1 automatisch zurückgesetzt");
|
Serial.println("Bahn 1 automatisch zurückgesetzt");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timerData.isRunning2 && (currentTime - timerData.localStartTime2 > maxTimeBeforeReset)) {
|
if (timerData.isRunning2 &&
|
||||||
|
(currentTime - timerData.localStartTime2 > maxTimeBeforeReset)) {
|
||||||
timerData.isRunning2 = false;
|
timerData.isRunning2 = false;
|
||||||
timerData.startTime2 = 0;
|
timerData.startTime2 = 0;
|
||||||
Serial.println("Bahn 2 automatisch zurückgesetzt");
|
Serial.println("Bahn 2 automatisch zurückgesetzt");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatischer Reset nach 10 Sekunden "Beendet"
|
// Automatischer Reset nach 10 Sekunden "Beendet"
|
||||||
if (!timerData.isRunning1 && timerData.endTime1 > 0 && timerData.finishedSince1 > 0) {
|
if (!timerData.isRunning1 && timerData.endTime1 > 0 &&
|
||||||
|
timerData.finishedSince1 > 0) {
|
||||||
if (millis() - timerData.finishedSince1 > maxTimeDisplay) {
|
if (millis() - timerData.finishedSince1 > maxTimeDisplay) {
|
||||||
timerData.startTime1 = 0;
|
timerData.startTime1 = 0;
|
||||||
timerData.endTime1 = 0;
|
timerData.endTime1 = 0;
|
||||||
timerData.finishedSince1 = 0;
|
timerData.finishedSince1 = 0;
|
||||||
timerData.isReady1 = true; // Zurücksetzen auf "Bereit"
|
timerData.isReady1 = true; // Zurücksetzen auf "Bereit"
|
||||||
|
|
||||||
JsonDocument messageDoc;
|
|
||||||
messageDoc["firstname"] ="";
|
|
||||||
messageDoc["lastname"] = "";
|
|
||||||
messageDoc["lane"] = "start1"; // Add lane information
|
|
||||||
|
|
||||||
String message;
|
JsonDocument messageDoc;
|
||||||
serializeJson(messageDoc, message);
|
messageDoc["firstname"] = "";
|
||||||
|
messageDoc["lastname"] = "";
|
||||||
|
messageDoc["lane"] = "start1"; // Add lane information
|
||||||
|
|
||||||
// Push the message to the frontend
|
String message;
|
||||||
pushUpdateToFrontend(message);
|
serializeJson(messageDoc, message);
|
||||||
|
|
||||||
|
// Push the message to the frontend
|
||||||
|
pushUpdateToFrontend(message);
|
||||||
|
|
||||||
Serial.println("Bahn 1 automatisch auf 'Bereit' zurückgesetzt");
|
Serial.println("Bahn 1 automatisch auf 'Bereit' zurückgesetzt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!timerData.isRunning2 && timerData.endTime2 > 0 && timerData.finishedSince2 > 0) {
|
if (!timerData.isRunning2 && timerData.endTime2 > 0 &&
|
||||||
|
timerData.finishedSince2 > 0) {
|
||||||
if (currentTime - timerData.finishedSince2 > maxTimeDisplay) {
|
if (currentTime - timerData.finishedSince2 > maxTimeDisplay) {
|
||||||
timerData.startTime2 = 0;
|
timerData.startTime2 = 0;
|
||||||
timerData.endTime2 = 0;
|
timerData.endTime2 = 0;
|
||||||
timerData.finishedSince2 = 0;
|
timerData.finishedSince2 = 0;
|
||||||
timerData.isReady2 = true; // Zurücksetzen auf "Bereit"
|
timerData.isReady2 = true; // Zurücksetzen auf "Bereit"
|
||||||
|
|
||||||
JsonDocument messageDoc;
|
|
||||||
messageDoc["firstname"] = "";
|
|
||||||
messageDoc["lastname"] = "";
|
|
||||||
messageDoc["lane"] = "start2"; // Add lane information
|
|
||||||
|
|
||||||
String message;
|
JsonDocument messageDoc;
|
||||||
serializeJson(messageDoc, message);
|
messageDoc["firstname"] = "";
|
||||||
|
messageDoc["lastname"] = "";
|
||||||
|
messageDoc["lane"] = "start2"; // Add lane information
|
||||||
|
|
||||||
// Push the message to the frontend
|
String message;
|
||||||
pushUpdateToFrontend(message);
|
serializeJson(messageDoc, message);
|
||||||
|
|
||||||
|
// Push the message to the frontend
|
||||||
|
pushUpdateToFrontend(message);
|
||||||
|
|
||||||
Serial.println("Bahn 2 automatisch auf 'Bereit' zurückgesetzt");
|
Serial.println("Bahn 2 automatisch auf 'Bereit' zurückgesetzt");
|
||||||
}
|
}
|
||||||
@@ -186,14 +193,14 @@ void saveWifiSettings() {
|
|||||||
preferences.putString("ssid", ssidSTA);
|
preferences.putString("ssid", ssidSTA);
|
||||||
preferences.putString("password", passwordSTA);
|
preferences.putString("password", passwordSTA);
|
||||||
preferences.end();
|
preferences.end();
|
||||||
delay(500); // Warte 2 Sekunden, bevor der Neustart erfolgt
|
delay(500); // Warte 2 Sekunden, bevor der Neustart erfolgt
|
||||||
ESP.restart(); // Neustart des ESP32
|
ESP.restart(); // Neustart des ESP32
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLocationSettings() {
|
void loadLocationSettings() {
|
||||||
preferences.begin("location", true);
|
preferences.begin("location", true);
|
||||||
masterlocation = preferences.getString("location", "");
|
masterlocation = preferences.getString("location", "");
|
||||||
preferences.end();
|
preferences.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveLocationSettings() {
|
void saveLocationSettings() {
|
||||||
@@ -203,18 +210,14 @@ void saveLocationSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadWifiSettings() {
|
void loadWifiSettings() {
|
||||||
preferences.begin("wifi", true);
|
preferences.begin("wifi", true);
|
||||||
String ssid = preferences.getString("ssid", "");
|
String ssid = preferences.getString("ssid", "");
|
||||||
String password = preferences.getString("password", "");
|
String password = preferences.getString("password", "");
|
||||||
ssidSTA = strdup(ssid.c_str());
|
ssidSTA = strdup(ssid.c_str());
|
||||||
passwordSTA = strdup(password.c_str());
|
passwordSTA = strdup(password.c_str());
|
||||||
preferences.end();
|
preferences.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int checkLicence() {
|
int checkLicence() {
|
||||||
loadLicenceFromPrefs();
|
loadLicenceFromPrefs();
|
||||||
String id = getUniqueDeviceID();
|
String id = getUniqueDeviceID();
|
||||||
@@ -224,7 +227,7 @@ int checkLicence() {
|
|||||||
|
|
||||||
String getTimerDataJSON() {
|
String getTimerDataJSON() {
|
||||||
DynamicJsonDocument doc(1024);
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
// Bahn 1
|
// Bahn 1
|
||||||
if (timerData.isRunning1) {
|
if (timerData.isRunning1) {
|
||||||
@@ -237,7 +240,7 @@ String getTimerDataJSON() {
|
|||||||
doc["time1"] = 0;
|
doc["time1"] = 0;
|
||||||
doc["status1"] = "ready";
|
doc["status1"] = "ready";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bahn 2
|
// Bahn 2
|
||||||
if (timerData.isRunning2) {
|
if (timerData.isRunning2) {
|
||||||
doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0;
|
doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0;
|
||||||
@@ -249,40 +252,38 @@ String getTimerDataJSON() {
|
|||||||
doc["time2"] = 0;
|
doc["time2"] = 0;
|
||||||
doc["status2"] = "ready";
|
doc["status2"] = "ready";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beste Zeiten
|
// Beste Zeiten
|
||||||
doc["best1"] = timerData.bestTime1 / 1000.0;
|
doc["best1"] = timerData.bestTime1 / 1000.0;
|
||||||
doc["best2"] = timerData.bestTime2 / 1000.0;
|
doc["best2"] = timerData.bestTime2 / 1000.0;
|
||||||
|
|
||||||
// Lernmodus
|
// Lernmodus
|
||||||
doc["learningMode"] = learningMode;
|
doc["learningMode"] = learningMode;
|
||||||
if (learningMode) {
|
if (learningMode) {
|
||||||
String buttons[] = {"Start Bahn 1", "Stop Bahn 1", "Start Bahn 2", "Stop Bahn 2"};
|
String buttons[] = {"Start Bahn 1", "Stop Bahn 1", "Start Bahn 2",
|
||||||
|
"Stop Bahn 2"};
|
||||||
doc["learningButton"] = buttons[learningStep];
|
doc["learningButton"] = buttons[learningStep];
|
||||||
}
|
}
|
||||||
|
|
||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
|
||||||
if (!SPIFFS.begin(true)) {
|
if (!SPIFFS.begin(true)) {
|
||||||
Serial.println("SPIFFS Mount Failed");
|
Serial.println("SPIFFS Mount Failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup API libararies
|
// setup API libararies
|
||||||
setupTimeAPI(server);
|
setupTimeAPI(server);
|
||||||
setupLicenceAPI(server);
|
setupLicenceAPI(server);
|
||||||
setupDebugAPI(server);
|
setupDebugAPI(server);
|
||||||
setupBackendRoutes(server);
|
setupBackendRoutes(server);
|
||||||
setupRFIDRoute(server);
|
setupRFIDRoute(server);
|
||||||
|
|
||||||
|
|
||||||
// Gespeicherte Daten laden
|
// Gespeicherte Daten laden
|
||||||
loadButtonConfig();
|
loadButtonConfig();
|
||||||
@@ -293,14 +294,12 @@ void setup() {
|
|||||||
|
|
||||||
setupWifi(); // WiFi initialisieren
|
setupWifi(); // WiFi initialisieren
|
||||||
setupOTA(&server);
|
setupOTA(&server);
|
||||||
|
|
||||||
setupRoutes();
|
setupRoutes();
|
||||||
setupWebSocket();
|
setupWebSocket();
|
||||||
setupLED();
|
setupLED();
|
||||||
setupMqttServer(); // MQTT Server initialisieren
|
setupMqttServer(); // MQTT Server initialisieren
|
||||||
setupRFID();
|
setupRFID();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
25
src/master.h
25
src/master.h
@@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <time.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
const char* ssidAP;
|
|
||||||
const char* passwordAP = nullptr;
|
|
||||||
|
|
||||||
char* ssidSTA = nullptr;
|
const char *ssidAP;
|
||||||
char* passwordSTA = nullptr;
|
const char *passwordAP = nullptr;
|
||||||
|
|
||||||
|
char *ssidSTA = nullptr;
|
||||||
|
char *passwordSTA = nullptr;
|
||||||
|
|
||||||
// Timer Struktur
|
// Timer Struktur
|
||||||
struct TimerData {
|
struct TimerData {
|
||||||
@@ -42,7 +43,7 @@ struct ButtonConfigs {
|
|||||||
ButtonConfig stop2;
|
ButtonConfig stop2;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* firmwareversion;
|
extern const char *firmwareversion;
|
||||||
|
|
||||||
// Globale Variablen
|
// Globale Variablen
|
||||||
TimerData timerData;
|
TimerData timerData;
|
||||||
@@ -50,13 +51,13 @@ ButtonConfigs buttonConfigs;
|
|||||||
bool learningMode = false;
|
bool learningMode = false;
|
||||||
int learningStep = 0; // 0=Start1, 1=Stop1, 2=Start2, 3=Stop2
|
int learningStep = 0; // 0=Start1, 1=Stop1, 2=Start2, 3=Stop2
|
||||||
unsigned long maxTimeBeforeReset = 300000; // 5 Minuten default
|
unsigned long maxTimeBeforeReset = 300000; // 5 Minuten default
|
||||||
unsigned long maxTimeDisplay = 20000; // 20 Sekunden Standard (in ms)
|
unsigned long maxTimeDisplay = 20000; // 20 Sekunden Standard (in ms)
|
||||||
bool wifimodeAP = false; // AP-Modus deaktiviert
|
bool wifimodeAP = false; // AP-Modus deaktiviert
|
||||||
String masterlocation;
|
String masterlocation;
|
||||||
|
|
||||||
//Function Declarations
|
// Function Declarations
|
||||||
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len);
|
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len);
|
||||||
void handleLearningMode(const uint8_t* mac);
|
void handleLearningMode(const uint8_t *mac);
|
||||||
void handleStartLearning();
|
void handleStartLearning();
|
||||||
void handleStart1(uint64_t timestamp);
|
void handleStart1(uint64_t timestamp);
|
||||||
void handleStop1(uint64_t timestamp);
|
void handleStop1(uint64_t timestamp);
|
||||||
|
|||||||
187
src/rfid.h
187
src/rfid.h
@@ -1,16 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <SPI.h>
|
|
||||||
#include <MFRC522.h>
|
#include <MFRC522.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
|
||||||
// RFID Konfiguration
|
// RFID Konfiguration
|
||||||
#define RST_PIN 21 // Configurable, see typical pin layout above
|
#define RST_PIN 21 // Configurable, see typical pin layout above
|
||||||
#define SS_PIN 5 // Configurable, see typical pin layout above
|
#define SS_PIN 5 // Configurable, see typical pin layout above
|
||||||
|
|
||||||
|
|
||||||
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
|
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
|
||||||
std::map<String, unsigned long> blockedUIDs; // Map to store blocked UIDs and their timestamps
|
std::map<String, unsigned long>
|
||||||
|
blockedUIDs; // Map to store blocked UIDs and their timestamps
|
||||||
const unsigned long BLOCK_DURATION = 10 * 1000; // 10 Seconds in milliseconds
|
const unsigned long BLOCK_DURATION = 10 * 1000; // 10 Seconds in milliseconds
|
||||||
|
|
||||||
// Neue Variablen für API-basiertes Lesen
|
// Neue Variablen für API-basiertes Lesen
|
||||||
@@ -18,20 +19,19 @@ bool rfidReadRequested = false;
|
|||||||
String lastReadUID = "";
|
String lastReadUID = "";
|
||||||
bool rfidReadSuccess = false;
|
bool rfidReadSuccess = false;
|
||||||
unsigned long rfidReadStartTime = 0;
|
unsigned long rfidReadStartTime = 0;
|
||||||
const unsigned long RFID_READ_TIMEOUT = 10000; // 10 Sekunden Timeout für API Requests
|
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(); // Init SPI bus
|
SPI.begin(); // Init SPI bus
|
||||||
mfrc522.PCD_Init(); // Init MFRC522
|
mfrc522.PCD_Init(); // Init MFRC522
|
||||||
delay(4); // Optional delay. Some boards need more time after init to be ready
|
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
|
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card
|
||||||
|
// Reader details
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void handleAutomaticRFID() {
|
void handleAutomaticRFID() {
|
||||||
if (!mfrc522.PICC_IsNewCardPresent()) {
|
if (!mfrc522.PICC_IsNewCardPresent()) {
|
||||||
return;
|
return;
|
||||||
@@ -73,7 +73,7 @@ void handleAutomaticRFID() {
|
|||||||
|
|
||||||
// Block the UID for 10 seconds
|
// Block the UID for 10 seconds
|
||||||
blockedUIDs[uid] = currentTime;
|
blockedUIDs[uid] = currentTime;
|
||||||
//show the remaining time for the block
|
// show the remaining time for the block
|
||||||
Serial.print(F("UID blocked for 10 seconds. Remaining time: "));
|
Serial.print(F("UID blocked for 10 seconds. Remaining time: "));
|
||||||
Serial.print((BLOCK_DURATION - (currentTime - blockedUIDs[uid])) / 1000);
|
Serial.print((BLOCK_DURATION - (currentTime - blockedUIDs[uid])) / 1000);
|
||||||
Serial.println(F(" seconds."));
|
Serial.println(F(" seconds."));
|
||||||
@@ -85,7 +85,7 @@ void handleAutomaticRFID() {
|
|||||||
// Neue Funktion für API-basiertes RFID Lesen
|
// Neue Funktion für API-basiertes RFID Lesen
|
||||||
void handleAPIRFIDRead() {
|
void handleAPIRFIDRead() {
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
// Timeout prüfen
|
// Timeout prüfen
|
||||||
if (currentTime - rfidReadStartTime > RFID_READ_TIMEOUT) {
|
if (currentTime - rfidReadStartTime > RFID_READ_TIMEOUT) {
|
||||||
Serial.println("RFID API Timeout - keine Karte erkannt");
|
Serial.println("RFID API Timeout - keine Karte erkannt");
|
||||||
@@ -94,17 +94,17 @@ void handleAPIRFIDRead() {
|
|||||||
lastReadUID = "";
|
lastReadUID = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prüfen ob neue Karte vorhanden ist
|
// 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 für API lesen (ohne Doppelpunkt-Trenner, Großbuchstaben)
|
// 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++) {
|
||||||
@@ -113,17 +113,17 @@ void handleAPIRFIDRead() {
|
|||||||
}
|
}
|
||||||
uid += String(mfrc522.uid.uidByte[i], HEX);
|
uid += String(mfrc522.uid.uidByte[i], HEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID in Großbuchstaben konvertieren
|
// UID in Großbuchstaben konvertieren
|
||||||
uid.toUpperCase();
|
uid.toUpperCase();
|
||||||
|
|
||||||
Serial.println("RFID API UID gelesen: " + uid);
|
Serial.println("RFID API UID gelesen: " + uid);
|
||||||
|
|
||||||
// Ergebnis speichern
|
// Ergebnis speichern
|
||||||
lastReadUID = uid;
|
lastReadUID = uid;
|
||||||
rfidReadSuccess = true;
|
rfidReadSuccess = true;
|
||||||
rfidReadRequested = false;
|
rfidReadRequested = false;
|
||||||
|
|
||||||
// Karte "halt" setzen
|
// Karte "halt" setzen
|
||||||
mfrc522.PICC_HaltA();
|
mfrc522.PICC_HaltA();
|
||||||
mfrc522.PCD_StopCrypto1();
|
mfrc522.PCD_StopCrypto1();
|
||||||
@@ -139,76 +139,79 @@ void startRFIDRead() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API Funktion: Prüfen ob Lesevorgang abgeschlossen
|
// API Funktion: Prüfen ob Lesevorgang abgeschlossen
|
||||||
bool isRFIDReadComplete() {
|
bool isRFIDReadComplete() { return !rfidReadRequested; }
|
||||||
return !rfidReadRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API Funktion: Ergebnis des Lesevorgangs abrufen
|
// API Funktion: Ergebnis des Lesevorgangs abrufen
|
||||||
String getRFIDReadResult(bool& success) {
|
String getRFIDReadResult(bool &success) {
|
||||||
success = rfidReadSuccess;
|
success = rfidReadSuccess;
|
||||||
return lastReadUID;
|
return lastReadUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupRFIDRoute(AsyncWebServer& server) {
|
void setupRFIDRoute(AsyncWebServer &server) {
|
||||||
server.on("/api/rfid/read", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/api/rfid/read", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
Serial.println("api/rfid/read");
|
Serial.println("api/rfid/read");
|
||||||
|
|
||||||
// Start RFID-Lesevorgang
|
// Start RFID-Lesevorgang
|
||||||
startRFIDRead();
|
startRFIDRead();
|
||||||
unsigned long startTime = millis();
|
unsigned long startTime = millis();
|
||||||
|
|
||||||
// Warten, bis eine UID gelesen wird oder Timeout eintritt
|
// Warten, bis eine UID gelesen wird oder Timeout eintritt
|
||||||
while (!isRFIDReadComplete()) {
|
while (!isRFIDReadComplete()) {
|
||||||
if (millis() - startTime > RFID_READ_TIMEOUT) {
|
if (millis() - startTime > RFID_READ_TIMEOUT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delay(10); // Kurze Pause, um die CPU nicht zu blockieren
|
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);
|
DynamicJsonDocument response(200);
|
||||||
|
|
||||||
if (error) {
|
if (rfidReadSuccess && lastReadUID.length() > 0) {
|
||||||
Serial.println("Fehler beim Parsen der JSON-Daten");
|
response["success"] = true;
|
||||||
response["success"] = false;
|
response["uid"] = lastReadUID;
|
||||||
response["error"] = "Ungültige JSON-Daten";
|
response["message"] = "UID erfolgreich gelesen";
|
||||||
} else {
|
} else {
|
||||||
// Extract user data from the JSON payload
|
response["success"] = false;
|
||||||
String uid = doc["uid"] | "";
|
response["error"] = "Keine RFID Karte erkannt oder Timeout";
|
||||||
String vorname = doc["vorname"] | "";
|
response["uid"] = "";
|
||||||
String nachname = doc["nachname"] | "";
|
}
|
||||||
String geburtsdatum = doc["geburtsdatum"] | "";
|
|
||||||
int alter = doc["alter"] | 0;
|
|
||||||
|
|
||||||
// Validate the data
|
String jsonString;
|
||||||
if (uid.isEmpty() || vorname.isEmpty() || nachname.isEmpty() || geburtsdatum.isEmpty() || alter <= 0) {
|
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"] | "";
|
||||||
|
String geburtsdatum = doc["geburtsdatum"] | "";
|
||||||
|
int alter = doc["alter"] | 0;
|
||||||
|
|
||||||
|
// Validate the data
|
||||||
|
if (uid.isEmpty() || vorname.isEmpty() || nachname.isEmpty() ||
|
||||||
|
geburtsdatum.isEmpty() || alter <= 0) {
|
||||||
Serial.println("Ungültige Eingabedaten");
|
Serial.println("Ungültige Eingabedaten");
|
||||||
response["success"] = false;
|
response["success"] = false;
|
||||||
response["error"] = "Ungültige Eingabedaten";
|
response["error"] = "Ungültige Eingabedaten";
|
||||||
} else {
|
} else {
|
||||||
// Process the data using the enterUserData function
|
// Process the data using the enterUserData function
|
||||||
Serial.println("Benutzerdaten empfangen:");
|
Serial.println("Benutzerdaten empfangen:");
|
||||||
Serial.println("UID: " + uid);
|
Serial.println("UID: " + uid);
|
||||||
@@ -216,37 +219,37 @@ server.on("/api/users/insert", HTTP_POST, [](AsyncWebServerRequest *request) {},
|
|||||||
Serial.println("Nachname: " + nachname);
|
Serial.println("Nachname: " + nachname);
|
||||||
Serial.println("Alter: " + String(alter));
|
Serial.println("Alter: " + String(alter));
|
||||||
|
|
||||||
bool dbSuccess = enterUserData(uid, vorname, nachname, geburtsdatum, alter);
|
bool dbSuccess =
|
||||||
|
enterUserData(uid, vorname, nachname, geburtsdatum, alter);
|
||||||
|
|
||||||
if (dbSuccess) {
|
if (dbSuccess) {
|
||||||
response["success"] = true;
|
response["success"] = true;
|
||||||
response["message"] = "Benutzer erfolgreich gespeichert";
|
response["message"] = "Benutzer erfolgreich gespeichert";
|
||||||
} else {
|
} else {
|
||||||
response["success"] = false;
|
response["success"] = false;
|
||||||
response["error"] = "Fehler beim Speichern in der Datenbank";
|
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// 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
|
// API Funktion: RFID Reader Status prüfen
|
||||||
bool checkRFIDReaderStatus() {
|
bool checkRFIDReaderStatus() {
|
||||||
byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
|
byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
|
||||||
|
|
||||||
// Bekannte MFRC522 Versionen: 0x91, 0x92
|
// Bekannte MFRC522 Versionen: 0x91, 0x92
|
||||||
if (version == 0x91 || version == 0x92) {
|
if (version == 0x91 || version == 0x92) {
|
||||||
Serial.println("RFID Reader OK (Version: 0x" + String(version, HEX) + ")");
|
Serial.println("RFID Reader OK (Version: 0x" + String(version, HEX) + ")");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Serial.println("RFID Reader Fehler (Version: 0x" + String(version, HEX) + ")");
|
Serial.println("RFID Reader Fehler (Version: 0x" + String(version, HEX) +
|
||||||
|
")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,7 +257,7 @@ bool checkRFIDReaderStatus() {
|
|||||||
// Hilfsfunktion: Blockierte UIDs aufräumen
|
// Hilfsfunktion: Blockierte UIDs aufräumen
|
||||||
void cleanupBlockedUIDs() {
|
void cleanupBlockedUIDs() {
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
// Iterator für sicheres Löschen während der Iteration
|
// Iterator für sicheres Löschen während der Iteration
|
||||||
for (auto it = blockedUIDs.begin(); it != blockedUIDs.end();) {
|
for (auto it = blockedUIDs.begin(); it != blockedUIDs.end();) {
|
||||||
if (currentTime - it->second >= BLOCK_DURATION) {
|
if (currentTime - it->second >= BLOCK_DURATION) {
|
||||||
@@ -265,16 +268,14 @@ void cleanupBlockedUIDs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loopRFID(){
|
void loopRFID() {
|
||||||
// Originale Funktionalität für automatisches Lesen
|
// Originale Funktionalität für automatisches Lesen
|
||||||
if (!rfidReadRequested) {
|
if (!rfidReadRequested) {
|
||||||
handleAutomaticRFID();
|
handleAutomaticRFID();
|
||||||
}
|
}
|
||||||
|
|
||||||
// API-basiertes Lesen verarbeiten
|
// API-basiertes Lesen verarbeiten
|
||||||
if (rfidReadRequested) {
|
if (rfidReadRequested) {
|
||||||
handleAPIRFIDRead();
|
handleAPIRFIDRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define LED_PIN 13
|
||||||
#define LED_PIN 13
|
|
||||||
|
|
||||||
// Status LED
|
// Status LED
|
||||||
unsigned long lastLedBlink = 0;
|
unsigned long lastLedBlink = 0;
|
||||||
@@ -14,45 +13,44 @@ void setupLED() {
|
|||||||
|
|
||||||
void updateStatusLED(int blinkPattern) {
|
void updateStatusLED(int blinkPattern) {
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
switch (blinkPattern) {
|
|
||||||
case 0: // Suche Master - Langsames Blinken
|
|
||||||
if (currentTime - lastLedBlink > 1000) {
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_PIN, ledState);
|
|
||||||
lastLedBlink = currentTime;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // Verbunden - Kurzes Blinken alle 3 Sekunden
|
|
||||||
if (currentTime - lastLedBlink > 3000) {
|
|
||||||
digitalWrite(LED_PIN, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(LED_PIN, LOW);
|
|
||||||
lastLedBlink = currentTime;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // Button gedrückt - Schnelles Blinken 3x
|
|
||||||
static int blinkCount = 0;
|
|
||||||
if (currentTime - lastLedBlink > 100) {
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_PIN, ledState);
|
|
||||||
lastLedBlink = currentTime;
|
|
||||||
blinkCount++;
|
|
||||||
|
|
||||||
if (blinkCount >= 6) { // 3 komplette Blinks
|
|
||||||
blinkCount = 0;
|
|
||||||
blinkPattern = 1; // Zurück zu verbunden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case 3: // Flash bei Empfang - Einmaliges kurzes Blinken
|
switch (blinkPattern) {
|
||||||
{
|
case 0: // Suche Master - Langsames Blinken
|
||||||
digitalWrite(LED_PIN, HIGH);
|
if (currentTime - lastLedBlink > 1000) {
|
||||||
delay(100);
|
ledState = !ledState;
|
||||||
digitalWrite(LED_PIN, LOW);
|
digitalWrite(LED_PIN, ledState);
|
||||||
|
lastLedBlink = currentTime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // Verbunden - Kurzes Blinken alle 3 Sekunden
|
||||||
|
if (currentTime - lastLedBlink > 3000) {
|
||||||
|
digitalWrite(LED_PIN, HIGH);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(LED_PIN, LOW);
|
||||||
|
lastLedBlink = currentTime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Button gedrückt - Schnelles Blinken 3x
|
||||||
|
static int blinkCount = 0;
|
||||||
|
if (currentTime - lastLedBlink > 100) {
|
||||||
|
ledState = !ledState;
|
||||||
|
digitalWrite(LED_PIN, ledState);
|
||||||
|
lastLedBlink = currentTime;
|
||||||
|
blinkCount++;
|
||||||
|
|
||||||
|
if (blinkCount >= 6) { // 3 komplette Blinks
|
||||||
|
blinkCount = 0;
|
||||||
|
blinkPattern = 1; // Zurück zu verbunden
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
case 3: // Flash bei Empfang - Einmaliges kurzes Blinken
|
||||||
|
{
|
||||||
|
digitalWrite(LED_PIN, HIGH);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(LED_PIN, LOW);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
269
src/timesync.h
269
src/timesync.h
@@ -1,12 +1,13 @@
|
|||||||
// Zeit-bezogene Variablen und Includes
|
// Zeit-bezogene Variablen und Includes
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
#include "RTClib.h"
|
#include "RTClib.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
RTC_PCF8523 rtc;
|
RTC_PCF8523 rtc;
|
||||||
|
|
||||||
@@ -16,8 +17,8 @@ struct timezone tz;
|
|||||||
time_t now;
|
time_t now;
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
|
|
||||||
//Prototypen für Zeit-Management-Funktionen
|
// Prototypen für Zeit-Management-Funktionen
|
||||||
void setupTimeAPI(AsyncWebServer& server);
|
void setupTimeAPI(AsyncWebServer &server);
|
||||||
String getCurrentTimeJSON();
|
String getCurrentTimeJSON();
|
||||||
bool setSystemTime(long timestamp);
|
bool setSystemTime(long timestamp);
|
||||||
|
|
||||||
@@ -25,11 +26,11 @@ bool setSystemTime(long timestamp);
|
|||||||
String getCurrentTimeJSON() {
|
String getCurrentTimeJSON() {
|
||||||
gettimeofday(&tv, &tz);
|
gettimeofday(&tv, &tz);
|
||||||
now = tv.tv_sec;
|
now = tv.tv_sec;
|
||||||
|
|
||||||
StaticJsonDocument<200> doc;
|
StaticJsonDocument<200> doc;
|
||||||
doc["timestamp"] = (long)now;
|
doc["timestamp"] = (long)now;
|
||||||
doc["success"] = true;
|
doc["success"] = true;
|
||||||
|
|
||||||
// Zusätzliche Zeitinformationen
|
// Zusätzliche Zeitinformationen
|
||||||
gmtime_r(&now, &timeinfo);
|
gmtime_r(&now, &timeinfo);
|
||||||
char timeStr[64];
|
char timeStr[64];
|
||||||
@@ -41,7 +42,7 @@ String getCurrentTimeJSON() {
|
|||||||
doc["hour"] = timeinfo.tm_hour;
|
doc["hour"] = timeinfo.tm_hour;
|
||||||
doc["minute"] = timeinfo.tm_min;
|
doc["minute"] = timeinfo.tm_min;
|
||||||
doc["second"] = timeinfo.tm_sec;
|
doc["second"] = timeinfo.tm_sec;
|
||||||
|
|
||||||
String response;
|
String response;
|
||||||
serializeJson(doc, response);
|
serializeJson(doc, response);
|
||||||
return response;
|
return response;
|
||||||
@@ -51,7 +52,7 @@ bool setSystemTime(long timestamp) {
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = timestamp;
|
tv.tv_sec = timestamp;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
if (settimeofday(&tv, NULL) == 0) {
|
if (settimeofday(&tv, NULL) == 0) {
|
||||||
Serial.println("Zeit erfolgreich gesetzt: " + String(timestamp));
|
Serial.println("Zeit erfolgreich gesetzt: " + String(timestamp));
|
||||||
return true;
|
return true;
|
||||||
@@ -61,151 +62,157 @@ bool setSystemTime(long timestamp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimeAPI(AsyncWebServer& server) {
|
void setupTimeAPI(AsyncWebServer &server) {
|
||||||
|
|
||||||
//setupRTC();
|
// setupRTC();
|
||||||
|
|
||||||
// API-Endpunkt: Aktuelle Zeit abrufen
|
// API-Endpunkt: Aktuelle Zeit abrufen
|
||||||
server.on("/api/time", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/time", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
String response = getCurrentTimeJSON();
|
String response = getCurrentTimeJSON();
|
||||||
request->send(200, "application/json", response);
|
request->send(200, "application/json", response);
|
||||||
});
|
});
|
||||||
|
|
||||||
// API-Endpunkt: Zeit setzen
|
// API-Endpunkt: Zeit setzen
|
||||||
server.on("/api/set-time", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/set-time", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
StaticJsonDocument<100> doc;
|
StaticJsonDocument<100> doc;
|
||||||
|
|
||||||
if (request->hasParam("timestamp", true)) {
|
if (request->hasParam("timestamp", true)) {
|
||||||
String timestampStr = request->getParam("timestamp", true)->value();
|
String timestampStr = request->getParam("timestamp", true)->value();
|
||||||
long timestamp = timestampStr.toInt();
|
long timestamp = timestampStr.toInt();
|
||||||
|
|
||||||
if (timestamp > 0) {
|
if (timestamp > 0) {
|
||||||
bool success = setSystemTime(timestamp);
|
bool success = setSystemTime(timestamp);
|
||||||
|
|
||||||
doc["success"] = success;
|
doc["success"] = success;
|
||||||
if (success) {
|
if (success) {
|
||||||
doc["message"] = "Zeit erfolgreich gesetzt";
|
doc["message"] = "Zeit erfolgreich gesetzt";
|
||||||
doc["timestamp"] = timestamp;
|
doc["timestamp"] = timestamp;
|
||||||
|
} else {
|
||||||
|
doc["message"] = "Fehler beim Setzen der Zeit";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doc["message"] = "Fehler beim Setzen der Zeit";
|
doc["success"] = false;
|
||||||
|
doc["message"] = "Ungültiger Timestamp";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
doc["success"] = false;
|
doc["success"] = false;
|
||||||
doc["message"] = "Ungültiger Timestamp";
|
doc["message"] = "Timestamp-Parameter fehlt";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
doc["success"] = false;
|
|
||||||
doc["message"] = "Timestamp-Parameter fehlt";
|
|
||||||
}
|
|
||||||
|
|
||||||
String response;
|
|
||||||
serializeJson(doc, response);
|
|
||||||
request->send(200, "application/json", response);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Alternative Implementierung für manuelle Datum/Zeit-Eingabe
|
String response;
|
||||||
server.on("/api/set-datetime", HTTP_POST, [](AsyncWebServerRequest *request){
|
serializeJson(doc, response);
|
||||||
StaticJsonDocument<150> doc;
|
request->send(200, "application/json", response);
|
||||||
|
});
|
||||||
if (request->hasParam("year", true) &&
|
|
||||||
request->hasParam("month", true) &&
|
// Alternative Implementierung für manuelle Datum/Zeit-Eingabe
|
||||||
request->hasParam("day", true) &&
|
server.on("/api/set-datetime", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
request->hasParam("hour", true) &&
|
StaticJsonDocument<150> doc;
|
||||||
request->hasParam("minute", true) &&
|
|
||||||
request->hasParam("second", true)) {
|
if (request->hasParam("year", true) && request->hasParam("month", true) &&
|
||||||
|
request->hasParam("day", true) && request->hasParam("hour", true) &&
|
||||||
struct tm timeinfo;
|
request->hasParam("minute", true) &&
|
||||||
timeinfo.tm_year = request->getParam("year", true)->value().toInt() - 1900;
|
request->hasParam("second", true)) {
|
||||||
timeinfo.tm_mon = request->getParam("month", true)->value().toInt() - 1;
|
|
||||||
timeinfo.tm_mday = request->getParam("day", true)->value().toInt();
|
struct tm timeinfo;
|
||||||
timeinfo.tm_hour = request->getParam("hour", true)->value().toInt();
|
timeinfo.tm_year =
|
||||||
timeinfo.tm_min = request->getParam("minute", true)->value().toInt();
|
request->getParam("year", true)->value().toInt() - 1900;
|
||||||
timeinfo.tm_sec = request->getParam("second", true)->value().toInt();
|
timeinfo.tm_mon = request->getParam("month", true)->value().toInt() - 1;
|
||||||
|
timeinfo.tm_mday = request->getParam("day", true)->value().toInt();
|
||||||
time_t timestamp = mktime(&timeinfo);
|
timeinfo.tm_hour = request->getParam("hour", true)->value().toInt();
|
||||||
|
timeinfo.tm_min = request->getParam("minute", true)->value().toInt();
|
||||||
if (timestamp != -1) {
|
timeinfo.tm_sec = request->getParam("second", true)->value().toInt();
|
||||||
bool success = setSystemTime(timestamp);
|
|
||||||
|
time_t timestamp = mktime(&timeinfo);
|
||||||
doc["success"] = success;
|
|
||||||
if (success) {
|
if (timestamp != -1) {
|
||||||
doc["message"] = "Zeit erfolgreich gesetzt";
|
bool success = setSystemTime(timestamp);
|
||||||
doc["timestamp"] = (long)timestamp;
|
|
||||||
|
doc["success"] = success;
|
||||||
|
if (success) {
|
||||||
|
doc["message"] = "Zeit erfolgreich gesetzt";
|
||||||
|
doc["timestamp"] = (long)timestamp;
|
||||||
|
} else {
|
||||||
|
doc["message"] = "Fehler beim Setzen der Zeit";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doc["message"] = "Fehler beim Setzen der Zeit";
|
doc["success"] = false;
|
||||||
|
doc["message"] = "Ungültiges Datum/Zeit";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
doc["success"] = false;
|
doc["success"] = false;
|
||||||
doc["message"] = "Ungültiges Datum/Zeit";
|
doc["message"] = "Datum/Zeit-Parameter fehlen";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
doc["success"] = false;
|
|
||||||
doc["message"] = "Datum/Zeit-Parameter fehlen";
|
|
||||||
}
|
|
||||||
|
|
||||||
String response;
|
|
||||||
serializeJson(doc, response);
|
|
||||||
request->send(200, "application/json", response);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Erweiterte Zeit-Informationen (optional)
|
String response;
|
||||||
server.on("/api/time/info", HTTP_GET, [](AsyncWebServerRequest *request){
|
serializeJson(doc, response);
|
||||||
gettimeofday(&tv, &tz);
|
request->send(200, "application/json", response);
|
||||||
now = tv.tv_sec;
|
});
|
||||||
gmtime_r(&now, &timeinfo);
|
|
||||||
|
// Erweiterte Zeit-Informationen (optional)
|
||||||
StaticJsonDocument<400> doc;
|
server.on("/api/time/info", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
doc["timestamp"] = (long)now;
|
gettimeofday(&tv, &tz);
|
||||||
doc["uptime"] = millis();
|
now = tv.tv_sec;
|
||||||
|
gmtime_r(&now, &timeinfo);
|
||||||
// Formatierte Zeitstrings
|
|
||||||
char buffer[64];
|
StaticJsonDocument<400> doc;
|
||||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d", &timeinfo);
|
doc["timestamp"] = (long)now;
|
||||||
doc["date"] = String(buffer);
|
doc["uptime"] = millis();
|
||||||
|
|
||||||
strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeinfo);
|
// Formatierte Zeitstrings
|
||||||
doc["time"] = String(buffer);
|
char buffer[64];
|
||||||
|
strftime(buffer, sizeof(buffer), "%Y-%m-%d", &timeinfo);
|
||||||
strftime(buffer, sizeof(buffer), "%A", &timeinfo);
|
doc["date"] = String(buffer);
|
||||||
doc["weekday"] = String(buffer);
|
|
||||||
|
strftime(buffer, sizeof(buffer), "%H:%M:%S", &timeinfo);
|
||||||
strftime(buffer, sizeof(buffer), "%B", &timeinfo);
|
doc["time"] = String(buffer);
|
||||||
doc["month_name"] = String(buffer);
|
|
||||||
|
strftime(buffer, sizeof(buffer), "%A", &timeinfo);
|
||||||
// Zusätzliche Infos
|
doc["weekday"] = String(buffer);
|
||||||
doc["day_of_year"] = timeinfo.tm_yday + 1;
|
|
||||||
doc["week_of_year"] = (timeinfo.tm_yday + 7 - timeinfo.tm_wday) / 7;
|
strftime(buffer, sizeof(buffer), "%B", &timeinfo);
|
||||||
doc["is_dst"] = timeinfo.tm_isdst;
|
doc["month_name"] = String(buffer);
|
||||||
|
|
||||||
String response;
|
// Zusätzliche Infos
|
||||||
serializeJson(doc, response);
|
doc["day_of_year"] = timeinfo.tm_yday + 1;
|
||||||
request->send(200, "application/json", response);
|
doc["week_of_year"] = (timeinfo.tm_yday + 7 - timeinfo.tm_wday) / 7;
|
||||||
});
|
doc["is_dst"] = timeinfo.tm_isdst;
|
||||||
Serial.println("Zeit-API initialisiert");
|
|
||||||
|
String response;
|
||||||
|
serializeJson(doc, response);
|
||||||
|
request->send(200, "application/json", response);
|
||||||
|
});
|
||||||
|
Serial.println("Zeit-API initialisiert");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hilfsfunktion: Zeit-Validierung
|
// Hilfsfunktion: Zeit-Validierung
|
||||||
bool isValidDateTime(int year, int month, int day, int hour, int minute, int second) {
|
bool isValidDateTime(int year, int month, int day, int hour, int minute,
|
||||||
if (year < 2020 || year > 2099) return false;
|
int second) {
|
||||||
if (month < 1 || month > 12) return false;
|
if (year < 2020 || year > 2099)
|
||||||
if (day < 1 || day > 31) return false;
|
return false;
|
||||||
if (hour < 0 || hour > 23) return false;
|
if (month < 1 || month > 12)
|
||||||
if (minute < 0 || minute > 59) return false;
|
return false;
|
||||||
if (second < 0 || second > 59) return false;
|
if (day < 1 || day > 31)
|
||||||
|
return false;
|
||||||
|
if (hour < 0 || hour > 23)
|
||||||
|
return false;
|
||||||
|
if (minute < 0 || minute > 59)
|
||||||
|
return false;
|
||||||
|
if (second < 0 || second > 59)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Erweiterte Validierung für Monatstage
|
// Erweiterte Validierung für Monatstage
|
||||||
int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
// Schaltjahr-Prüfung
|
// Schaltjahr-Prüfung
|
||||||
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
|
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
|
||||||
daysInMonth[1] = 29;
|
daysInMonth[1] = 29;
|
||||||
}
|
}
|
||||||
|
|
||||||
return day <= daysInMonth[month - 1];
|
return day <= daysInMonth[month - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getCurrentTimestampMs() {
|
uint64_t getCurrentTimestampMs() {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
return (uint64_t)tv.tv_sec * 1000LL + (uint64_t)tv.tv_usec / 1000LL;
|
return (uint64_t)tv.tv_sec * 1000LL + (uint64_t)tv.tv_usec / 1000LL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,57 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
void sendMQTTMessage(const char * topic, const char * message);
|
void sendMQTTMessage(const char *topic, const char *message);
|
||||||
|
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <AsyncWebSocket.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <AsyncWebSocket.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "communication.h"
|
||||||
#include <buttonassigh.h>
|
#include <buttonassigh.h>
|
||||||
#include <wificlass.h>
|
#include <wificlass.h>
|
||||||
#include "communication.h"
|
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
AsyncWebSocket ws("/ws");
|
AsyncWebSocket ws("/ws");
|
||||||
|
|
||||||
void setupRoutes(){
|
void setupRoutes() {
|
||||||
// Web Server Routes
|
// Web Server Routes
|
||||||
|
|
||||||
// Attach WebSocket to the server
|
// Attach WebSocket to the server
|
||||||
server.addHandler(&ws);
|
server.addHandler(&ws);
|
||||||
|
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(SPIFFS, "/index.html", "text/html");
|
request->send(SPIFFS, "/index.html", "text/html");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(SPIFFS, "/settings.html", "text/html");
|
request->send(SPIFFS, "/settings.html", "text/html");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/rfid", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/rfid", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(SPIFFS, "/rfid.html", "text/html");
|
request->send(SPIFFS, "/rfid.html", "text/html");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/firmware.bin", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/firmware.bin", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (SPIFFS.exists("/firmware.bin")) {
|
if (SPIFFS.exists("/firmware.bin")) {
|
||||||
request->send(SPIFFS, "/firmware.bin", "application/octet-stream");
|
request->send(SPIFFS, "/firmware.bin", "application/octet-stream");
|
||||||
Serial.println("Firmware file served: /firmware.bin");
|
Serial.println("Firmware file served: /firmware.bin");
|
||||||
} else {
|
} else {
|
||||||
request->send(404, "application/json", "{\"error\":\"File not found\"}");
|
request->send(404, "application/json", "{\"error\":\"File not found\"}");
|
||||||
Serial.println("Firmware file not found: /firmware.bin");
|
Serial.println("Firmware file not found: /firmware.bin");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/data", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/data", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(200, "application/json", getTimerDataJSON());
|
request->send(200, "application/json", getTimerDataJSON());
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/reset-best", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/reset-best", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
Serial.println("/api/reset-best called");
|
Serial.println("/api/reset-best called");
|
||||||
timerData.bestTime1 = 0;
|
timerData.bestTime1 = 0;
|
||||||
timerData.bestTime2 = 0;
|
timerData.bestTime2 = 0;
|
||||||
@@ -61,38 +63,39 @@ void setupRoutes(){
|
|||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/unlearn-button", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/unlearn-button", HTTP_POST,
|
||||||
Serial.println("/api/unlearn-button called");
|
[](AsyncWebServerRequest *request) {
|
||||||
unlearnButton();
|
Serial.println("/api/unlearn-button called");
|
||||||
request->send(200, "application/json", "{\"success\":true}");
|
unlearnButton();
|
||||||
|
request->send(200, "application/json", "{\"success\":true}");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
server.on("/api/set-max-time", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
|
|
||||||
server.on("/api/set-max-time", HTTP_POST, [](AsyncWebServerRequest *request){
|
|
||||||
Serial.println("/api/set-max-time called");
|
Serial.println("/api/set-max-time called");
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (request->hasParam("maxTime", true)) {
|
if (request->hasParam("maxTime", true)) {
|
||||||
maxTimeBeforeReset = request->getParam("maxTime", true)->value().toInt() * 1000;
|
maxTimeBeforeReset =
|
||||||
changed = true;
|
request->getParam("maxTime", true)->value().toInt() * 1000;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
if (request->hasParam("maxTimeDisplay", true)) {
|
if (request->hasParam("maxTimeDisplay", true)) {
|
||||||
maxTimeDisplay = request->getParam("maxTimeDisplay", true)->value().toInt() * 1000;
|
maxTimeDisplay =
|
||||||
changed = true;
|
request->getParam("maxTimeDisplay", true)->value().toInt() * 1000;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
DynamicJsonDocument doc(32);
|
DynamicJsonDocument doc(32);
|
||||||
doc["success"] = true;
|
doc["success"] = true;
|
||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
} else {
|
} else {
|
||||||
request->send(400, "application/json", "{\"success\":false}");
|
request->send(400, "application/json", "{\"success\":false}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/get-settings", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/get-settings", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
Serial.println("/api/get-settings called");
|
Serial.println("/api/get-settings called");
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
doc["maxTime"] = maxTimeBeforeReset / 1000;
|
doc["maxTime"] = maxTimeBeforeReset / 1000;
|
||||||
@@ -102,31 +105,33 @@ void setupRoutes(){
|
|||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/start-learning", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/start-learning", HTTP_POST,
|
||||||
Serial.println("/api/start-learning called");
|
[](AsyncWebServerRequest *request) {
|
||||||
learningMode = true;
|
Serial.println("/api/start-learning called");
|
||||||
learningStep = 0;
|
learningMode = true;
|
||||||
DynamicJsonDocument doc(64);
|
learningStep = 0;
|
||||||
doc["success"] = true;
|
DynamicJsonDocument doc(64);
|
||||||
String result;
|
doc["success"] = true;
|
||||||
serializeJson(doc, result);
|
String result;
|
||||||
Serial.println("Learning mode started");
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
Serial.println("Learning mode started");
|
||||||
});
|
request->send(200, "application/json", result);
|
||||||
|
});
|
||||||
|
|
||||||
server.on("/api/stop-learning", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/api/stop-learning", HTTP_POST,
|
||||||
Serial.println("/api/stop-learning called");
|
[](AsyncWebServerRequest *request) {
|
||||||
learningMode = false;
|
Serial.println("/api/stop-learning called");
|
||||||
learningStep = 0;
|
learningMode = false;
|
||||||
DynamicJsonDocument doc(64);
|
learningStep = 0;
|
||||||
doc["success"] = true;
|
DynamicJsonDocument doc(64);
|
||||||
String result;
|
doc["success"] = true;
|
||||||
serializeJson(doc, result);
|
String result;
|
||||||
Serial.println("Learning mode stopped");
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
Serial.println("Learning mode stopped");
|
||||||
});
|
request->send(200, "application/json", result);
|
||||||
|
});
|
||||||
|
|
||||||
server.on("/api/learn/status", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/learn/status", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
doc["active"] = learningMode;
|
doc["active"] = learningMode;
|
||||||
doc["step"] = learningStep;
|
doc["step"] = learningStep;
|
||||||
@@ -135,18 +140,19 @@ void setupRoutes(){
|
|||||||
request->send(200, "application/json", response);
|
request->send(200, "application/json", response);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/buttons/status", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/buttons/status", HTTP_GET,
|
||||||
DynamicJsonDocument doc(128);
|
[](AsyncWebServerRequest *request) {
|
||||||
doc["lane1Start"] = buttonConfigs.start1.isAssigned;
|
DynamicJsonDocument doc(128);
|
||||||
doc["lane1Stop"] = buttonConfigs.stop1.isAssigned;
|
doc["lane1Start"] = buttonConfigs.start1.isAssigned;
|
||||||
doc["lane2Start"] = buttonConfigs.start2.isAssigned;
|
doc["lane1Stop"] = buttonConfigs.stop1.isAssigned;
|
||||||
doc["lane2Stop"] = buttonConfigs.stop2.isAssigned;
|
doc["lane2Start"] = buttonConfigs.start2.isAssigned;
|
||||||
String result;
|
doc["lane2Stop"] = buttonConfigs.stop2.isAssigned;
|
||||||
serializeJson(doc, result);
|
String result;
|
||||||
request->send(200, "application/json", result);
|
serializeJson(doc, result);
|
||||||
});
|
request->send(200, "application/json", result);
|
||||||
|
});
|
||||||
|
|
||||||
server.on("/api/info", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/info", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
|
|
||||||
// IP address
|
// IP address
|
||||||
@@ -158,7 +164,8 @@ void setupRoutes(){
|
|||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
||||||
char macStr[18];
|
char macStr[18];
|
||||||
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2],
|
||||||
|
mac[3], mac[4], mac[5]);
|
||||||
doc["mac"] = macStr;
|
doc["mac"] = macStr;
|
||||||
|
|
||||||
// Free memory
|
// Free memory
|
||||||
@@ -166,55 +173,59 @@ void setupRoutes(){
|
|||||||
|
|
||||||
// Connected buttons (count assigned)
|
// Connected buttons (count assigned)
|
||||||
int connected = 0;
|
int connected = 0;
|
||||||
if (buttonConfigs.start1.isAssigned) connected++;
|
if (buttonConfigs.start1.isAssigned)
|
||||||
if (buttonConfigs.stop1.isAssigned) connected++;
|
connected++;
|
||||||
if (buttonConfigs.start2.isAssigned) connected++;
|
if (buttonConfigs.stop1.isAssigned)
|
||||||
if (buttonConfigs.stop2.isAssigned) connected++;
|
connected++;
|
||||||
|
if (buttonConfigs.start2.isAssigned)
|
||||||
|
connected++;
|
||||||
|
if (buttonConfigs.stop2.isAssigned)
|
||||||
|
connected++;
|
||||||
doc["connectedButtons"] = connected;
|
doc["connectedButtons"] = connected;
|
||||||
|
|
||||||
doc["valid"] = checkLicence() > 0 ? "Ja" : "Nein";
|
doc["valid"] = checkLicence() > 0 ? "Ja" : "Nein";
|
||||||
doc["tier"] = checkLicence() ;
|
doc["tier"] = checkLicence();
|
||||||
|
|
||||||
|
|
||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setze WLAN-Name und Passwort (POST)
|
// 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");
|
Serial.println("/api/set-wifi called");
|
||||||
String ssid, password;
|
String ssid, password;
|
||||||
if (request->hasParam("ssid", true)) {
|
if (request->hasParam("ssid", true)) {
|
||||||
ssid = request->getParam("ssid", true)->value();
|
ssid = request->getParam("ssid", true)->value();
|
||||||
}
|
}
|
||||||
if (request->hasParam("password", true)) {
|
if (request->hasParam("password", true)) {
|
||||||
password = request->getParam("password", true)->value();
|
password = request->getParam("password", true)->value();
|
||||||
}
|
}
|
||||||
if (ssid.length() > 0) {
|
if (ssid.length() > 0) {
|
||||||
// Speicher freigeben, bevor neue Werte zugewiesen werden
|
// Speicher freigeben, bevor neue Werte zugewiesen werden
|
||||||
free(ssidSTA);
|
free(ssidSTA);
|
||||||
free(passwordSTA);
|
free(passwordSTA);
|
||||||
|
|
||||||
// Neue Werte zuweisen
|
// Neue Werte zuweisen
|
||||||
ssidSTA = strdup(ssid.c_str());
|
ssidSTA = strdup(ssid.c_str());
|
||||||
passwordSTA = strdup(password.c_str());
|
passwordSTA = strdup(password.c_str());
|
||||||
|
|
||||||
saveWifiSettings();
|
saveWifiSettings();
|
||||||
|
|
||||||
// Rückmeldung
|
// Rückmeldung
|
||||||
DynamicJsonDocument doc(64);
|
DynamicJsonDocument doc(64);
|
||||||
doc["success"] = true;
|
doc["success"] = true;
|
||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
} else {
|
} 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)
|
// Liefert aktuelle WLAN-Einstellungen (GET)
|
||||||
server.on("/api/get-wifi", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/api/get-wifi", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
DynamicJsonDocument doc(128);
|
DynamicJsonDocument doc(128);
|
||||||
doc["ssid"] = ssidSTA ? ssidSTA : "";
|
doc["ssid"] = ssidSTA ? ssidSTA : "";
|
||||||
doc["password"] = passwordSTA ? passwordSTA : "";
|
doc["password"] = passwordSTA ? passwordSTA : "";
|
||||||
@@ -223,31 +234,30 @@ void setupRoutes(){
|
|||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/api/set-location", HTTP_POST, [](AsyncWebServerRequest *request) {
|
server.on("/api/set-location", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
Serial.println("/api/set-location called");
|
Serial.println("/api/set-location called");
|
||||||
|
|
||||||
String id, name;
|
String id, name;
|
||||||
|
|
||||||
if (request->hasParam("id", true)) {
|
if (request->hasParam("id", true)) {
|
||||||
id = request->getParam("id", true)->value();
|
id = request->getParam("id", true)->value();
|
||||||
}
|
}
|
||||||
if (request->hasParam("name", true)) {
|
if (request->hasParam("name", true)) {
|
||||||
name = request->getParam("name", true)->value();
|
name = request->getParam("name", true)->value();
|
||||||
}
|
}
|
||||||
masterlocation = name;
|
masterlocation = name;
|
||||||
|
|
||||||
saveLocationSettings();
|
|
||||||
|
|
||||||
// Rückmeldung
|
saveLocationSettings();
|
||||||
DynamicJsonDocument doc(64);
|
|
||||||
doc["success"] = true;
|
|
||||||
String result;
|
|
||||||
serializeJson(doc, result);
|
|
||||||
request->send(200, "application/json", result);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/api/get-location", HTTP_GET, [](AsyncWebServerRequest *request){
|
// Rückmeldung
|
||||||
|
DynamicJsonDocument doc(64);
|
||||||
|
doc["success"] = true;
|
||||||
|
String result;
|
||||||
|
serializeJson(doc, result);
|
||||||
|
request->send(200, "application/json", result);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/api/get-location", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
DynamicJsonDocument doc(128);
|
DynamicJsonDocument doc(128);
|
||||||
loadLocationSettings();
|
loadLocationSettings();
|
||||||
doc["locationid"] = masterlocation ? masterlocation : "";
|
doc["locationid"] = masterlocation ? masterlocation : "";
|
||||||
@@ -256,41 +266,39 @@ server.on("/api/set-location", HTTP_POST, [](AsyncWebServerRequest *request) {
|
|||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.on("/api/updateButtons", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
server.on("/api/updateButtons", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
||||||
Serial.println("/api/updateButtons called");
|
Serial.println("/api/updateButtons called");
|
||||||
|
|
||||||
// MQTT publish on aquacross/update/flag with raw payload "1"
|
// MQTT publish on aquacross/update/flag with raw payload "1"
|
||||||
sendMQTTMessage("aquacross/update/flag", "1");
|
sendMQTTMessage("aquacross/update/flag", "1");
|
||||||
Serial.println("MQTT published: aquacross/update/flag -> 1");
|
Serial.println("MQTT published: aquacross/update/flag -> 1");
|
||||||
request->send(200, "application/json", "{\"success\":true}");
|
request->send(200, "application/json", "{\"success\":true}");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Statische Dateien
|
||||||
// Statische Dateien
|
|
||||||
server.serveStatic("/", SPIFFS, "/");
|
server.serveStatic("/", SPIFFS, "/");
|
||||||
server.begin();
|
server.begin();
|
||||||
Serial.println("Web Server gestartet");
|
Serial.println("Web Server gestartet");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWebSocket() {
|
void setupWebSocket() {
|
||||||
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client,
|
||||||
if (type == WS_EVT_CONNECT) {
|
AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
||||||
Serial.printf("WebSocket client connected: %u\n", client->id());
|
if (type == WS_EVT_CONNECT) {
|
||||||
} else if (type == WS_EVT_DISCONNECT) {
|
Serial.printf("WebSocket client connected: %u\n", client->id());
|
||||||
Serial.printf("WebSocket client disconnected: %u\n", client->id());
|
} else if (type == WS_EVT_DISCONNECT) {
|
||||||
} else if (type == WS_EVT_DATA) {
|
Serial.printf("WebSocket client disconnected: %u\n", client->id());
|
||||||
// Handle incoming WebSocket messages if needed
|
} else if (type == WS_EVT_DATA) {
|
||||||
Serial.printf("WebSocket message received: %s\n", (char *)data);
|
// Handle incoming WebSocket messages if needed
|
||||||
}
|
Serial.printf("WebSocket message received: %s\n", (char *)data);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushUpdateToFrontend(const String &message) {
|
void pushUpdateToFrontend(const String &message) {
|
||||||
ws.textAll(message); // Send the message to all connected clients
|
ws.textAll(message); // Send the message to all connected clients
|
||||||
}
|
}
|
||||||
|
|
||||||
void loopWebSocket() {
|
void loopWebSocket() {
|
||||||
ws.cleanupClients(); // Clean up disconnected clients
|
ws.cleanupClients(); // Clean up disconnected clients
|
||||||
}
|
}
|
||||||
|
|||||||
121
src/wificlass.h
121
src/wificlass.h
@@ -1,13 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <esp_wifi.h>
|
|
||||||
#include <PrettyOTA.h>
|
|
||||||
#include <esp_now.h>
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <ESPmDNS.h> // <-- mDNS hinzufügen
|
#include <ESPmDNS.h> // <-- mDNS hinzufügen
|
||||||
|
#include <PrettyOTA.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <esp_now.h>
|
||||||
|
#include <esp_wifi.h>
|
||||||
|
|
||||||
|
|
||||||
#include "master.h"
|
|
||||||
#include "licenceing.h"
|
#include "licenceing.h"
|
||||||
|
#include "master.h"
|
||||||
|
|
||||||
|
|
||||||
String uniqueSSID;
|
String uniqueSSID;
|
||||||
|
|
||||||
@@ -17,84 +19,79 @@ String getUniqueSSID();
|
|||||||
|
|
||||||
void setupWifi() {
|
void setupWifi() {
|
||||||
|
|
||||||
uniqueSSID = getUniqueSSID();
|
uniqueSSID = getUniqueSSID();
|
||||||
ssidAP = uniqueSSID.c_str();
|
ssidAP = uniqueSSID.c_str();
|
||||||
if (ssidSTA == nullptr || passwordSTA == nullptr || String(ssidSTA).isEmpty() || String(passwordSTA).isEmpty() ) {
|
if (ssidSTA == nullptr || passwordSTA == nullptr ||
|
||||||
Serial.println("Fehler: ssidSTA oder passwordSTA ist null!");
|
String(ssidSTA).isEmpty() || String(passwordSTA).isEmpty()) {
|
||||||
WiFi.mode(WIFI_MODE_AP);
|
Serial.println("Fehler: ssidSTA oder passwordSTA ist null!");
|
||||||
WiFi.softAP(ssidAP, passwordAP);
|
WiFi.mode(WIFI_MODE_AP);
|
||||||
|
WiFi.softAP(ssidAP, passwordAP);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_MODE_APSTA);
|
||||||
|
WiFi.begin(ssidSTA, passwordSTA);
|
||||||
|
WiFi.softAP(ssidAP, passwordAP);
|
||||||
|
|
||||||
|
// Add timeout for WiFi connection
|
||||||
|
unsigned long startAttemptTime = millis();
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED &&
|
||||||
|
millis() - startAttemptTime < 10000) { // 10 seconds timeout
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
}
|
}
|
||||||
else
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
{
|
Serial.println("Fehler: Verbindung zum WLAN fehlgeschlagen!");
|
||||||
|
Serial.println("Starte Access Point...");
|
||||||
WiFi.mode(WIFI_MODE_APSTA);
|
WiFi.mode(WIFI_MODE_AP);
|
||||||
WiFi.begin(ssidSTA, passwordSTA);
|
WiFi.softAP(ssidAP, passwordAP);
|
||||||
WiFi.softAP(ssidAP, passwordAP);
|
} else {
|
||||||
|
Serial.println("Erfolgreich mit WLAN verbunden!");
|
||||||
// Add timeout for WiFi connection
|
Serial.print("IP Adresse: ");
|
||||||
unsigned long startAttemptTime = millis();
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED &&
|
|
||||||
millis() - startAttemptTime < 10000) { // 10 seconds timeout
|
|
||||||
delay(500);
|
|
||||||
Serial.print(".");
|
|
||||||
|
|
||||||
}
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
Serial.println("Fehler: Verbindung zum WLAN fehlgeschlagen!");
|
|
||||||
Serial.println("Starte Access Point...");
|
|
||||||
WiFi.mode(WIFI_MODE_AP);
|
|
||||||
WiFi.softAP(ssidAP, passwordAP);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Serial.println("Erfolgreich mit WLAN verbunden!");
|
|
||||||
Serial.print("IP Adresse: ");
|
|
||||||
Serial.println(WiFi.localIP());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only wait for connection if ssidSTA and passwordSTA are set
|
||||||
//Only wait for connection if ssidSTA and passwordSTA are set
|
|
||||||
Serial.println("WiFi AP gestartet");
|
Serial.println("WiFi AP gestartet");
|
||||||
Serial.print("SSID: ");
|
Serial.print("SSID: ");
|
||||||
Serial.println(WiFi.softAPSSID());
|
Serial.println(WiFi.softAPSSID());
|
||||||
Serial.print("IP Adresse: ");
|
Serial.print("IP Adresse: ");
|
||||||
Serial.println(WiFi.softAPIP());
|
Serial.println(WiFi.softAPIP());
|
||||||
Serial.println("PrettyOTA can be accessed at: http://" + WiFi.softAPIP().toString() + "/update");
|
Serial.println("PrettyOTA can be accessed at: http://" +
|
||||||
|
WiFi.softAPIP().toString() + "/update");
|
||||||
|
|
||||||
// mDNS starten
|
// mDNS starten
|
||||||
if (MDNS.begin("aquacross-timer")) { // z.B. http://aquacross-timer.local/
|
if (MDNS.begin("aquacross-timer")) { // z.B. http://aquacross-timer.local/
|
||||||
Serial.println("mDNS responder gestartet: http://aquacross-timer.local/");
|
Serial.println("mDNS responder gestartet: http://aquacross-timer.local/");
|
||||||
} else {
|
} else {
|
||||||
Serial.println("Fehler beim Starten von mDNS!");
|
Serial.println("Fehler beim Starten von mDNS!");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupOTA(AsyncWebServer *server) {
|
void setupOTA(AsyncWebServer *server) {
|
||||||
// Initialize PrettyOTA
|
// Initialize PrettyOTA
|
||||||
OTAUpdates.Begin(server);
|
OTAUpdates.Begin(server);
|
||||||
|
|
||||||
// Set unique Hardware-ID for your hardware/board
|
// Set unique Hardware-ID for your hardware/board
|
||||||
OTAUpdates.SetHardwareID("AquaCross-Master");
|
OTAUpdates.SetHardwareID("AquaCross-Master");
|
||||||
|
|
||||||
// Set firmware version to 1.0.0
|
|
||||||
OTAUpdates.SetAppVersion(firmwareversion);
|
|
||||||
|
|
||||||
// Set current build time and date
|
// Set firmware version to 1.0.0
|
||||||
PRETTY_OTA_SET_CURRENT_BUILD_TIME_AND_DATE();
|
OTAUpdates.SetAppVersion(firmwareversion);
|
||||||
|
|
||||||
|
// Set current build time and date
|
||||||
|
PRETTY_OTA_SET_CURRENT_BUILD_TIME_AND_DATE();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getUniqueSSID() {
|
String getUniqueSSID() {
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
||||||
|
|
||||||
// Create a 5-character string from last 3 bytes of MAC
|
// Create a 5-character string from last 3 bytes of MAC
|
||||||
char uniqueId[6];
|
char uniqueId[6];
|
||||||
snprintf(uniqueId, sizeof(uniqueId), "%02X%03X", mac[4], mac[5]);
|
snprintf(uniqueId, sizeof(uniqueId), "%02X%03X", mac[4], mac[5]);
|
||||||
|
|
||||||
return String("AquaCross-") + String(uniqueId);
|
return String("AquaCross-") + String(uniqueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// WiFi als Access Point
|
// WiFi als Access Point
|
||||||
|
|||||||
Reference in New Issue
Block a user