Added minTime

This commit is contained in:
Carsten Graf
2025-10-13 19:17:35 +02:00
parent 5ca67d8804
commit 2a832257ba
9 changed files with 115 additions and 48 deletions

80
API.md
View File

@@ -7,86 +7,86 @@ All API endpoints return JSON unless otherwise noted.
## Static Files ## Static Files
| Route | Method | Description | Response Type | | Route | Method | Description | Response Type |
|------------------|--------|------------------------------|--------------| | --------------- | ------ | ---------------------- | ------------- |
| `/` | GET | Main page | HTML | | `/` | GET | Main page | HTML |
| `/settings` | GET | Settings page | HTML | | `/settings` | GET | Settings page | HTML |
| `/rfid` | GET | RFID page | HTML | | `/rfid` | GET | RFID page | HTML |
| `/firmware.bin` | GET | Firmware file (SPIFFS) | Binary | | `/firmware.bin` | GET | Firmware file (SPIFFS) | Binary |
--- ---
## Timer & Data ## Timer & Data
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|-------------------|--------|-------------------------------------|--------------------|------------------| | ----------------- | ------ | --------------------------------- | ------------------- | --------------------- |
| `/api/data` | GET | Get current timer and status data | | `{...}` | | `/api/data` | GET | Get current timer and status data | | `{...}` |
| `/api/reset-best` | POST | Reset best times | | `{ "success": true }` | | `/api/reset-best` | POST | Reset best times | | `{ "success": true }` |
--- ---
## Button Learning ## Button Learning
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|------------------------|--------|-------------------------------------|--------------------|------------------| | --------------------- | ------ | --------------------------------- | ------------------- | ------------------------------------------------------- |
| `/api/unlearn-button` | POST | Remove all button assignments | | `{ "success": true }` | | `/api/unlearn-button` | POST | Remove all button assignments | | `{ "success": true }` |
| `/api/start-learning` | POST | Start button learning mode | | `{ "success": true }` | | `/api/start-learning` | POST | Start button learning mode | | `{ "success": true }` |
| `/api/stop-learning` | POST | Stop button learning mode | | `{ "success": true }` | | `/api/stop-learning` | POST | Stop button learning mode | | `{ "success": true }` |
| `/api/learn/status` | GET | Get learning mode status | | `{ "active": true, "step": 1 }` | | `/api/learn/status` | GET | Get learning mode status | | `{ "active": true, "step": 1 }` |
| `/api/buttons/status` | GET | Get button assignment and voltage | | `{ "lane1Start": true, "lane1StartVoltage": 3.3, ... }` | | `/api/buttons/status` | GET | Get button assignment and voltage | | `{ "lane1Start": true, "lane1StartVoltage": 3.3, ... }` |
--- ---
## Settings ## Settings
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|----------------------|--------|-------------------------------------|--------------------|------------------| | ------------------- | ------ | ------------------------------ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `/api/set-max-time` | POST | Set max timer and display time | `maxTime`, `maxTimeDisplay` (form params, seconds) | `{ "success": true }` | | `/api/set-max-time` | POST | Set max timer and display time | `maxTime`, `maxTimeDisplay`, `minTimeForLeaderboard` (form params, seconds) | `{ "success": true }` |
| `/api/get-settings` | GET | Get current timer settings | | `{ "maxTime": 300, "maxTimeDisplay": 20 }` | | `/api/get-settings` | GET | Get current timer settings | | `{ "maxTime": 300, "maxTimeDisplay": 20, "minTimeForLeaderboard": 5 }` |
--- ---
## WiFi Configuration ## WiFi Configuration
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|-------------------|--------|-------------------------------------|--------------------|------------------| | --------------- | ------ | ---------------------------------- | -------------------------------- | -------------------------------------- |
| `/api/set-wifi` | POST | Set WiFi SSID and password | `ssid`, `password` (form params) | `{ "success": true }` | | `/api/set-wifi` | POST | Set WiFi SSID and password | `ssid`, `password` (form params) | `{ "success": true }` |
| `/api/get-wifi` | GET | Get current WiFi SSID and password | | `{ "ssid": "...", "password": "..." }` | | `/api/get-wifi` | GET | Get current WiFi SSID and password | | `{ "ssid": "...", "password": "..." }` |
--- ---
## Location Configuration ## Location Configuration
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|----------------------|--------|-------------------------------------|--------------------|------------------| | ------------------- | ------ | ------------------------ | -------------------------- | ------------------------- |
| `/api/set-location` | POST | Set location name and ID | `id`, `name` (form params) | `{ "success": true }` | | `/api/set-location` | POST | Set location name and ID | `id`, `name` (form params) | `{ "success": true }` |
| `/api/get-location` | GET | Get current location | | `{ "locationid": "..." }` | | `/api/get-location` | GET | Get current location | | `{ "locationid": "..." }` |
--- ---
## Button Update & Mode ## Button Update & Mode
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|----------------------|--------|-------------------------------------|--------------------|------------------| | -------------------- | ------ | ------------------------------- | ------------------------------------------------ | -------------------------- |
| `/api/updateButtons` | GET | Trigger MQTT update for buttons | | `{ "success": true }` | | `/api/updateButtons` | GET | Trigger MQTT update for buttons | | `{ "success": true }` |
| `/api/set-mode` | POST | Set operational mode | `mode` (form param: "individual" or "wettkampf") | `{ "success": true }` | | `/api/set-mode` | POST | Set operational mode | `mode` (form param: "individual" or "wettkampf") | `{ "success": true }` |
| `/api/get-mode` | GET | Get current operational mode | | `{ "mode": "individual" }` | | `/api/get-mode` | GET | Get current operational mode | | `{ "mode": "individual" }` |
--- ---
## System Info ## System Info
| Route | Method | Description | Request Body/Params | Response Example | | Route | Method | Description | Request Body/Params | Response Example |
|---------------|--------|-------------------------------------|--------------------|------------------| | ----------- | ------ | ------------------------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `/api/info` | GET | Get system info (IP, MAC, memory, license, etc.) | | `{ "ip": "...", "ipSTA": "...", "channel": 1, "mac": "...", "freeMemory": 123456, "connectedButtons": 3, "isOnline": true, "valid": "Ja", "tier": 1 }` | | `/api/info` | GET | Get system info (IP, MAC, memory, license, etc.) | | `{ "ip": "...", "ipSTA": "...", "channel": 1, "mac": "...", "freeMemory": 123456, "connectedButtons": 3, "isOnline": true, "valid": "Ja", "tier": 1 }` |
--- ---
## WebSocket ## WebSocket
| Route | Description | | Route | Description |
|---------|------------------------------------| | ----- | ----------------------------------- |
| `/ws` | WebSocket endpoint for live updates| | `/ws` | WebSocket endpoint for live updates |
--- ---

