Bug fixed, Wettkampfmodus Done. TODO: Zeitstempel der Statusampel im Master verwenden
This commit is contained in:
@@ -355,18 +355,24 @@ body {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.ready {
|
.status.finished {
|
||||||
background-color: rgba(52, 152, 219, 0.3);
|
background-color: rgba(52, 152, 219, 0.3);
|
||||||
border: 2px solid #3498db;
|
border: 2px solid #3498db;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.running {
|
.status.ready {
|
||||||
background-color: rgba(46, 204, 113, 0.3);
|
background-color: rgba(46, 204, 113, 0.3);
|
||||||
border: 2px solid #2ecc71;
|
border: 2px solid #2ecc71;
|
||||||
animation: pulse 1s infinite;
|
animation: pulse 1s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.finished {
|
.status.armed {
|
||||||
|
background-color: rgb(197, 194, 0);
|
||||||
|
border: 2px solid #fbff00;
|
||||||
|
animation: pulse 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.running {
|
||||||
background-color: rgba(231, 76, 60, 0.3);
|
background-color: rgba(231, 76, 60, 0.3);
|
||||||
border: 2px solid #e74c3c;
|
border: 2px solid #e74c3c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -380,7 +380,7 @@
|
|||||||
s1.textContent = "Beendet";
|
s1.textContent = "Beendet";
|
||||||
break;
|
break;
|
||||||
case "armed":
|
case "armed":
|
||||||
s1.textContent = "Armiert"; // Neuer Status für armiert
|
s1.textContent = "Armiert";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
s1.textContent = "Unbekannter Status";
|
s1.textContent = "Unbekannter Status";
|
||||||
@@ -391,7 +391,7 @@
|
|||||||
|
|
||||||
if (!lane2Connected) {
|
if (!lane2Connected) {
|
||||||
s2.className = "status standby";
|
s2.className = "status standby";
|
||||||
s2.textContent = "Standby: Bitte beide 1x betätigen";
|
s2.textContent = "Standby: Bitte beide Buttons 1x betätigen";
|
||||||
} else {
|
} else {
|
||||||
s2.className = `status ${status2}`;
|
s2.className = `status ${status2}`;
|
||||||
|
|
||||||
|
|||||||
@@ -344,6 +344,11 @@ void setupMqttServer() {
|
|||||||
handleBatteryTopic(topic, payload);
|
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);
|
||||||
|
} else if (strncmp(topic, "aquacross/competition/toMaster", 30) == 0) {
|
||||||
|
// Handle competition lane messages
|
||||||
|
// payload ist sendMQTTMessage("aquacross/competition/toMaster", "start");
|
||||||
|
startCompetition = (payload != nullptr && strcmp(payload, "start") == 0);
|
||||||
|
runCompetition();
|
||||||
}
|
}
|
||||||
updateStatusLED(3);
|
updateStatusLED(3);
|
||||||
});
|
});
|
||||||
|
|||||||
104
src/gamemodes.h
104
src/gamemodes.h
@@ -14,10 +14,6 @@ void IndividualMode(const char *action, int press, int lane,
|
|||||||
uint64_t timestamp = 0);
|
uint64_t timestamp = 0);
|
||||||
void CompetitionMode(const char *action, int press, int lane,
|
void CompetitionMode(const char *action, int press, int lane,
|
||||||
uint64_t timestamp = 0);
|
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 triggerAction(const char *action, int press, int lane,
|
void triggerAction(const char *action, int press, int lane,
|
||||||
uint64_t _timestamp) {
|
uint64_t _timestamp) {
|
||||||
@@ -41,6 +37,7 @@ void IndividualMode(const char *action, int press, int lane,
|
|||||||
timerData.localStartTime1 = millis(); // Set local start time
|
timerData.localStartTime1 = millis(); // Set local start time
|
||||||
timerData.isRunning1 = true;
|
timerData.isRunning1 = true;
|
||||||
timerData.endTime1 = 0;
|
timerData.endTime1 = 0;
|
||||||
|
timerData.isArmed1 = false; // Reset armed status
|
||||||
publishLaneStatus(1, "running");
|
publishLaneStatus(1, "running");
|
||||||
Serial.println("Bahn 1 gestartet");
|
Serial.println("Bahn 1 gestartet");
|
||||||
}
|
}
|
||||||
@@ -68,6 +65,7 @@ void IndividualMode(const char *action, int press, int lane,
|
|||||||
timerData.localStartTime2 = millis(); // Set local start time
|
timerData.localStartTime2 = millis(); // Set local start time
|
||||||
timerData.isRunning2 = true;
|
timerData.isRunning2 = true;
|
||||||
timerData.endTime2 = 0;
|
timerData.endTime2 = 0;
|
||||||
|
timerData.isArmed2 = false; // Reset armed status
|
||||||
publishLaneStatus(2, "running");
|
publishLaneStatus(2, "running");
|
||||||
Serial.println("Bahn 2 gestartet");
|
Serial.println("Bahn 2 gestartet");
|
||||||
}
|
}
|
||||||
@@ -137,26 +135,11 @@ void CompetitionMode(const char *action, int press, int lane,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (timerData.isArmed1 && timerData.isArmed2) {
|
if (timerData.isArmed1 && timerData.isArmed2) {
|
||||||
timerData.isReady1 = false;
|
sendMQTTMessage("aquacross/competition/toSignal", "armed");
|
||||||
uint64_t startNow = getCurrentTimestampMs();
|
|
||||||
timerData.startTime1 = startNow;
|
|
||||||
timerData.localStartTime1 = millis(); // Set local start time
|
|
||||||
timerData.isRunning1 = true;
|
|
||||||
timerData.endTime1 = 0; // Reset end time for Bahn 1
|
|
||||||
timerData.isArmed1 = false; // Reset Bahn 1 armed status
|
|
||||||
publishLaneStatus(1, "running");
|
|
||||||
Serial.println("Bahn 1 gestartet");
|
|
||||||
|
|
||||||
timerData.isReady2 = false;
|
|
||||||
timerData.startTime2 = startNow;
|
|
||||||
timerData.localStartTime2 = millis(); // Set local start time
|
|
||||||
timerData.isRunning2 = true;
|
|
||||||
timerData.endTime2 = 0; // Reset end time for Bahn 2
|
|
||||||
timerData.isArmed2 = false; // Reset Bahn 2 armed status
|
|
||||||
publishLaneStatus(2, "running");
|
|
||||||
Serial.println("Bahn 2 gestartet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((action == "stop" && press == 1 && lane == 1)) {
|
if ((action == "stop" && press == 1 && lane == 1)) {
|
||||||
if (timerData.isRunning1) {
|
if (timerData.isRunning1) {
|
||||||
timerData.endTime1 = (timestamp > 0) ? timestamp : millis();
|
timerData.endTime1 = (timestamp > 0) ? timestamp : millis();
|
||||||
@@ -191,6 +174,32 @@ void CompetitionMode(const char *action, int press, int lane,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runCompetition() {
|
||||||
|
if (timerData.isArmed1 && timerData.isArmed2 && startCompetition) {
|
||||||
|
timerData.isReady1 = false;
|
||||||
|
uint64_t startNow = getCurrentTimestampMs();
|
||||||
|
timerData.startTime1 = startNow;
|
||||||
|
timerData.localStartTime1 = millis(); // Set local start time
|
||||||
|
timerData.isRunning1 = true;
|
||||||
|
timerData.endTime1 = 0; // Reset end time for Bahn 1
|
||||||
|
timerData.isArmed1 = false; // Reset Bahn 1 armed status
|
||||||
|
publishLaneStatus(1, "running");
|
||||||
|
Serial.println("Bahn 1 gestartet");
|
||||||
|
|
||||||
|
timerData.isReady2 = false;
|
||||||
|
timerData.startTime2 = startNow;
|
||||||
|
timerData.localStartTime2 = millis(); // Set local start time
|
||||||
|
timerData.isRunning2 = true;
|
||||||
|
timerData.endTime2 = 0; // Reset end time for Bahn 2
|
||||||
|
timerData.isArmed2 = false; // Reset Bahn 2 armed status
|
||||||
|
publishLaneStatus(2, "running");
|
||||||
|
Serial.println("Bahn 2 gestartet");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println("Bahn 1 und Bahn 2 müssen armiert sein, um den Wettkampf zu starten.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void checkAutoReset() {
|
void checkAutoReset() {
|
||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
@@ -273,3 +282,54 @@ void checkAutoReset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getTimerDataJSON() {
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
|
unsigned long currentTime = millis();
|
||||||
|
// Bahn 1
|
||||||
|
if (timerData.isRunning1) {
|
||||||
|
doc["time1"] = (currentTime - timerData.localStartTime1) / 1000.0;
|
||||||
|
doc["status1"] = "running";
|
||||||
|
} else if (timerData.endTime1 > 0) {
|
||||||
|
doc["time1"] = (timerData.endTime1 - timerData.startTime1) / 1000.0;
|
||||||
|
doc["status1"] = "finished";
|
||||||
|
} else if (timerData.isArmed1) {
|
||||||
|
doc["time1"] = 0;
|
||||||
|
doc["status1"] = "armed"; // Status für Bahn 1, wenn sie armiert ist
|
||||||
|
} else {
|
||||||
|
doc["time1"] = 0;
|
||||||
|
doc["status1"] = "ready";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bahn 2
|
||||||
|
if (timerData.isRunning2) {
|
||||||
|
doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0;
|
||||||
|
doc["status2"] = "running";
|
||||||
|
} else if (timerData.endTime2 > 0) {
|
||||||
|
doc["time2"] = (timerData.endTime2 - timerData.startTime2) / 1000.0;
|
||||||
|
doc["status2"] = "finished";
|
||||||
|
} else if (timerData.isArmed2) {
|
||||||
|
doc["time2"] = 0;
|
||||||
|
doc["status2"] = "armed"; // Status für Bahn 2, wenn sie armiert ist
|
||||||
|
} else {
|
||||||
|
doc["time2"] = 0;
|
||||||
|
doc["status2"] = "ready";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Beste Zeiten
|
||||||
|
doc["best1"] = timerData.bestTime1 / 1000.0;
|
||||||
|
doc["best2"] = timerData.bestTime2 / 1000.0;
|
||||||
|
|
||||||
|
// Lernmodus
|
||||||
|
doc["learningMode"] = learningMode;
|
||||||
|
if (learningMode) {
|
||||||
|
String buttons[] = {"Start Bahn 1", "Stop Bahn 1", "Start Bahn 2",
|
||||||
|
"Stop Bahn 2"};
|
||||||
|
doc["learningButton"] = buttons[learningStep];
|
||||||
|
}
|
||||||
|
|
||||||
|
String result;
|
||||||
|
serializeJson(doc, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -107,56 +107,7 @@ int checkLicence() {
|
|||||||
return tier;
|
return tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTimerDataJSON() {
|
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
|
|
||||||
unsigned long currentTime = millis();
|
|
||||||
// Bahn 1
|
|
||||||
if (timerData.isRunning1) {
|
|
||||||
doc["time1"] = (currentTime - timerData.localStartTime1) / 1000.0;
|
|
||||||
doc["status1"] = "running";
|
|
||||||
} else if (timerData.endTime1 > 0) {
|
|
||||||
doc["time1"] = (timerData.endTime1 - timerData.startTime1) / 1000.0;
|
|
||||||
doc["status1"] = "finished";
|
|
||||||
} else if (timerData.isArmed1) {
|
|
||||||
doc["time1"] = 0;
|
|
||||||
doc["status1"] = "armed"; // Status für Bahn 1, wenn sie armiert ist
|
|
||||||
} else {
|
|
||||||
doc["time1"] = 0;
|
|
||||||
doc["status1"] = "ready";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bahn 2
|
|
||||||
if (timerData.isRunning2) {
|
|
||||||
doc["time2"] = (currentTime - timerData.localStartTime2) / 1000.0;
|
|
||||||
doc["status2"] = "running";
|
|
||||||
} else if (timerData.endTime2 > 0) {
|
|
||||||
doc["time2"] = (timerData.endTime2 - timerData.startTime2) / 1000.0;
|
|
||||||
doc["status2"] = "finished";
|
|
||||||
} else if (timerData.isArmed2) {
|
|
||||||
doc["time2"] = 0;
|
|
||||||
doc["status2"] = "armed"; // Status für Bahn 2, wenn sie armiert ist
|
|
||||||
} else {
|
|
||||||
doc["time2"] = 0;
|
|
||||||
doc["status2"] = "ready";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Beste Zeiten
|
|
||||||
doc["best1"] = timerData.bestTime1 / 1000.0;
|
|
||||||
doc["best2"] = timerData.bestTime2 / 1000.0;
|
|
||||||
|
|
||||||
// Lernmodus
|
|
||||||
doc["learningMode"] = learningMode;
|
|
||||||
if (learningMode) {
|
|
||||||
String buttons[] = {"Start Bahn 1", "Stop Bahn 1", "Start Bahn 2",
|
|
||||||
"Stop Bahn 2"};
|
|
||||||
doc["learningButton"] = buttons[learningStep];
|
|
||||||
}
|
|
||||||
|
|
||||||
String result;
|
|
||||||
serializeJson(doc, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
@@ -180,6 +131,7 @@ void setup() {
|
|||||||
loadWifiSettings();
|
loadWifiSettings();
|
||||||
loadLocationSettings();
|
loadLocationSettings();
|
||||||
|
|
||||||
|
|
||||||
setupWifi(); // WiFi initialisieren
|
setupWifi(); // WiFi initialisieren
|
||||||
setupOTA(&server);
|
setupOTA(&server);
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ unsigned long maxTimeBeforeReset = 300000; // 5 Minuten default
|
|||||||
unsigned long maxTimeDisplay = 20000; // 20 Sekunden Standard (in ms)
|
unsigned long maxTimeDisplay = 20000; // 20 Sekunden Standard (in ms)
|
||||||
bool wifimodeAP = false; // AP-Modus deaktiviert
|
bool wifimodeAP = false; // AP-Modus deaktiviert
|
||||||
String masterlocation;
|
String masterlocation;
|
||||||
int gamemode; // 0=Individual, 1=Wettkampf
|
int gamemode; // 0=Individual, 1=Wettkampf
|
||||||
|
bool startCompetition = false; // Flag, ob der Timer gestartet wurde
|
||||||
|
|
||||||
// Function Declarations
|
// Function Declarations
|
||||||
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len);
|
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len);
|
||||||
|
|||||||
@@ -300,6 +300,7 @@ void setupRoutes() {
|
|||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
|
saveSettings();
|
||||||
} else {
|
} else {
|
||||||
request->send(400, "application/json",
|
request->send(400, "application/json",
|
||||||
"{\"success\":false,\"error\":\"Modus fehlt\"}");
|
"{\"success\":false,\"error\":\"Modus fehlt\"}");
|
||||||
@@ -314,16 +315,6 @@ void setupRoutes() {
|
|||||||
request->send(200, "application/json", 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
|
// Statische Dateien
|
||||||
server.serveStatic("/", SPIFFS, "/");
|
server.serveStatic("/", SPIFFS, "/");
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|||||||
Reference in New Issue
Block a user