Comments und add licence

This commit is contained in:
Carsten Graf
2025-07-12 17:39:45 +02:00
parent 585d2d7d5d
commit d10a8fef6d
11 changed files with 126 additions and 34 deletions

26
LICENCE.md Normal file
View File

@@ -0,0 +1,26 @@
# Lizenzvereinbarung (License Agreement)
Dieses Softwareprojekt ("Ninjacross Timer") sowie sämtliche zugehörigen Quellcodes, Dokumentationen und Ressourcen sind urheberrechtlich geschützt und stehen ausschließlich unter folgender Lizenz:
## Exklusive Lizenz
Die Nutzung, Vervielfältigung, Veränderung, Verbreitung oder Veröffentlichung dieses Projekts ist ausschließlich Carsten Graf (@reptil1990) vorbehalten. Jede Weitergabe, Nutzung oder Bearbeitung durch Dritte ist ohne ausdrückliche, schriftliche Genehmigung von Carsten Graf untersagt.
## Rechte des Lizenznehmers
- Exklusives, zeitlich und räumlich uneingeschränktes Nutzungsrecht für alle privaten, gewerblichen und wissenschaftlichen Zwecke
- Recht zur Modifikation, Erweiterung und Integration in eigene Projekte
- Recht zur Weitergabe an Dritte nur mit ausdrücklicher, schriftlicher Zustimmung des Rechteinhabers
## Pflichten und Einschränkungen
- Die Software darf nicht ohne Genehmigung veröffentlicht, verkauft oder anderweitig Dritten zugänglich gemacht werden
- Der Urheberrechtshinweis und diese Lizenzvereinbarung müssen in allen Kopien und abgeleiteten Werken enthalten bleiben
## Haftungsausschluss
Die Software wird ohne jegliche Gewährleistung bereitgestellt. Der Rechteinhaber übernimmt keine Haftung für Schäden, die aus der Nutzung der Software entstehen.
---
© 2025 Carsten Graf (@reptil1990). Alle Rechte vorbehalten.

20
TODO.md
View File

@@ -1,19 +1,17 @@
- KOMPLETTES Messageing System auf MQTT Server und Broker umstellen. DONE - KOMPLETTES Messageing System auf MQTT Server und Broker umstellen. DONE
- Testen wie zuverlässig das ist - Testen wie zuverlässig das ist
- message system überarbeiten. Sehr unzuverlässig mit dem peering DONE jetzt MQTT
- Uhrzeit abfragen (Eingabe der Zeitzone) DONE
- message system überarbeiten. Sehr unzuverlässig mit dem peering DONE jetzt MQTT - Sync der Buttons mit echtzeit DONE
- Uhrzeit abfragen (Eingabe der Zeitzone) DONE
- Sync der Buttons mit echtzeit
- implementierung einer RTC - implementierung einer RTC
v2.0 v2.0
- ADD Hotspot Manager to connect to a Wifi
- ADD Hotspot Manager to connect to a Wifi DONE
- ADD Licence Management (generate a programm where i can generate keys that get checked agains a private seed in the firmware) - ADD Licence Management (generate a programm where i can generate keys that get checked agains a private seed in the firmware)
enables the Wifimanager to connect DONE enables the Wifimanager to connect DONE
- ADD option point for location (read from online table and select the location via dropdown)
- ADD option to enter a name, age DONE
- ADD upload to a Online Database () DONE
- ADD option point for location (read from online table and select the location via dropdown) DONE
- ADD option to enter a name, age DONE
- ADD upload to a Online Database () DONE

View File