View File

@@ -9,7 +9,7 @@ POST /api/unlearn-button
→ Verlernt alle Button-Zuordnungen → Verlernt alle Button-Zuordnungen
POST /api/set-max-time POST /api/set-max-time
→ Setzt die maximale Zeit und maxTimeDisplay → Setzt die maximale Zeit, maxTimeDisplay und minTimeForLeaderboard
GET /api/get-settings GET /api/get-settings
→ Gibt die aktuellen Einstellungen zurück → Gibt die aktuellen Einstellungen zurück

Binary file not shown.

View File

@@ -182,6 +182,18 @@
title="Zeit nach der die angezeigte Zeit zurückgesetzt wird" title="Zeit nach der die angezeigte Zeit zurückgesetzt wird"
/> />
</div> </div>
<div class="form-group">
<label for="minTimeForLeaderboard">Minimale Zeit für Leaderboard (Sekunden):</label>
<input
type="number"
id="minTimeForLeaderboard"
name="minTimeForLeaderboard"
min="1"
max="300"
value="5"
title="Zeiten unter diesem Wert werden nicht ins lokale Leaderboard eingetragen (Missbrauchsschutz)"
/>
</div>
<div class="button-group"> <div class="button-group">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
💾 Einstellungen speichern 💾 Einstellungen speichern
@@ -718,6 +730,8 @@
document.getElementById("maxTime").value = data.maxTime || 300; document.getElementById("maxTime").value = data.maxTime || 300;
document.getElementById("maxTimeDisplay").value = document.getElementById("maxTimeDisplay").value =
data.maxTimeDisplay || 20; data.maxTimeDisplay || 20;
document.getElementById("minTimeForLeaderboard").value =
data.minTimeForLeaderboard || 5;
}) })
.catch((error) => .catch((error) =>
showMessage("Fehler beim Laden der Einstellungen", "error") showMessage("Fehler beim Laden der Einstellungen", "error")
@@ -971,6 +985,9 @@
const maxTimeDisplay = parseInt( const maxTimeDisplay = parseInt(
document.getElementById("maxTimeDisplay").value document.getElementById("maxTimeDisplay").value
); );
const minTimeForLeaderboard = parseInt(
document.getElementById("minTimeForLeaderboard").value
);
fetch("/api/set-max-time", { fetch("/api/set-max-time", {
method: "POST", method: "POST",
@@ -981,7 +998,9 @@
"maxTime=" + "maxTime=" +
encodeURIComponent(maxTime) + encodeURIComponent(maxTime) +
"&maxTimeDisplay=" + "&maxTimeDisplay=" +
encodeURIComponent(maxTimeDisplay), encodeURIComponent(maxTimeDisplay) +
"&minTimeForLeaderboard=" +
encodeURIComponent(minTimeForLeaderboard),
}) })
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {

View File

@@ -52,6 +52,7 @@ lib_deps =
adafruit/Adafruit PN532@^1.3.4 adafruit/Adafruit PN532@^1.3.4
[env:esp32thing] [env:esp32thing]
board = esp32thing_plus board = esp32thing_plus
monitor_speed = 115200 monitor_speed = 115200
@@ -87,14 +88,41 @@ lib_deps =
mlesniew/PicoMQTT@^1.3.0 mlesniew/PicoMQTT@^1.3.0
adafruit/Adafruit PN532@^1.3.4 adafruit/Adafruit PN532@^1.3.4
[env:esp32-s3-devkitc-1] [env:um_feathers3]
board = esp32-s3-devkitc-1 board = um_feathers3
monitor_speed = 115200 monitor_speed = 115200
board_upload.flash_size = 16MB board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv board_build.partitions = default_16MB.csv
board_upload.wait_for_upload_port = false
build_flags = build_flags =
-DARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_CDC_ON_BOOT=1
-DBATTERY_PIN=35 -D BATTERY_PIN=35
-D ARDUINO_USB_MODE=1
lib_deps =
bblanchon/ArduinoJson@^7.4.1
esp32async/ESPAsyncWebServer@^3.7.7
esp32async/AsyncTCP@^3.4.2
mlesniew/PicoMQTT@^1.3.0
adafruit/Adafruit PN532@^1.3.4
[env:um_feathers3_debug]
board = um_feathers3
board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv
board_upload.wait_for_upload_port = false
build_flags =
-D ARDUINO_USB_CDC_ON_BOOT=1
-D BATTERY_PIN=35
-D ARDUINO_USB_MODE=0
build_type = debug
debug_speed = 12000
debug_tool = esp-builtin
upload_port = COM5
monitor_speed = 115200
monitor_port = COM7
lib_deps = lib_deps =
bblanchon/ArduinoJson@^7.4.1 bblanchon/ArduinoJson@^7.4.1
esp32async/ESPAsyncWebServer@^3.7.7 esp32async/ESPAsyncWebServer@^3.7.7

View File

@@ -526,6 +526,15 @@ void sendTimeToOnlineAPI(int lane, String uid, float timeInSeconds) {
// Funktionen für lokales Leaderboard // Funktionen für lokales Leaderboard
void addLocalTime(String uid, String name, unsigned long timeMs) { void addLocalTime(String uid, String name, unsigned long timeMs) {
// Prüfe minimale Zeit für Leaderboard-Eintrag
if (timeMs < minTimeForLeaderboard) {
Serial.printf(
"Zeit zu kurz für Leaderboard: %s (%s) - %.2fs (Minimum: %.2fs)\n",
name.c_str(), uid.c_str(), timeMs / 1000.0,
minTimeForLeaderboard / 1000.0);
return; // Zeit wird nicht ins Leaderboard eingetragen
}
LocalTime newTime; LocalTime newTime;
newTime.uid = uid; newTime.uid = uid;
newTime.name = name; newTime.name = name;

View File

@@ -72,7 +72,9 @@ bool learningMode = false;
int learningStep = 0; // 0=Start1, 1=Stop1, 2=Start2, 3=Stop2 int learningStep = 0; // 0=Start1, 1=Stop1, 2=Start2, 3=Stop2
unsigned long maxTimeBeforeReset = 300000; // 5 Minuten default 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 unsigned long minTimeForLeaderboard =
5000; // 5 Sekunden minimum für Leaderboard (in ms)
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 bool startCompetition = false; // Flag, ob der Timer gestartet wurde

View File

@@ -82,6 +82,7 @@ void saveSettings() {
preferences.begin("settings", false); preferences.begin("settings", false);
preferences.putULong("maxTime", maxTimeBeforeReset); preferences.putULong("maxTime", maxTimeBeforeReset);
preferences.putULong("maxTimeDisplay", maxTimeDisplay); preferences.putULong("maxTimeDisplay", maxTimeDisplay);
preferences.putULong("minTime", minTimeForLeaderboard);
preferences.putUInt("gamemode", gamemode); preferences.putUInt("gamemode", gamemode);
preferences.putUInt("laneConfigType", laneConfigType); preferences.putUInt("laneConfigType", laneConfigType);
preferences.putUInt("lane1Diff", lane1DifficultyType); preferences.putUInt("lane1Diff", lane1DifficultyType);
@@ -93,6 +94,7 @@ void loadSettings() {
preferences.begin("settings", true); preferences.begin("settings", true);
maxTimeBeforeReset = preferences.getULong("maxTime", 300000); maxTimeBeforeReset = preferences.getULong("maxTime", 300000);
maxTimeDisplay = preferences.getULong("maxTimeDisplay", 20000); maxTimeDisplay = preferences.getULong("maxTimeDisplay", 20000);
minTimeForLeaderboard = preferences.getULong("minTime", 5000);
gamemode = preferences.getUInt("gamemode", 0); gamemode = preferences.getUInt("gamemode", 0);
laneConfigType = preferences.getUInt("laneConfigType", 0); laneConfigType = preferences.getUInt("laneConfigType", 0);
lane1DifficultyType = preferences.getUInt("lane1Diff", 0); lane1DifficultyType = preferences.getUInt("lane1Diff", 0);

View File

@@ -84,6 +84,12 @@ void setupRoutes() {
request->getParam("maxTimeDisplay", true)->value().toInt() * 1000; request->getParam("maxTimeDisplay", true)->value().toInt() * 1000;
changed = true; changed = true;
} }
if (request->hasParam("minTimeForLeaderboard", true)) {
minTimeForLeaderboard =
request->getParam("minTimeForLeaderboard", true)->value().toInt() *
1000;
changed = true;
}
if (changed) { if (changed) {
saveSettings(); saveSettings();
DynamicJsonDocument doc(32); DynamicJsonDocument doc(32);
@@ -101,6 +107,7 @@ void setupRoutes() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
doc["maxTime"] = maxTimeBeforeReset / 1000; doc["maxTime"] = maxTimeBeforeReset / 1000;
doc["maxTimeDisplay"] = maxTimeDisplay / 1000; doc["maxTimeDisplay"] = maxTimeDisplay / 1000;
doc["minTimeForLeaderboard"] = minTimeForLeaderboard / 1000;
String result; String result;
serializeJson(doc, result); serializeJson(doc, result);
request->send(200, "application/json", result); request->send(200, "application/json", result);