#pragma once #include #include "master.h" #include #include #include "statusled.h" #include "timesync.h" #include "buttonassigh.h" #include "helper.h" #include "debug.h" #include #include "databasebackend.h" #include "webserverrouter.h" struct TimestampData { uint64_t lastMessageTimestamp; // Timestamp from the device uint64_t lastLocalTimestamp; // Our local timestamp when message was received uint64_t drift; // Calculated drift }; // Map to store timestamp data for each MAC address std::map deviceTimestamps; // Datenstruktur für ESP-NOW Nachrichten // Datenstruktur für ESP-NOW Nachrichten typedef struct { uint8_t messageType; uint8_t buttonId; int buttonPressed; uint32_t timestamp; char messageId[33]; // 32 hex chars + null terminator for 128-bit ID } ButtonMessage; PicoMQTT::Server mqtt; void readButtonJSON(const char * topic, const char * payload) { if(strcmp(topic, "aquacross/button/press") == 0){ // Create a JSON document to parse the incoming message JsonDocument doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print("JSON parsing failed: "); Serial.println(error.c_str()); return; } // Extract values from JSON int pressType = doc["type"] | 0; const char* buttonId = doc["buttonmac"] | "unknown"; uint64_t timestamp = doc["timestamp"] | 0; // Print received data Serial.printf("Button Press Received:\n"); Serial.printf(" Type: %d\n", pressType); Serial.printf(" Button MAC: %s\n", buttonId); Serial.printf(" Timestamp: %llu\n", timestamp); auto macBytes = macStringToBytes(buttonId); 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(); } else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 && (pressType == 1)) { handleStop1(); } else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 && (pressType == 2)) { handleStart2(); } else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 1)) { handleStop2(); } // Flash status LED to indicate received message updateStatusLED(3); } } void readRFIDfromButton(const char * topic, const char * payload) { // Create a JSON document to hold the button press data StaticJsonDocument<256> doc; DeserializationError error = deserializeJson(doc, payload); if (!error) { const char* mac = doc["buttonmac"] | "unknown"; const char* uid = doc["uid"] | "unknown"; Serial.printf("RFID Read from Button:\n"); Serial.printf(" Button MAC: %s\n", mac); Serial.printf(" UID: %s\n", uid); // Convert buttonmac to byte array for comparison auto macBytes = macStringToBytes(mac); // Check if the buttonmac matches buttonConfigs.start1.mac if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) { // Fetch user data UserData userData = checkUser(uid); if (userData.exists) { // Log user data Serial.printf("User found for start1: %s %s, Alter: %d\n", userData.firstname.c_str(), userData.lastname.c_str(), userData.alter); // Create JSON message to send to the frontend StaticJsonDocument<128> messageDoc; messageDoc["firstname"] = userData.firstname; messageDoc["lastname"] = userData.lastname; messageDoc["lane"] = "start1"; // Add lane information String message; serializeJson(messageDoc, message); // Push the message to the frontend pushUpdateToFrontend(message); Serial.printf("Pushed user data for start1 to frontend: %s\n", message.c_str()); } else { Serial.println("User not found for UID: " + String(uid)); } } // Check if the buttonmac matches buttonConfigs.start2.mac else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) { // Fetch user data UserData userData = checkUser(uid); if (userData.exists) { // Log user data Serial.printf("User found for start2: %s %s, Alter: %d\n", userData.firstname.c_str(), userData.lastname.c_str(), userData.alter); // Create JSON message to send to the frontend StaticJsonDocument<128> messageDoc; messageDoc["firstname"] = userData.firstname; messageDoc["lastname"] = userData.lastname; messageDoc["lane"] = "start2"; // Add lane information String message; serializeJson(messageDoc, message); // Push the message to the frontend pushUpdateToFrontend(message); Serial.printf("Pushed user data for start2 to frontend: %s\n", message.c_str()); } else { Serial.println("User not found for UID: " + String(uid)); } } else { Serial.println("Button MAC does not match start1.mac or start2.mac"); } } else { Serial.println("Failed to parse RFID JSON"); } } void setupMqttServer() { // Set up the MQTT server with the desired port // Subscribe to a topic pattern and attach a callback mqtt.subscribe("#", [](const char * topic, const char * payload) { //Message received callback //Serial.printf("Received message on topic '%s': %s\n", topic, payload); if (strcmp(topic, "aquacross/button/press") == 0) { readButtonJSON(topic, payload); } else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) { readRFIDfromButton(topic, payload); // Handle RFID read messages } updateStatusLED(3); }); // Start the MQTT server mqtt.begin(); Serial.println("MQTT server started on port 1883"); } void loopMqttServer() { mqtt.loop(); static unsigned long lastPublish = 0; if (millis() - lastPublish > 5000) { // Convert timestamp to string before publishing char timeStr[32]; snprintf(timeStr, sizeof(timeStr), "%llu", getCurrentTimestampMs()); mqtt.publish("sync/time", timeStr); lastPublish = millis(); } } 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); } void sendMQTTJSONMessage(const char * topic, const JsonDocument & doc) { String jsonString; serializeJson(doc, jsonString); // Publish the JSON string to the specified topic auto publish = mqtt.begin_publish(topic, measureJson(doc)); serializeJson(doc, publish); publish.send(); Serial.printf("Published JSON message to topic '%s': %s\n", topic, jsonString.c_str()); }