@@ -5,6 +5,8 @@
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus) // Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
// Weist im Lernmodus eine MAC-Adresse dem nächsten freien Button zu, sofern sie
// noch nicht vergeben ist
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 && if (buttonConfigs.start1.isAssigned &&
@@ -61,6 +63,8 @@ void handleLearningMode(const uint8_t *mac) {
} }
} }
// Startet den Lernmodus und setzt den Lernschritt entsprechend der bereits
// zugewiesenen Buttons
void handleStartLearning() { void handleStartLearning() {
learningMode = true; learningMode = true;
@@ -82,6 +86,7 @@ void handleStartLearning() {
assignedButtons, learningStep); assignedButtons, learningStep);
} }
// Erstellt ein JSON mit Status und aktuellem Lernschritt des Lernmodus
void handleLearningStatus() { void handleLearningStatus() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
doc["active"] = learningMode; doc["active"] = learningMode;
@@ -91,6 +96,7 @@ void handleLearningStatus() {
serializeJson(doc, response); serializeJson(doc, response);
} }
// Setzt alle Button-Zuweisungen zurück und speichert die Konfiguration
void unlearnButton() { void unlearnButton() {
memset(buttonConfigs.start1.mac, 0, 6); memset(buttonConfigs.start1.mac, 0, 6);

View File

@@ -3,7 +3,6 @@
#include <Arduino.h> #include <Arduino.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <PicoMQTT.h> #include <PicoMQTT.h>
#include "buttonassigh.h" #include "buttonassigh.h"
@@ -15,18 +14,24 @@
#include "webserverrouter.h" #include "webserverrouter.h"
#include <map> #include <map>
/**
* Struktur zur Speicherung von Zeitdaten für jedes Gerät/MAC.
* lastMessageTimestamp: Timestamp vom Gerät (z.B. Button)
* lastLocalTimestamp: Lokaler Timestamp beim Empfang der Nachricht
* drift: Berechneter Drift zwischen Gerät und Master
*/
struct TimestampData { struct TimestampData {
uint64_t lastMessageTimestamp; // Timestamp from the device uint64_t lastMessageTimestamp;
uint64_t lastLocalTimestamp; // Our local timestamp when message was received uint64_t lastLocalTimestamp;
uint64_t drift; // Calculated drift uint64_t drift;
}; };
// Map to store timestamp data for each MAC address // Map zur Speicherung der Zeitdaten für jede MAC-Adresse
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 eine Button-Nachricht (optional, falls benötigt)
*/
typedef struct { typedef struct {
uint8_t messageType; uint8_t messageType;
uint8_t buttonId; uint8_t buttonId;
@@ -35,8 +40,13 @@ typedef struct {
char messageId[33]; // 32 hex chars + null terminator for 128-bit ID char messageId[33]; // 32 hex chars + null terminator for 128-bit ID
} ButtonMessage; } ButtonMessage;
// MQTT-Server-Instanz
PicoMQTT::Server mqtt; PicoMQTT::Server mqtt;
/**
* Liest eine Button-JSON-Nachricht, extrahiert Typ, MAC und Timestamp,
* prüft die Button-Zuordnung und ruft die entsprechende Handler-Funktion auf.
*/
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/";
@@ -94,6 +104,10 @@ void readButtonJSON(const char *topic, const char *payload) {
updateStatusLED(3); updateStatusLED(3);
} }
/**
* Verarbeitet Heartbeat-Nachrichten von Buttons, erkennt den Button-Typ,
* extrahiert MAC und Timestamp und sendet ein JSON an das Frontend.
*/
void handleHeartbeatTopic(const char *topic, const char *payload) { void handleHeartbeatTopic(const char *topic, const char *payload) {
// Topic-Format: heartbeat/alive/CC:DB:A7:2F:95:08 // Topic-Format: heartbeat/alive/CC:DB:A7:2F:95:08
String topicStr(topic); String topicStr(topic);
@@ -138,6 +152,10 @@ void handleHeartbeatTopic(const char *topic, const char *payload) {
// Serial.printf("Published heartbeat JSON: %s\n", json.c_str()); // Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
} }
/**
* Verarbeitet Batteriestands-Nachrichten von Buttons, erkennt den Button-Typ,
* berechnet den Ladezustand und sendet ein JSON an das Frontend.
*/
void handleBatteryTopic(const char *topic, const char *payload) { void handleBatteryTopic(const char *topic, const char *payload) {
int batteryLevel = 0; int batteryLevel = 0;
String topicStr(topic); String topicStr(topic);
@@ -194,6 +212,10 @@ void handleBatteryTopic(const char *topic, const char *payload) {
// Serial.printf("Published heartbeat JSON: %s\n", json.c_str()); // Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
} }
/**
* Verarbeitet RFID-Lese-Nachrichten von Buttons, prüft Userdaten,
* sendet diese ggf. als JSON an das Frontend.
*/
void readRFIDfromButton(const char *topic, const char *payload) { void readRFIDfromButton(const char *topic, const char *payload) {
// Create a JSON document to hold the button press data // Create a JSON document to hold the button press data
StaticJsonDocument<256> doc; StaticJsonDocument<256> doc;
@@ -270,6 +292,10 @@ void readRFIDfromButton(const char *topic, const char *payload) {
} }
} }
/**
* Initialisiert den MQTT-Server, richtet Subscriptions und Callback-Handler
* ein.
*/
void setupMqttServer() { void setupMqttServer() {
// Set up the MQTT server with the desired port // Set up the MQTT server with the desired port
@@ -296,6 +322,10 @@ void setupMqttServer() {
Serial.println("MQTT server started on port 1883"); Serial.println("MQTT server started on port 1883");
} }
/**
* Muss regelmäßig im Loop aufgerufen werden, damit der MQTT-Server arbeitet.
* Sendet außerdem alle 5 Sekunden einen Zeit-Sync.
*/
void loopMqttServer() { void loopMqttServer() {
mqtt.loop(); mqtt.loop();
@@ -309,12 +339,18 @@ void loopMqttServer() {
} }
} }
/**
* Sendet eine einfache Textnachricht an ein MQTT-Topic.
*/
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);
} }
/**
* Sendet ein JSON-Dokument als Nachricht an ein MQTT-Topic.
*/
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);

