Anpassung Zeitmessung, Batterie Backend to Frontend

This commit is contained in:
Carsten Graf
2025-07-11 22:07:13 +02:00
parent 393a0b718b
commit 2bd47a10a5
4 changed files with 96 additions and 34 deletions

View File

@@ -78,13 +78,13 @@ void readButtonJSON(const char * topic, const char * payload) {
// Button-Zuordnung prüfen und entsprechende Aktion ausführen // Button-Zuordnung prüfen und entsprechende Aktion ausführen
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0 && (pressType == 2)) { 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)) { } 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)) { } 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)) { } else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 1)) {
handleStop2(); handleStop2(timestamp);
} }
// Flash status LED to indicate received message // 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()); //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) { 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;
@@ -219,10 +273,14 @@ void setupMqttServer() {
//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, "heartbeat/alive/", 16) == 0) { else if (strncmp(topic, "heartbeat/alive/", 16) == 0) {
handleHeartbeatTopic(topic, payload); handleHeartbeatTopic(topic, payload);
} }

View File

@@ -18,22 +18,22 @@ void setupDebugAPI(AsyncWebServer& server) {
//DEBUG //DEBUG
server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request){
handleStart1(); 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(); 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(); 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(); handleStop2(0);
request->send(200, "text/plain", "handleStop2() called"); request->send(200, "text/plain", "handleStop2() called");
}); });

View File

@@ -24,19 +24,21 @@
const char* firmwareversion = "1.0.0"; // Version der Firmware const char* firmwareversion = "1.0.0"; // Version der Firmware
void handleStart1() { void handleStart1(uint64_t timestamp = 0) {
if (!timerData.isRunning1 && timerData.isReady1) { if (!timerData.isRunning1 && timerData.isReady1) {
timerData.isReady1 = false; // Setze auf "Nicht bereit" bis Stopp timerData.isReady1 = false;
timerData.startTime1 = millis(); timerData.startTime1 = (timestamp > 0) ? timestamp : millis();
timerData.localStartTime1 = millis(); // Set local start time
timerData.isRunning1 = true; timerData.isRunning1 = true;
timerData.endTime1 = 0; timerData.endTime1 = 0;
Serial.println("Bahn 1 gestartet"); Serial.println("Bahn 1 gestartet");
} }
} }
void handleStop1() { void handleStop1(uint64_t timestamp = 0) {
if (timerData.isRunning1) { if (timerData.isRunning1) {
timerData.endTime1 = millis(); timerData.endTime1 = (timestamp > 0) ? timestamp : millis();
timerData.finishedSince1 = millis(); // Set finished time
timerData.isRunning1 = false; timerData.isRunning1 = false;
unsigned long currentTime = timerData.endTime1 - timerData.startTime1; unsigned long currentTime = timerData.endTime1 - timerData.startTime1;
@@ -44,24 +46,25 @@ void handleStop1() {
timerData.bestTime1 = currentTime; timerData.bestTime1 = currentTime;
saveBestTimes(); saveBestTimes();
} }
timerData.finishedSince1 = millis();
Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime/1000.0) + "s"); Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime/1000.0) + "s");
} }
} }
void handleStart2() { void handleStart2(uint64_t timestamp = 0) {
if (!timerData.isRunning2 && timerData.isReady2) { if (!timerData.isRunning2 && timerData.isReady2) {
timerData.isReady2 = false; // Setze auf "Nicht bereit" bis Stopp timerData.isReady2 = false;
timerData.startTime2 = millis(); timerData.startTime2 = (timestamp > 0) ? timestamp : millis();
timerData.localStartTime2 = millis(); // Set local start time
timerData.isRunning2 = true; timerData.isRunning2 = true;
timerData.endTime2 = 0; timerData.endTime2 = 0;
Serial.println("Bahn 2 gestartet"); Serial.println("Bahn 2 gestartet");
} }
} }
void handleStop2() { void handleStop2(uint64_t timestamp = 0) {
if (timerData.isRunning2) { if (timerData.isRunning2) {
timerData.endTime2 = millis(); timerData.endTime2 = (timestamp > 0) ? timestamp : millis();
timerData.finishedSince2 = millis(); // Set finished time
timerData.isRunning2 = false; timerData.isRunning2 = false;
unsigned long currentTime = timerData.endTime2 - timerData.startTime2; unsigned long currentTime = timerData.endTime2 - timerData.startTime2;
@@ -69,7 +72,6 @@ void handleStop2() {
timerData.bestTime2 = currentTime; timerData.bestTime2 = currentTime;
saveBestTimes(); saveBestTimes();
} }
timerData.finishedSince2 = millis();
Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime/1000.0) + "s"); Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime/1000.0) + "s");
} }
} }
@@ -77,13 +79,13 @@ void handleStop2() {
void checkAutoReset() { void checkAutoReset() {
unsigned long currentTime = millis(); unsigned long currentTime = millis();
if (timerData.isRunning1 && (currentTime - timerData.startTime1 > 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.startTime2 > 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");
@@ -91,7 +93,7 @@ void checkAutoReset() {
// 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 (currentTime - 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;
@@ -226,7 +228,7 @@ String getTimerDataJSON() {
unsigned long currentTime = millis(); unsigned long currentTime = millis();
// Bahn 1 // Bahn 1
if (timerData.isRunning1) { if (timerData.isRunning1) {
doc["time1"] = (currentTime - timerData.startTime1) / 1000.0; doc["time1"] = (currentTime - timerData.localStartTime1) / 1000.0;
doc["status1"] = "running"; doc["status1"] = "running";
} else if (timerData.endTime1 > 0) { } else if (timerData.endTime1 > 0) {
doc["time1"] = (timerData.endTime1 - timerData.startTime1) / 1000.0; doc["time1"] = (timerData.endTime1 - timerData.startTime1) / 1000.0;
@@ -238,7 +240,7 @@ String getTimerDataJSON() {
// Bahn 2 // Bahn 2
if (timerData.isRunning2) { if (timerData.isRunning2) {
doc["time2"] = (currentTime - timerData.startTime2) / 1000.0; doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0;
doc["status2"] = "running"; doc["status2"] = "running";
} else if (timerData.endTime2 > 0) { } else if (timerData.endTime2 > 0) {
doc["time2"] = (timerData.endTime2 - timerData.startTime2) / 1000.0; doc["time2"] = (timerData.endTime2 - timerData.startTime2) / 1000.0;

View File

@@ -15,14 +15,16 @@ char* passwordSTA = nullptr;
struct TimerData { struct TimerData {
unsigned long startTime1 = 0; unsigned long startTime1 = 0;
unsigned long startTime2 = 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 endTime1 = 0;
unsigned long endTime2 = 0; unsigned long endTime2 = 0;
unsigned long bestTime1 = 0; unsigned long bestTime1 = 0;
unsigned long bestTime2 = 0; unsigned long bestTime2 = 0;
bool isRunning1 = false; bool isRunning1 = false;
bool isRunning2 = false; bool isRunning2 = false;
unsigned long finishedSince1 = 0;
unsigned long finishedSince2 = 0;
bool isReady1 = true; // Status für Bahn 1 bool isReady1 = true; // Status für Bahn 1
bool isReady2 = true; // Status für Bahn 2 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 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(); void handleStart1(uint64_t timestamp);
void handleStop1(); void handleStop1(uint64_t timestamp);
void handleStart2(); void handleStart2(uint64_t timestamp);
void handleStop2(); void handleStop2(uint64_t timestamp);
void checkAutoReset(); void checkAutoReset();
void saveButtonConfig(); void saveButtonConfig();
void loadButtonConfig(); void loadButtonConfig();