diff --git a/data/settings.html b/data/settings.html index 1a7abff..fc9dec1 100644 --- a/data/settings.html +++ b/data/settings.html @@ -344,6 +344,7 @@ loadCurrentTime(); updateCurrentTimeDisplay(); loadWifiSettings(); + loadMode(); }; // Aktuelle Zeit anzeigen (Live-Update) @@ -525,6 +526,23 @@ .catch(error => showMessage('Verbindungsfehler', 'error')); }); + function loadMode() { + fetch("/api/get-mode") + .then((response) => response.json()) + .then((data) => { + const mode = data.mode || "individual"; + document.querySelectorAll('.mode-button').forEach(button => { + button.classList.remove('active'); + }); + const btn = document.querySelector(`.mode-button[data-mode="${mode}"]`); + if (btn) btn.classList.add('active'); + }) + .catch((error) => { + showMessage("Fehler beim Laden des Modus", "error"); + }); +} + + // Einstellungen laden function loadSettings() { fetch("/api/get-settings") diff --git a/src/communication.h b/src/communication.h index 614ebb1..5e299a0 100644 --- a/src/communication.h +++ b/src/communication.h @@ -12,6 +12,7 @@ #include "statusled.h" #include "timesync.h" #include "webserverrouter.h" +#include #include /** @@ -88,16 +89,20 @@ 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(timestamp); + // handleStart1(timestamp); + triggerAction("start", 2, 1, timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0 && (pressType == 1)) { - handleStop1(timestamp); + // handleStop1(timestamp); + triggerAction("stop", 1, 1, timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0 && (pressType == 2)) { - handleStart2(timestamp); + // handleStart2(timestamp); + triggerAction("start", 2, 2, timestamp); } else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0 && (pressType == 1)) { - handleStop2(timestamp); + // handleStop2(timestamp); + triggerAction("stop", 1, 2, timestamp); } // Flash status LED to indicate received message diff --git a/src/debug.h b/src/debug.h index 88786f5..581dc1c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -7,8 +7,8 @@ #include #include - #include "communication.h" +#include "gamemodes.h" void setupDebugAPI(AsyncWebServer &server); @@ -16,22 +16,22 @@ void setupDebugAPI(AsyncWebServer &server) { // DEBUG server.on("/api/debug/start1", HTTP_GET, [](AsyncWebServerRequest *request) { - handleStart1(0); + // handleStart1(0); request->send(200, "text/plain", "handleStart1() called"); }); server.on("/api/debug/stop1", HTTP_GET, [](AsyncWebServerRequest *request) { - handleStop1(0); + // handleStop1(0); request->send(200, "text/plain", "handleStop1() called"); }); server.on("/api/debug/start2", HTTP_GET, [](AsyncWebServerRequest *request) { - handleStart2(0); + // handleStart2(0); request->send(200, "text/plain", "handleStart2() called"); }); server.on("/api/debug/stop2", HTTP_GET, [](AsyncWebServerRequest *request) { - handleStop2(0); + // handleStop2(0); request->send(200, "text/plain", "handleStop2() called"); }); diff --git a/src/gamemodes.h b/src/gamemodes.h index c4fca1d..7e2a62c 100644 --- a/src/gamemodes.h +++ b/src/gamemodes.h @@ -1,20 +1,171 @@ +void publishLaneStatus(int lane, String status); +void pushUpdateToFrontend(const String &message); + #pragma once #include +#include #include #include +#include +#include -void IndividualMode(); -void CompetitionMode(); +void IndividualMode(const char *action, int press, int lane, + uint64_t timestamp = 0); +void CompetitionMode(const char *action, int press, int lane, + uint64_t timestamp = 0); +void handleStart1(uint64_t timestamp); +void handleStop1(uint64_t timestamp); +void handleStart2(uint64_t timestamp); +void handleStop2(uint64_t timestamp); -void IndividualMode(const char *action, int lane, int timestamp = 0) { - Serial.printf("Individual Mode Action: %s on Lane %d at %d\n", action, lane, +void triggerAction(const char *action, int press, int lane, + uint64_t _timestamp = 0) { + if (gamemode == 0) { + Serial.println("Individual Mode aktiv"); + IndividualMode(action, press, lane, _timestamp); + } else if (gamemode == 1) { + Serial.println("Wettkampf Mode aktiv"); + CompetitionMode(action, press, lane, _timestamp); + } else { + Serial.println("Unbekannter Modus, bitte überprüfen"); + } +} + +void IndividualMode(const char *action, int press, int lane, + uint64_t timestamp) { + if (action == "start" && press == 2 && lane == 1) { + if (!timerData.isRunning1 && timerData.isReady1) { + timerData.isReady1 = false; + timerData.startTime1 = (timestamp > 0) ? timestamp : millis(); + timerData.localStartTime1 = millis(); // Set local start time + timerData.isRunning1 = true; + timerData.endTime1 = 0; + publishLaneStatus(1, "running"); + Serial.println("Bahn 1 gestartet"); + } + } + if (action == "stop" && press == 1 && lane == 1) { + if (timerData.isRunning1) { + 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(); + } + publishLaneStatus(1, "stopped"); + Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime / 1000.0) + + "s"); + } + } + if (action == "start" && press == 2 && lane == 2) { + if (!timerData.isRunning2 && timerData.isReady2) { + timerData.isReady2 = false; + timerData.startTime2 = (timestamp > 0) ? timestamp : millis(); + timerData.localStartTime2 = millis(); // Set local start time + timerData.isRunning2 = true; + timerData.endTime2 = 0; + publishLaneStatus(2, "running"); + Serial.println("Bahn 2 gestartet"); + } + } + if (action == "stop" && press == 1 && lane == 2) { + if (timerData.isRunning2) { + 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(); + } + publishLaneStatus(2, "stopped"); + Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime / 1000.0) + + "s"); + } + } + + Serial.printf("Individual Mode Action: %s on Lane %d at %llu\n", action, lane, timestamp); // Implement individual mode logic here } -void CompetitionMode(const char *action, int lane, int timestamp = 0) { - Serial.printf("Competition Mode Action: %s on Lane %d at %d\n", action, lane, - timestamp); +void CompetitionMode(const char *action, int press, int lane, + uint64_t timestamp) { + Serial.printf("Competition Mode Action: %s on Lane %d at %llu\n", action, + lane, timestamp); // Implement competition mode logic here +} + +void checkAutoReset() { + unsigned long currentTime = millis(); + + if (timerData.isRunning1 && + (currentTime - timerData.localStartTime1 > maxTimeBeforeReset)) { + timerData.isRunning1 = false; + timerData.startTime1 = 0; + publishLaneStatus(1, "ready"); + Serial.println("Bahn 1 automatisch zurückgesetzt"); + } + + if (timerData.isRunning2 && + (currentTime - timerData.localStartTime2 > maxTimeBeforeReset)) { + timerData.isRunning2 = false; + timerData.startTime2 = 0; + publishLaneStatus(2, "ready"); + Serial.println("Bahn 2 automatisch zurückgesetzt"); + } + + // Automatischer Reset nach 10 Sekunden "Beendet" + if (!timerData.isRunning1 && timerData.endTime1 > 0 && + timerData.finishedSince1 > 0) { + if (millis() - timerData.finishedSince1 > maxTimeDisplay) { + timerData.startTime1 = 0; + timerData.endTime1 = 0; + timerData.finishedSince1 = 0; + timerData.isReady1 = true; // Zurücksetzen auf "Bereit" + + JsonDocument messageDoc; + messageDoc["firstname"] = ""; + messageDoc["lastname"] = ""; + messageDoc["lane"] = "start1"; // Add lane information + + String message; + serializeJson(messageDoc, message); + + // Push the message to the frontend + pushUpdateToFrontend(message); + publishLaneStatus(1, "ready"); + + Serial.println("Bahn 1 automatisch auf 'Bereit' zurückgesetzt"); + } + } + + if (!timerData.isRunning2 && timerData.endTime2 > 0 && + timerData.finishedSince2 > 0) { + if (currentTime - timerData.finishedSince2 > maxTimeDisplay) { + timerData.startTime2 = 0; + timerData.endTime2 = 0; + timerData.finishedSince2 = 0; + timerData.isReady2 = true; // Zurücksetzen auf "Bereit" + + JsonDocument messageDoc; + messageDoc["firstname"] = ""; + messageDoc["lastname"] = ""; + messageDoc["lane"] = "start2"; // Add lane information + + String message; + serializeJson(messageDoc, message); + + // Push the message to the frontend + pushUpdateToFrontend(message); + publishLaneStatus(2, "ready"); + + Serial.println("Bahn 2 automatisch auf 'Bereit' zurückgesetzt"); + } + } } \ No newline at end of file diff --git a/src/master.cpp b/src/master.cpp index 4fc66eb..bf472a9 100644 --- a/src/master.cpp +++ b/src/master.cpp @@ -21,135 +21,10 @@ #include #include #include +#include const char *firmwareversion = "1.0.0"; // Version der Firmware -void handleStart1(uint64_t timestamp = 0) { - if (!timerData.isRunning1 && timerData.isReady1) { - timerData.isReady1 = false; - timerData.startTime1 = (timestamp > 0) ? timestamp : millis(); - timerData.localStartTime1 = millis(); // Set local start time - timerData.isRunning1 = true; - timerData.endTime1 = 0; - publishLaneStatus(1, "running"); - Serial.println("Bahn 1 gestartet"); - } -} - -void handleStop1(uint64_t timestamp = 0) { - if (timerData.isRunning1) { - 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(); - } - publishLaneStatus(1, "stopped"); - Serial.println("Bahn 1 gestoppt - Zeit: " + String(currentTime / 1000.0) + - "s"); - } -} - -void handleStart2(uint64_t timestamp = 0) { - if (!timerData.isRunning2 && timerData.isReady2) { - timerData.isReady2 = false; - timerData.startTime2 = (timestamp > 0) ? timestamp : millis(); - timerData.localStartTime2 = millis(); // Set local start time - timerData.isRunning2 = true; - timerData.endTime2 = 0; - publishLaneStatus(2, "running"); - Serial.println("Bahn 2 gestartet"); - } -} - -void handleStop2(uint64_t timestamp = 0) { - if (timerData.isRunning2) { - 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(); - } - publishLaneStatus(2, "stopped"); - Serial.println("Bahn 2 gestoppt - Zeit: " + String(currentTime / 1000.0) + - "s"); - } -} - -void checkAutoReset() { - unsigned long currentTime = millis(); - - if (timerData.isRunning1 && - (currentTime - timerData.localStartTime1 > maxTimeBeforeReset)) { - timerData.isRunning1 = false; - timerData.startTime1 = 0; - publishLaneStatus(1, "ready"); - Serial.println("Bahn 1 automatisch zurückgesetzt"); - } - - if (timerData.isRunning2 && - (currentTime - timerData.localStartTime2 > maxTimeBeforeReset)) { - timerData.isRunning2 = false; - timerData.startTime2 = 0; - publishLaneStatus(2, "ready"); - Serial.println("Bahn 2 automatisch zurückgesetzt"); - } - - // Automatischer Reset nach 10 Sekunden "Beendet" - if (!timerData.isRunning1 && timerData.endTime1 > 0 && - timerData.finishedSince1 > 0) { - if (millis() - timerData.finishedSince1 > maxTimeDisplay) { - timerData.startTime1 = 0; - timerData.endTime1 = 0; - timerData.finishedSince1 = 0; - timerData.isReady1 = true; // Zurücksetzen auf "Bereit" - - JsonDocument messageDoc; - messageDoc["firstname"] = ""; - messageDoc["lastname"] = ""; - messageDoc["lane"] = "start1"; // Add lane information - - String message; - serializeJson(messageDoc, message); - - // Push the message to the frontend - pushUpdateToFrontend(message); - publishLaneStatus(1, "ready"); - - Serial.println("Bahn 1 automatisch auf 'Bereit' zurückgesetzt"); - } - } - - if (!timerData.isRunning2 && timerData.endTime2 > 0 && - timerData.finishedSince2 > 0) { - if (currentTime - timerData.finishedSince2 > maxTimeDisplay) { - timerData.startTime2 = 0; - timerData.endTime2 = 0; - timerData.finishedSince2 = 0; - timerData.isReady2 = true; // Zurücksetzen auf "Bereit" - - JsonDocument messageDoc; - messageDoc["firstname"] = ""; - messageDoc["lastname"] = ""; - messageDoc["lane"] = "start2"; // Add lane information - - String message; - serializeJson(messageDoc, message); - - // Push the message to the frontend - pushUpdateToFrontend(message); - publishLaneStatus(2, "ready"); - - Serial.println("Bahn 2 automatisch auf 'Bereit' zurückgesetzt"); - } - } -} void saveButtonConfig() { preferences.begin("buttons", false); diff --git a/src/master.h b/src/master.h index c839274..ac05d97 100644 --- a/src/master.h +++ b/src/master.h @@ -56,16 +56,12 @@ unsigned long maxTimeBeforeReset = 300000; // 5 Minuten default unsigned long maxTimeDisplay = 20000; // 20 Sekunden Standard (in ms) bool wifimodeAP = false; // AP-Modus deaktiviert String masterlocation; -int operationalMode = 0; // 0=Individual, 1=Wettkampf +int gamemode; // 0=Individual, 1=Wettkampf // Function Declarations void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len); void handleLearningMode(const uint8_t *mac); void handleStartLearning(); -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(); diff --git a/src/webserverrouter.h b/src/webserverrouter.h index df9529e..b1621a6 100644 --- a/src/webserverrouter.h +++ b/src/webserverrouter.h @@ -12,6 +12,7 @@ void sendMQTTMessage(const char *topic, const char *message); #include "communication.h" #include +#include #include AsyncWebServer server(80); @@ -290,9 +291,9 @@ void setupRoutes() { if (mode.length() > 0) { // Speichere den Modus - operationalMode = mode == "individual" ? 1 : 0; + gamemode = mode == "individual" ? 0 : 1; Serial.printf("Operational mode set to: %s\n", - operationalMode == 1 ? "Individual" : "Wettkampf"); + gamemode == 0 ? "Individual" : "Wettkampf"); // Rückmeldung DynamicJsonDocument doc(64); doc["success"] = true; @@ -305,6 +306,24 @@ void setupRoutes() { } }); + server.on("/api/get-mode", HTTP_GET, [](AsyncWebServerRequest *request) { + DynamicJsonDocument doc(32); + doc["mode"] = gamemode == 0 ? "individual" : "wettkampf"; + String result; + serializeJson(doc, result); + request->send(200, "application/json", result); + }); + + server.on("/api/get-mode", HTTP_GET, [](AsyncWebServerRequest *request) { + DynamicJsonDocument doc(32); + doc["mode"] = gamemode == 0 ? "individual" : "wettkampf"; + String result; + serializeJson(doc, result); + request->send(200, "application/json", result); + }); + + // ...existing code... + // Statische Dateien server.serveStatic("/", SPIFFS, "/"); server.begin();