View File

@@ -41,8 +41,8 @@ struct UserData {
bool exists; bool exists;
}; };
// UserData checkUser(const String& uid) is defined only once to avoid // Prüft, ob ein Benutzer mit der angegebenen UID in der Datenbank existiert und
// redefinition errors. // gibt dessen Daten zurück.
UserData checkUser(const String &uid) { UserData checkUser(const String &uid) {
UserData userData = {"", "", "", 0, false}; UserData userData = {"", "", "", 0, false};
@@ -85,7 +85,7 @@ UserData checkUser(const String &uid) {
return userData; return userData;
} }
// Function to enter user data into the database // Fügt einen neuen Benutzer mit den angegebenen Daten in die Datenbank ein.
bool enterUserData(const String &uid, const String &firstname, bool enterUserData(const String &uid, const String &firstname,
const String &lastname, const String &geburtsdatum, const String &lastname, const String &geburtsdatum,
int alter) { int alter) {
@@ -123,6 +123,7 @@ bool enterUserData(const String &uid, const String &firstname,
} }
} }
// Holt alle Standorte aus der Datenbank und gibt sie als JSON-Dokument zurück.
JsonDocument getAllLocations() { JsonDocument getAllLocations() {
JsonDocument locations; // Allocate memory for the JSON document JsonDocument locations; // Allocate memory for the JSON document
@@ -152,11 +153,12 @@ JsonDocument getAllLocations() {
return locations; // Return the populated JSON document return locations; // Return the populated JSON document
} }
// Keep this for backward compatibility // Prüft, ob ein Benutzer mit der angegebenen UID existiert
// (Kompatibilitätsfunktion).
bool userExists(const String &uid) { return checkUser(uid).exists; } bool userExists(const String &uid) { return checkUser(uid).exists; }
// Routes from the Frontend into here and then into DB backend. // Richtet die HTTP-Routen für die Backend-API ein (z.B. Health-Check, User- und
// Location-Abfragen).
void setupBackendRoutes(AsyncWebServer &server) { void setupBackendRoutes(AsyncWebServer &server) {
server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) { server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) {

View File

@@ -5,7 +5,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
const char *ssidAP; const char *ssidAP;
const char *passwordAP = nullptr; const char *passwordAP = nullptr;

View File

@@ -4,7 +4,6 @@
#include <MFRC522.h> #include <MFRC522.h>
#include <SPI.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
@@ -22,6 +21,7 @@ unsigned long rfidReadStartTime = 0;
const unsigned long RFID_READ_TIMEOUT = const unsigned long RFID_READ_TIMEOUT =
10000; // 10 Sekunden Timeout für API Requests 10000; // 10 Sekunden Timeout für API Requests
// Initialisiert den RFID-Reader und das SPI-Interface.
void setupRFID() { void setupRFID() {
// SPI und RFID initialisieren // SPI und RFID initialisieren
@@ -32,6 +32,8 @@ void setupRFID() {
// Reader details // Reader details
} }
// Liest automatisch eine RFID-Karte ein und blockiert die UID für eine
// bestimmte Zeit.
void handleAutomaticRFID() { void handleAutomaticRFID() {
if (!mfrc522.PICC_IsNewCardPresent()) { if (!mfrc522.PICC_IsNewCardPresent()) {
return; return;
@@ -83,6 +85,8 @@ void handleAutomaticRFID() {
} }
// Neue Funktion für API-basiertes RFID Lesen // Neue Funktion für API-basiertes RFID Lesen
// Liest eine RFID-Karte im API-Modus ein (für Web-Requests).
void handleAPIRFIDRead() { void handleAPIRFIDRead() {
unsigned long currentTime = millis(); unsigned long currentTime = millis();
@@ -130,6 +134,8 @@ void handleAPIRFIDRead() {
} }
// API Funktion: RFID Lesevorgang starten // API Funktion: RFID Lesevorgang starten
// Startet einen neuen RFID-Lesevorgang über die API.
void startRFIDRead() { void startRFIDRead() {
Serial.println("RFID API Lesevorgang gestartet..."); Serial.println("RFID API Lesevorgang gestartet...");
rfidReadRequested = true; rfidReadRequested = true;
@@ -139,14 +145,18 @@ void startRFIDRead() {
} }
// API Funktion: Prüfen ob Lesevorgang abgeschlossen // API Funktion: Prüfen ob Lesevorgang abgeschlossen
// Prüft, ob der aktuelle RFID-Lesevorgang abgeschlossen ist.
bool isRFIDReadComplete() { return !rfidReadRequested; } bool isRFIDReadComplete() { return !rfidReadRequested; }
// API Funktion: Ergebnis des Lesevorgangs abrufen // API Funktion: Ergebnis des Lesevorgangs abrufen
// Gibt das Ergebnis des letzten RFID-Lesevorgangs zurück.
String getRFIDReadResult(bool &success) { String getRFIDReadResult(bool &success) {
success = rfidReadSuccess; success = rfidReadSuccess;
return lastReadUID; return lastReadUID;
} }
// Richtet die HTTP-API-Routen für RFID-Operationen ein.
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");
@@ -240,6 +250,8 @@ void setupRFIDRoute(AsyncWebServer &server) {
} }
// API Funktion: RFID Reader Status prüfen // API Funktion: RFID Reader Status prüfen
// Prüft, ob der RFID-Reader korrekt funktioniert und gibt den Status zurück.
bool checkRFIDReaderStatus() { bool checkRFIDReaderStatus() {
byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
@@ -255,6 +267,8 @@ bool checkRFIDReaderStatus() {
} }
// Hilfsfunktion: Blockierte UIDs aufräumen // Hilfsfunktion: Blockierte UIDs aufräumen
// Entfernt UIDs aus der Blockliste, deren Blockdauer abgelaufen ist.
void cleanupBlockedUIDs() { void cleanupBlockedUIDs() {
unsigned long currentTime = millis(); unsigned long currentTime = millis();
@@ -268,6 +282,7 @@ void cleanupBlockedUIDs() {
} }
} }
// Hauptschleife für das RFID-Handling (automatisch und API-basiert).
void loopRFID() { void loopRFID() {
// Originale Funktionalität für automatisches Lesen // Originale Funktionalität für automatisches Lesen
if (!rfidReadRequested) { if (!rfidReadRequested) {

View File

@@ -6,11 +6,13 @@
unsigned long lastLedBlink = 0; unsigned long lastLedBlink = 0;
bool ledState = false; bool ledState = false;
// Initialisiert die Status-LED (setzt Pin-Modus und schaltet sie aus).
void setupLED() { void setupLED() {
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // LED aus digitalWrite(LED_PIN, LOW); // LED aus
} }
// Steuert die Status-LED je nach übergebenem Blinkmuster (Statusanzeige).
void updateStatusLED(int blinkPattern) { void updateStatusLED(int blinkPattern) {
unsigned long currentTime = millis(); unsigned long currentTime = millis();

View File

@@ -8,7 +8,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
RTC_PCF8523 rtc; RTC_PCF8523 rtc;
// Globale Zeitvariablen // Globale Zeitvariablen
@@ -17,12 +16,14 @@ struct timezone tz;
time_t now; time_t now;
struct tm timeinfo; struct tm timeinfo;
// Prototypen für Zeit-Management-Funktionen // Initialisiert die Zeit-API und richtet die HTTP-Endpunkte ein.
void setupTimeAPI(AsyncWebServer &server); void setupTimeAPI(AsyncWebServer &server);
// Gibt die aktuelle Zeit als JSON-String zurück.
String getCurrentTimeJSON(); String getCurrentTimeJSON();
// Setzt die Systemzeit auf den angegebenen Zeitstempel (Sekunden seit 1970).
bool setSystemTime(long timestamp); bool setSystemTime(long timestamp);
// Hilfsfunktionen für Zeit-Management // Hilfsfunktion: Gibt die aktuelle Zeit als JSON-String zurück.
String getCurrentTimeJSON() { String getCurrentTimeJSON() {
gettimeofday(&tv, &tz); gettimeofday(&tv, &tz);
now = tv.tv_sec; now = tv.tv_sec;
@@ -48,6 +49,7 @@ String getCurrentTimeJSON() {
return response; return response;
} }
// Hilfsfunktion: Setzt die Systemzeit auf den angegebenen Zeitstempel.
bool setSystemTime(long timestamp) { bool setSystemTime(long timestamp) {
struct timeval tv; struct timeval tv;
tv.tv_sec = timestamp; tv.tv_sec = timestamp;
@@ -62,6 +64,7 @@ bool setSystemTime(long timestamp) {
} }
} }
// Initialisiert die Zeit-API und richtet die HTTP-Endpunkte ein.
void setupTimeAPI(AsyncWebServer &server) { void setupTimeAPI(AsyncWebServer &server) {
// setupRTC(); // setupRTC();
@@ -185,6 +188,7 @@ void setupTimeAPI(AsyncWebServer &server) {
} }
// Hilfsfunktion: Zeit-Validierung // Hilfsfunktion: Zeit-Validierung
// Prüft, ob die übergebenen Datums- und Zeitwerte gültig sind.
bool isValidDateTime(int year, int month, int day, int hour, int minute, bool isValidDateTime(int year, int month, int day, int hour, int minute,
int second) { int second) {
if (year < 2020 || year > 2099) if (year < 2020 || year > 2099)
@@ -211,6 +215,7 @@ bool isValidDateTime(int year, int month, int day, int hour, int minute,
return day <= daysInMonth[month - 1]; return day <= daysInMonth[month - 1];
} }
// Gibt den aktuellen Zeitstempel in Millisekunden seit 1970 zurück.
uint64_t getCurrentTimestampMs() { uint64_t getCurrentTimestampMs() {
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);

View File

@@ -10,15 +10,14 @@ void sendMQTTMessage(const char *topic, const char *message);
#include <SPIFFS.h> #include <SPIFFS.h>
#include <esp_wifi.h> #include <esp_wifi.h>
#include "communication.h" #include "communication.h"
#include <buttonassigh.h> #include <buttonassigh.h>
#include <wificlass.h> #include <wificlass.h>
AsyncWebServer server(80); AsyncWebServer server(80);
AsyncWebSocket ws("/ws"); AsyncWebSocket ws("/ws");
// Richtet alle HTTP-Routen für den Webserver ein (API und statische Dateien).
void setupRoutes() { void setupRoutes() {
// Web Server Routes // Web Server Routes
@@ -281,6 +280,7 @@ void setupRoutes() {
Serial.println("Web Server gestartet"); Serial.println("Web Server gestartet");
} }
// Initialisiert den WebSocket-Server und definiert die Event-Handler.
void setupWebSocket() { void setupWebSocket() {
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client, ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) { AwsEventType type, void *arg, uint8_t *data, size_t len) {
@@ -295,10 +295,12 @@ void setupWebSocket() {
}); });
} }
// Sendet eine Nachricht an alle verbundenen WebSocket-Clients (Frontend).
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
} }
// Bereinigt getrennte WebSocket-Clients (sollte regelmäßig aufgerufen werden).
void loopWebSocket() { void loopWebSocket() {
ws.cleanupClients(); // Clean up disconnected clients ws.cleanupClients(); // Clean up disconnected clients
} }

View File

@@ -6,17 +6,16 @@
#include <esp_now.h> #include <esp_now.h>
#include <esp_wifi.h> #include <esp_wifi.h>
#include "licenceing.h" #include "licenceing.h"
#include "master.h" #include "master.h"
String uniqueSSID; String uniqueSSID;
PrettyOTA OTAUpdates; PrettyOTA OTAUpdates;
String getUniqueSSID(); String getUniqueSSID();
// Initialisiert das WLAN als Access Point oder Station und startet mDNS/OTA.
void setupWifi() { void setupWifi() {
uniqueSSID = getUniqueSSID(); uniqueSSID = getUniqueSSID();
@@ -69,6 +68,7 @@ void setupWifi() {
} }
} }
// Initialisiert das OTA-Update-System (PrettyOTA) für Firmware-Updates.
void setupOTA(AsyncWebServer *server) { void setupOTA(AsyncWebServer *server) {
// Initialize PrettyOTA // Initialize PrettyOTA
OTAUpdates.Begin(server); OTAUpdates.Begin(server);
@@ -83,6 +83,7 @@ void setupOTA(AsyncWebServer *server) {
PRETTY_OTA_SET_CURRENT_BUILD_TIME_AND_DATE(); PRETTY_OTA_SET_CURRENT_BUILD_TIME_AND_DATE();
} }
// Generiert eine eindeutige SSID auf Basis der MAC-Adresse.
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);