Comments und add licence
This commit is contained in:
26
LICENCE.md
Normal file
26
LICENCE.md
Normal 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.
|
||||
14
TODO.md
14
TODO.md
@@ -1,19 +1,17 @@
|
||||
- KOMPLETTES Messageing System auf MQTT Server und Broker umstellen. DONE
|
||||
- Testen wie zuverlässig das ist
|
||||
|
||||
|
||||
|
||||
- message system überarbeiten. Sehr unzuverlässig mit dem peering DONE jetzt MQTT
|
||||
- Uhrzeit abfragen (Eingabe der Zeitzone) DONE
|
||||
- Sync der Buttons mit echtzeit
|
||||
- Sync der Buttons mit echtzeit DONE
|
||||
- implementierung einer RTC
|
||||
|
||||
v2.0
|
||||
- ADD Hotspot Manager to connect to a Wifi
|
||||
- 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
|
||||
|
||||
- ADD option point for location (read from online table and select the location via dropdown)
|
||||
- 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)
|
||||
enables the Wifimanager to connect 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
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// Aquacross Timer - ESP32 Master (Webserver + ESP-NOW + Anlernmodus)
|
||||
#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) {
|
||||
// Prüfen ob MAC bereits einem anderen Button zugewiesen ist
|
||||
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() {
|
||||
learningMode = true;
|
||||
|
||||
@@ -82,6 +86,7 @@ void handleStartLearning() {
|
||||
assignedButtons, learningStep);
|
||||
}
|
||||
|
||||
// Erstellt ein JSON mit Status und aktuellem Lernschritt des Lernmodus
|
||||
void handleLearningStatus() {
|
||||
DynamicJsonDocument doc(256);
|
||||
doc["active"] = learningMode;
|
||||
@@ -91,6 +96,7 @@ void handleLearningStatus() {
|
||||
serializeJson(doc, response);
|
||||
}
|
||||
|
||||
// Setzt alle Button-Zuweisungen zurück und speichert die Konfiguration
|
||||
void unlearnButton() {
|
||||
|
||||
memset(buttonConfigs.start1.mac, 0, 6);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
|
||||
#include <PicoMQTT.h>
|
||||
|
||||
#include "buttonassigh.h"
|
||||
@@ -15,18 +14,24 @@
|
||||
#include "webserverrouter.h"
|
||||
#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 {
|
||||
uint64_t lastMessageTimestamp; // Timestamp from the device
|
||||
uint64_t lastLocalTimestamp; // Our local timestamp when message was received
|
||||
uint64_t drift; // Calculated drift
|
||||
uint64_t lastMessageTimestamp;
|
||||
uint64_t lastLocalTimestamp;
|
||||
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;
|
||||
|
||||
// Datenstruktur für ESP-NOW Nachrichten
|
||||
// Datenstruktur für ESP-NOW Nachrichten
|
||||
/**
|
||||
* Datenstruktur für eine Button-Nachricht (optional, falls benötigt)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t messageType;
|
||||
uint8_t buttonId;
|
||||
@@ -35,8 +40,13 @@ typedef struct {
|
||||
char messageId[33]; // 32 hex chars + null terminator for 128-bit ID
|
||||
} ButtonMessage;
|
||||
|
||||
// MQTT-Server-Instanz
|
||||
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) {
|
||||
|
||||
const char *prefix = "aquacross/button/";
|
||||
@@ -94,6 +104,10 @@ void readButtonJSON(const char *topic, const char *payload) {
|
||||
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) {
|
||||
// Topic-Format: heartbeat/alive/CC:DB:A7:2F:95:08
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
int batteryLevel = 0;
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// Create a JSON document to hold the button press data
|
||||
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() {
|
||||
|
||||
// Set up the MQTT server with the desired port
|
||||
@@ -296,6 +322,10 @@ void setupMqttServer() {
|
||||
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() {
|
||||
mqtt.loop();
|
||||
|
||||
@@ -309,12 +339,18 @@ void loopMqttServer() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine einfache Textnachricht an ein MQTT-Topic.
|
||||
*/
|
||||
void sendMQTTMessage(const char *topic, const char *message) {
|
||||
// Publish a message to the specified topic
|
||||
mqtt.publish(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) {
|
||||
String jsonString;
|
||||
serializeJson(doc, jsonString);
|
||||
|
||||
@@ -41,8 +41,8 @@ struct UserData {
|
||||
bool exists;
|
||||
};
|
||||
|
||||
// UserData checkUser(const String& uid) is defined only once to avoid
|
||||
// redefinition errors.
|
||||
// Prüft, ob ein Benutzer mit der angegebenen UID in der Datenbank existiert und
|
||||
// gibt dessen Daten zurück.
|
||||
UserData checkUser(const String &uid) {
|
||||
|
||||
UserData userData = {"", "", "", 0, false};
|
||||
@@ -85,7 +85,7 @@ UserData checkUser(const String &uid) {
|
||||
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,
|
||||
const String &lastname, const String &geburtsdatum,
|
||||
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 locations; // Allocate memory for the JSON document
|
||||
|
||||
@@ -152,11 +153,12 @@ JsonDocument getAllLocations() {
|
||||
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; }
|
||||
|
||||
// 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) {
|
||||
|
||||
server.on("/api/health", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
const char *ssidAP;
|
||||
const char *passwordAP = nullptr;
|
||||
|
||||
|
||||
17
src/rfid.h
17
src/rfid.h
@@ -4,7 +4,6 @@
|
||||
#include <MFRC522.h>
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
// RFID Konfiguration
|
||||
#define RST_PIN 21 // Configurable, see typical pin layout above
|
||||
#define SS_PIN 5 // Configurable, see typical pin layout above
|
||||
@@ -22,6 +21,7 @@ unsigned long rfidReadStartTime = 0;
|
||||
const unsigned long RFID_READ_TIMEOUT =
|
||||
10000; // 10 Sekunden Timeout für API Requests
|
||||
|
||||
// Initialisiert den RFID-Reader und das SPI-Interface.
|
||||
void setupRFID() {
|
||||
|
||||
// SPI und RFID initialisieren
|
||||
@@ -32,6 +32,8 @@ void setupRFID() {
|
||||
// Reader details
|
||||
}
|
||||
|
||||
// Liest automatisch eine RFID-Karte ein und blockiert die UID für eine
|
||||
// bestimmte Zeit.
|
||||
void handleAutomaticRFID() {
|
||||
if (!mfrc522.PICC_IsNewCardPresent()) {
|
||||
return;
|
||||
@@ -83,6 +85,8 @@ void handleAutomaticRFID() {
|
||||
}
|
||||
|
||||
// Neue Funktion für API-basiertes RFID Lesen
|
||||
|
||||
// Liest eine RFID-Karte im API-Modus ein (für Web-Requests).
|
||||
void handleAPIRFIDRead() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
@@ -130,6 +134,8 @@ void handleAPIRFIDRead() {
|
||||
}
|
||||
|
||||
// API Funktion: RFID Lesevorgang starten
|
||||
|
||||
// Startet einen neuen RFID-Lesevorgang über die API.
|
||||
void startRFIDRead() {
|
||||
Serial.println("RFID API Lesevorgang gestartet...");
|
||||
rfidReadRequested = true;
|
||||
@@ -139,14 +145,18 @@ void startRFIDRead() {
|
||||
}
|
||||
|
||||
// API Funktion: Prüfen ob Lesevorgang abgeschlossen
|
||||
|
||||
// Prüft, ob der aktuelle RFID-Lesevorgang abgeschlossen ist.
|
||||
bool isRFIDReadComplete() { return !rfidReadRequested; }
|
||||
|
||||
// API Funktion: Ergebnis des Lesevorgangs abrufen
|
||||
// Gibt das Ergebnis des letzten RFID-Lesevorgangs zurück.
|
||||
String getRFIDReadResult(bool &success) {
|
||||
success = rfidReadSuccess;
|
||||
return lastReadUID;
|
||||
}
|
||||
|
||||
// Richtet die HTTP-API-Routen für RFID-Operationen ein.
|
||||
void setupRFIDRoute(AsyncWebServer &server) {
|
||||
server.on("/api/rfid/read", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
Serial.println("api/rfid/read");
|
||||
@@ -240,6 +250,8 @@ void setupRFIDRoute(AsyncWebServer &server) {
|
||||
}
|
||||
|
||||
// API Funktion: RFID Reader Status prüfen
|
||||
|
||||
// Prüft, ob der RFID-Reader korrekt funktioniert und gibt den Status zurück.
|
||||
bool checkRFIDReaderStatus() {
|
||||
byte version = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
|
||||
|
||||
@@ -255,6 +267,8 @@ bool checkRFIDReaderStatus() {
|
||||
}
|
||||
|
||||
// Hilfsfunktion: Blockierte UIDs aufräumen
|
||||
|
||||
// Entfernt UIDs aus der Blockliste, deren Blockdauer abgelaufen ist.
|
||||
void cleanupBlockedUIDs() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
@@ -268,6 +282,7 @@ void cleanupBlockedUIDs() {
|
||||
}
|
||||
}
|
||||
|
||||
// Hauptschleife für das RFID-Handling (automatisch und API-basiert).
|
||||
void loopRFID() {
|
||||
// Originale Funktionalität für automatisches Lesen
|
||||
if (!rfidReadRequested) {
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
unsigned long lastLedBlink = 0;
|
||||
bool ledState = false;
|
||||
|
||||
// Initialisiert die Status-LED (setzt Pin-Modus und schaltet sie aus).
|
||||
void setupLED() {
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW); // LED aus
|
||||
}
|
||||
|
||||
// Steuert die Status-LED je nach übergebenem Blinkmuster (Statusanzeige).
|
||||
void updateStatusLED(int blinkPattern) {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
RTC_PCF8523 rtc;
|
||||
|
||||
// Globale Zeitvariablen
|
||||
@@ -17,12 +16,14 @@ struct timezone tz;
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
|
||||
// Prototypen für Zeit-Management-Funktionen
|
||||
// Initialisiert die Zeit-API und richtet die HTTP-Endpunkte ein.
|
||||
void setupTimeAPI(AsyncWebServer &server);
|
||||
// Gibt die aktuelle Zeit als JSON-String zurück.
|
||||
String getCurrentTimeJSON();
|
||||
// Setzt die Systemzeit auf den angegebenen Zeitstempel (Sekunden seit 1970).
|
||||
bool setSystemTime(long timestamp);
|
||||
|
||||
// Hilfsfunktionen für Zeit-Management
|
||||
// Hilfsfunktion: Gibt die aktuelle Zeit als JSON-String zurück.
|
||||
String getCurrentTimeJSON() {
|
||||
gettimeofday(&tv, &tz);
|
||||
now = tv.tv_sec;
|
||||
@@ -48,6 +49,7 @@ String getCurrentTimeJSON() {
|
||||
return response;
|
||||
}
|
||||
|
||||
// Hilfsfunktion: Setzt die Systemzeit auf den angegebenen Zeitstempel.
|
||||
bool setSystemTime(long timestamp) {
|
||||
struct timeval tv;
|
||||
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) {
|
||||
|
||||
// setupRTC();
|
||||
@@ -185,6 +188,7 @@ void setupTimeAPI(AsyncWebServer &server) {
|
||||
}
|
||||
|
||||
// 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,
|
||||
int second) {
|
||||
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];
|
||||
}
|
||||
|
||||
// Gibt den aktuellen Zeitstempel in Millisekunden seit 1970 zurück.
|
||||
uint64_t getCurrentTimestampMs() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
@@ -10,15 +10,14 @@ void sendMQTTMessage(const char *topic, const char *message);
|
||||
#include <SPIFFS.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
|
||||
#include "communication.h"
|
||||
#include <buttonassigh.h>
|
||||
#include <wificlass.h>
|
||||
|
||||
|
||||
AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
|
||||
// Richtet alle HTTP-Routen für den Webserver ein (API und statische Dateien).
|
||||
void setupRoutes() {
|
||||
// Web Server Routes
|
||||
|
||||
@@ -281,6 +280,7 @@ void setupRoutes() {
|
||||
Serial.println("Web Server gestartet");
|
||||
}
|
||||
|
||||
// Initialisiert den WebSocket-Server und definiert die Event-Handler.
|
||||
void setupWebSocket() {
|
||||
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client,
|
||||
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) {
|
||||
ws.textAll(message); // Send the message to all connected clients
|
||||
}
|
||||
|
||||
// Bereinigt getrennte WebSocket-Clients (sollte regelmäßig aufgerufen werden).
|
||||
void loopWebSocket() {
|
||||
ws.cleanupClients(); // Clean up disconnected clients
|
||||
}
|
||||
|
||||
@@ -6,17 +6,16 @@
|
||||
#include <esp_now.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
|
||||
#include "licenceing.h"
|
||||
#include "master.h"
|
||||
|
||||
|
||||
String uniqueSSID;
|
||||
|
||||
PrettyOTA OTAUpdates;
|
||||
|
||||
String getUniqueSSID();
|
||||
|
||||
// Initialisiert das WLAN als Access Point oder Station und startet mDNS/OTA.
|
||||
void setupWifi() {
|
||||
|
||||
uniqueSSID = getUniqueSSID();
|
||||
@@ -69,6 +68,7 @@ void setupWifi() {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialisiert das OTA-Update-System (PrettyOTA) für Firmware-Updates.
|
||||
void setupOTA(AsyncWebServer *server) {
|
||||
// Initialize PrettyOTA
|
||||
OTAUpdates.Begin(server);
|
||||
@@ -83,6 +83,7 @@ void setupOTA(AsyncWebServer *server) {
|
||||
PRETTY_OTA_SET_CURRENT_BUILD_TIME_AND_DATE();
|
||||
}
|
||||
|
||||
// Generiert eine eindeutige SSID auf Basis der MAC-Adresse.
|
||||
String getUniqueSSID() {
|
||||
uint8_t mac[6];
|
||||
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
||||
|
||||
Reference in New Issue
Block a user