From 2bd47a10a58f5ec2130c21a55ab1f1bb80713dd2 Mon Sep 17 00:00:00 2001 From: Carsten Graf Date: Fri, 11 Jul 2025 22:07:13 +0200 Subject: [PATCH] Anpassung Zeitmessung, Batterie Backend to Frontend --- src/communication.h | 68 +++++++++++++++++++++++++++++++++++++++++---- src/debug.h | 8 +++--- src/master.cpp | 40 +++++++++++++------------- src/master.h | 14 ++++++---- 4 files changed, 96 insertions(+), 34 deletions(-) diff --git a/src/communication.h b/src/communication.h index aea9d36..7dfb314 100644 --- a/src/communication.h +++ b/src/communication.h @@ -78,13 +78,13 @@ void readButtonJSON(const char * topic, const char * payload) { // Button-Zuordnung prüfen und entsprechende Aktion ausführen if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0 && (pressType == 2)) { - handleStart1(); + handleStart1(timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 && (pressType == 1)) { - handleStop1(); + handleStop1(timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 && (pressType == 2)) { - handleStart2(); + handleStart2(timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 1)) { - handleStop2(); + handleStop2(timestamp); } // Flash status LED to indicate received message @@ -134,6 +134,60 @@ void handleHeartbeatTopic(const char* topic, const char* payload) { //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) + uint64_t timestamp = millis(); + StaticJsonDocument<128> payloadDoc; + if (payload && strlen(payload) > 0 && deserializeJson(payloadDoc, payload) == DeserializationError::Ok) { + if (payloadDoc.containsKey("voltage")) { + timestamp = 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 < 3000) { + 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; @@ -219,9 +273,13 @@ void setupMqttServer() { //Serial.printf("Received message on topic '%s': %s\n", topic, payload); if (strncmp(topic, "aquacross/button/", 17) == 0) { readButtonJSON(topic, payload); - } else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) { + } + else if (strncmp(topic, "aquacross/button/rfid/", 22) == 0) { readRFIDfromButton(topic, payload); // Handle RFID read messages + } + else if (strncmp(topic, "aquacross/battery/", 17) == 0) { + handleBatteryTopic(topic, payload); } else if (strncmp(topic, "heartbeat/alive/", 16) == 0) { handleHeartbeatTopic(topic, payload); diff --git a/src/debug.h b/src/debug.h index 0607629..2210b7b 100644 --- a/src/debug.h +++ b/src/debug.h @@ -18,22 +18,22 @@ void setupDebugAPI(AsyncWebServer& server) { //DEBUG server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request){ - handleStart1(); + handleStart1(0); request->send(200, "text/plain", "handleStart1() called"); }); server.on("/api/debug/stop1", HTTP_GET, [](AsyncWebServerRequest *request){ - handleStop1(); + handleStop1(0); request->send(200, "text/plain", "handleStop1() called"); }); server.on("/api/debug/start2", HTTP_GET, [](AsyncWebServerRequest *request){ - handleStart2(); + handleStart2(0); request->send(200, "text/plain", "handleStart2() called"); }); server.on("/api/debug/stop2", HTTP_GET, [](AsyncWebServerRequest *request){ - handleStop2(); + handleStop2(0); request->send(200, "text/plain", "handleStop2() called"); }); diff --git a/src/master.cpp b/src/master.cpp index 9c97050..77c21a2 100644 --- a/src/master.cpp +++ b/src/master.cpp @@ -24,52 +24,54 @@ const char* firmwareversion = "1.0.0"; // Version der Firmware -void handleStart1() { +void handleStart1(uint64_t timestamp = 0) { if (!timerData.isRunning1 && timerData.isReady1) { - timerData.isReady1 = false; // Setze auf "Nicht bereit" bis Stopp - timerData.startTime1 = millis(); + timerData.isReady1 = false; + timerData.startTime1 = (timestamp > 0) ? timestamp : millis(); + timerData.localStartTime1 = millis(); // Set local start time timerData.isRunning1 = true; timerData.endTime1 = 0; Serial.println("Bahn 1 gestartet"); } } -void handleStop1() { +void handleStop1(uint64_t timestamp = 0) { if (timerData.isRunning1) { - timerData.endTime1 = millis(); + timerData.endTime1 = (timestamp > 0) ? timestamp : millis(); + timerData.finishedSince1 = millis(); // Set finished time timerData.isRunning1 = false; unsigned long currentTime = timerData.endTime1 - timerData.startTime1; - + if (timerData.bestTime1 == 0 || currentTime < timerData.bestTime1) { timerData.bestTime1 = currentTime; saveBestTimes(); } - timerData.finishedSince1 = millis(); Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime/1000.0) + "s"); } } -void handleStart2() { +void handleStart2(uint64_t timestamp = 0) { if (!timerData.isRunning2 && timerData.isReady2) { - timerData.isReady2 = false; // Setze auf "Nicht bereit" bis Stopp - timerData.startTime2 = millis(); + timerData.isReady2 = false; + timerData.startTime2 = (timestamp > 0) ? timestamp : millis(); + timerData.localStartTime2 = millis(); // Set local start time timerData.isRunning2 = true; timerData.endTime2 = 0; Serial.println("Bahn 2 gestartet"); } } -void handleStop2() { +void handleStop2(uint64_t timestamp = 0) { if (timerData.isRunning2) { - timerData.endTime2 = millis(); + timerData.endTime2 = (timestamp > 0) ? timestamp : millis(); + timerData.finishedSince2 = millis(); // Set finished time timerData.isRunning2 = false; unsigned long currentTime = timerData.endTime2 - timerData.startTime2; - + if (timerData.bestTime2 == 0 || currentTime < timerData.bestTime2) { timerData.bestTime2 = currentTime; saveBestTimes(); } - timerData.finishedSince2 = millis(); Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime/1000.0) + "s"); } } @@ -77,13 +79,13 @@ void handleStop2() { void checkAutoReset() { unsigned long currentTime = millis(); - if (timerData.isRunning1 && (currentTime - timerData.startTime1 > maxTimeBeforeReset)) { + if (timerData.isRunning1 && (currentTime - timerData.localStartTime1 > maxTimeBeforeReset)) { timerData.isRunning1 = false; timerData.startTime1 = 0; Serial.println("Bahn 1 automatisch zurückgesetzt"); } - if (timerData.isRunning2 && (currentTime - timerData.startTime2 > maxTimeBeforeReset)) { + if (timerData.isRunning2 && (currentTime - timerData.localStartTime2 > maxTimeBeforeReset)) { timerData.isRunning2 = false; timerData.startTime2 = 0; Serial.println("Bahn 2 automatisch zurückgesetzt"); @@ -91,7 +93,7 @@ void checkAutoReset() { // Automatischer Reset nach 10 Sekunden "Beendet" if (!timerData.isRunning1 && timerData.endTime1 > 0 && timerData.finishedSince1 > 0) { - if (currentTime - timerData.finishedSince1 > maxTimeDisplay) { + if (millis() - timerData.finishedSince1 > maxTimeDisplay) { timerData.startTime1 = 0; timerData.endTime1 = 0; timerData.finishedSince1 = 0; @@ -226,7 +228,7 @@ String getTimerDataJSON() { unsigned long currentTime = millis(); // Bahn 1 if (timerData.isRunning1) { - doc["time1"] = (currentTime - timerData.startTime1) / 1000.0; + doc["time1"] = (currentTime - timerData.localStartTime1) / 1000.0; doc["status1"] = "running"; } else if (timerData.endTime1 > 0) { doc["time1"] = (timerData.endTime1 - timerData.startTime1) / 1000.0; @@ -238,7 +240,7 @@ String getTimerDataJSON() { // Bahn 2 if (timerData.isRunning2) { - doc["time2"] = (currentTime - timerData.startTime2) / 1000.0; + doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0; doc["status2"] = "running"; } else if (timerData.endTime2 > 0) { doc["time2"] = (timerData.endTime2 - timerData.startTime2) / 1000.0; diff --git a/src/master.h b/src/master.h index eadfc40..234441b 100644 --- a/src/master.h +++ b/src/master.h @@ -15,14 +15,16 @@ char* passwordSTA = nullptr; struct TimerData { unsigned long startTime1 = 0; unsigned long startTime2 = 0; + unsigned long localStartTime1 = 0; + unsigned long localStartTime2 = 0; + unsigned long finishedSince1 = 0; + unsigned long finishedSince2 = 0; unsigned long endTime1 = 0; unsigned long endTime2 = 0; unsigned long bestTime1 = 0; unsigned long bestTime2 = 0; bool isRunning1 = false; bool isRunning2 = false; - unsigned long finishedSince1 = 0; - unsigned long finishedSince2 = 0; bool isReady1 = true; // Status für Bahn 1 bool isReady2 = true; // Status für Bahn 2 }; @@ -56,10 +58,10 @@ String masterlocation; void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len); void handleLearningMode(const uint8_t* mac); void handleStartLearning(); -void handleStart1(); -void handleStop1(); -void handleStart2(); -void handleStop2(); +void handleStart1(uint64_t timestamp); +void handleStop1(uint64_t timestamp); +void handleStart2(uint64_t timestamp); +void handleStop2(uint64_t timestamp); void checkAutoReset(); void saveButtonConfig(); void loadButtonConfig();