NTP, send Voltage to Frontend
This commit is contained in:
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<!-- Meta Tags -->
|
<!-- Meta Tags -->
|
||||||
@@ -255,6 +255,7 @@
|
|||||||
<div>IP-Adresse: <span id="ipAddress">Laden...</span></div>
|
<div>IP-Adresse: <span id="ipAddress">Laden...</span></div>
|
||||||
<div>Kanal: <span id="channel">Laden...</span></div>
|
<div>Kanal: <span id="channel">Laden...</span></div>
|
||||||
<div>MAC-Adresse: <span id="macAddress">Laden...</span></div>
|
<div>MAC-Adresse: <span id="macAddress">Laden...</span></div>
|
||||||
|
<div>Internet: <span id="isOnline">Laden...</span></div>
|
||||||
<div>Freier Speicher: <span id="freeMemory">Laden...</span></div>
|
<div>Freier Speicher: <span id="freeMemory">Laden...</span></div>
|
||||||
<div>
|
<div>
|
||||||
Verbundene Buttons: <span id="connectedButtons">Laden...</span>
|
Verbundene Buttons: <span id="connectedButtons">Laden...</span>
|
||||||
@@ -325,8 +326,9 @@
|
|||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
});
|
});
|
||||||
document.getElementById("currentTime").textContent =
|
document.getElementById(
|
||||||
`System Zeit: ${timeString}`;
|
"currentTime"
|
||||||
|
).textContent = `System Zeit: ${timeString}`;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("currentTime").textContent =
|
document.getElementById("currentTime").textContent =
|
||||||
"Aktuelle Zeit: Fehler beim Laden";
|
"Aktuelle Zeit: Fehler beim Laden";
|
||||||
@@ -356,7 +358,7 @@
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(
|
console.log(
|
||||||
"Zeit konnte nicht geladen werden, verwende Browser-Zeit",
|
"Zeit konnte nicht geladen werden, verwende Browser-Zeit"
|
||||||
);
|
);
|
||||||
syncWithBrowserTime();
|
syncWithBrowserTime();
|
||||||
});
|
});
|
||||||
@@ -401,7 +403,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Verbindungsfehler beim Setzen der Zeit", "error"),
|
showMessage("Verbindungsfehler beim Setzen der Zeit", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,7 +440,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Verbindungsfehler beim Setzen der Zeit", "error"),
|
showMessage("Verbindungsfehler beim Setzen der Zeit", "error")
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -459,7 +461,7 @@
|
|||||||
data.maxTimeDisplay || 20;
|
data.maxTimeDisplay || 20;
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Fehler beim Laden der Einstellungen", "error"),
|
showMessage("Fehler beim Laden der Einstellungen", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,6 +476,9 @@
|
|||||||
data.channel || "Unbekannt";
|
data.channel || "Unbekannt";
|
||||||
document.getElementById("macAddress").textContent =
|
document.getElementById("macAddress").textContent =
|
||||||
data.mac || "Unbekannt";
|
data.mac || "Unbekannt";
|
||||||
|
document.getElementById("isOnline").textContent = data.isOnline
|
||||||
|
? "Ja"
|
||||||
|
: "Nein";
|
||||||
document.getElementById("freeMemory").textContent =
|
document.getElementById("freeMemory").textContent =
|
||||||
(data.freeMemory || 0) + " Bytes";
|
(data.freeMemory || 0) + " Bytes";
|
||||||
document.getElementById("connectedButtons").textContent =
|
document.getElementById("connectedButtons").textContent =
|
||||||
@@ -499,7 +504,7 @@
|
|||||||
loadLocations();
|
loadLocations();
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Fehler beim Laden der Lizenz", "error"),
|
showMessage("Fehler beim Laden der Lizenz", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +542,7 @@
|
|||||||
data.password || "";
|
data.password || "";
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Fehler beim Laden der WLAN-Einstellungen", "error"),
|
showMessage("Fehler beim Laden der WLAN-Einstellungen", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +564,7 @@
|
|||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
"Der Server wird nach dem setzten neu gestartet. Fortsetzten?",
|
"Der Server wird nach dem setzten neu gestartet. Fortsetzten?"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
@@ -570,19 +575,21 @@
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
body: `ssid=${encodeURIComponent(ssid)}&password=${encodeURIComponent(password)}`,
|
body: `ssid=${encodeURIComponent(
|
||||||
|
ssid
|
||||||
|
)}&password=${encodeURIComponent(password)}`,
|
||||||
})
|
})
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"WLAN-Einstellungen erfolgreich gespeichert!",
|
"WLAN-Einstellungen erfolgreich gespeichert!",
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showMessage(
|
showMessage(
|
||||||
data.error || "Fehler beim Speichern der WLAN-Einstellungen",
|
data.error || "Fehler beim Speichern der WLAN-Einstellungen",
|
||||||
"error",
|
"error"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -593,10 +600,10 @@
|
|||||||
function updateOTAButtonAccess(licenseLevel) {
|
function updateOTAButtonAccess(licenseLevel) {
|
||||||
const otaButton = document.getElementById("otaUpdateBtn");
|
const otaButton = document.getElementById("otaUpdateBtn");
|
||||||
const otarestrictionNotice = document.getElementById(
|
const otarestrictionNotice = document.getElementById(
|
||||||
"otaRestrictionNotice",
|
"otaRestrictionNotice"
|
||||||
);
|
);
|
||||||
const otacurrentLevelSpan = document.getElementById(
|
const otacurrentLevelSpan = document.getElementById(
|
||||||
"currentLicenseLevel",
|
"currentLicenseLevel"
|
||||||
);
|
);
|
||||||
|
|
||||||
const level = parseInt(licenseLevel) || 0;
|
const level = parseInt(licenseLevel) || 0;
|
||||||
@@ -625,14 +632,14 @@
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Buttons führen das Update erfolgreich aus!",
|
"Buttons führen das Update erfolgreich aus!",
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showMessage("Fehler beim Senden der MQTT Message", "error");
|
showMessage("Fehler beim Senden der MQTT Message", "error");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Verbindungsfehler beim MQTT Publish", "error"),
|
showMessage("Verbindungsfehler beim MQTT Publish", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,10 +648,10 @@
|
|||||||
const wifiSubmitBtn = document.getElementById("wifiSubmitBtn");
|
const wifiSubmitBtn = document.getElementById("wifiSubmitBtn");
|
||||||
const wifiForm = document.getElementById("wifiForm");
|
const wifiForm = document.getElementById("wifiForm");
|
||||||
const wifiRestrictionNotice = document.getElementById(
|
const wifiRestrictionNotice = document.getElementById(
|
||||||
"wifiRestrictionNotice",
|
"wifiRestrictionNotice"
|
||||||
);
|
);
|
||||||
const wifiCurrentLevelSpan = document.getElementById(
|
const wifiCurrentLevelSpan = document.getElementById(
|
||||||
"currentLicenseLevel",
|
"currentLicenseLevel"
|
||||||
);
|
);
|
||||||
|
|
||||||
const level = parseInt(licenseLevel) || 0;
|
const level = parseInt(licenseLevel) || 0;
|
||||||
@@ -679,14 +686,14 @@
|
|||||||
) {
|
) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"OTA Update erfordert Lizenz Level 2 oder höher",
|
"OTA Update erfordert Lizenz Level 2 oder höher",
|
||||||
"error",
|
"error"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
"Möchten Sie wirklich ein OTA Update durchführen? Das Gerät wird während des Updates neu gestartet.",
|
"Möchten Sie wirklich ein OTA Update durchführen? Das Gerät wird während des Updates neu gestartet."
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
window.location.href = "/update";
|
window.location.href = "/update";
|
||||||
@@ -701,7 +708,7 @@
|
|||||||
|
|
||||||
const maxTime = parseInt(document.getElementById("maxTime").value);
|
const maxTime = parseInt(document.getElementById("maxTime").value);
|
||||||
const maxTimeDisplay = parseInt(
|
const maxTimeDisplay = parseInt(
|
||||||
document.getElementById("maxTimeDisplay").value,
|
document.getElementById("maxTimeDisplay").value
|
||||||
);
|
);
|
||||||
|
|
||||||
fetch("/api/set-max-time", {
|
fetch("/api/set-max-time", {
|
||||||
@@ -720,7 +727,7 @@
|
|||||||
if (data.success) {
|
if (data.success) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Einstellungen erfolgreich gespeichert!",
|
"Einstellungen erfolgreich gespeichert!",
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showMessage("Fehler beim Speichern der Einstellungen", "error");
|
showMessage("Fehler beim Speichern der Einstellungen", "error");
|
||||||
@@ -738,7 +745,7 @@
|
|||||||
if (data.success) {
|
if (data.success) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Beste Zeiten erfolgreich zurückgesetzt!",
|
"Beste Zeiten erfolgreich zurückgesetzt!",
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showMessage("Fehler beim Zurücksetzen", "error");
|
showMessage("Fehler beim Zurücksetzen", "error");
|
||||||
@@ -786,8 +793,9 @@
|
|||||||
// Anlern-Anweisung aktualisieren
|
// Anlern-Anweisung aktualisieren
|
||||||
function updateLearningInstruction() {
|
function updateLearningInstruction() {
|
||||||
if (learningStep < learningSteps.length) {
|
if (learningStep < learningSteps.length) {
|
||||||
document.getElementById("learningInstruction").innerHTML =
|
document.getElementById(
|
||||||
`Drücken Sie jetzt den Button für: <strong>${learningSteps[learningStep]}</strong>`;
|
"learningInstruction"
|
||||||
|
).innerHTML = `Drücken Sie jetzt den Button für: <strong>${learningSteps[learningStep]}</strong>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +822,7 @@
|
|||||||
if (learningStep > 0) {
|
if (learningStep > 0) {
|
||||||
showMessage(
|
showMessage(
|
||||||
`${learningSteps[learningStep - 1]} erfolgreich angelernt!`,
|
`${learningSteps[learningStep - 1]} erfolgreich angelernt!`,
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -836,13 +844,13 @@
|
|||||||
if (data.success) {
|
if (data.success) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Button-Zuweisungen erfolgreich zurückgesetzt!",
|
"Button-Zuweisungen erfolgreich zurückgesetzt!",
|
||||||
"success",
|
"success"
|
||||||
);
|
);
|
||||||
loadSystemInfo();
|
loadSystemInfo();
|
||||||
} else {
|
} else {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Fehler beim Zurücksetzen der Button-Zuweisungen",
|
"Fehler beim Zurücksetzen der Button-Zuweisungen",
|
||||||
"error",
|
"error"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -857,22 +865,46 @@
|
|||||||
.then((data) => {
|
.then((data) => {
|
||||||
let statusText = "Button-Status:\n\n";
|
let statusText = "Button-Status:\n\n";
|
||||||
statusText += `Bahn 1 Start: ${
|
statusText += `Bahn 1 Start: ${
|
||||||
data.lane1Start ? "Konfiguriert" : "Nicht konfiguriert"
|
data.lane1Start
|
||||||
|
? `Konfiguriert${
|
||||||
|
data.lane1StartVoltage !== undefined
|
||||||
|
? " (Batterystand: " + data.lane1StartVoltage + " %)"
|
||||||
|
: ""
|
||||||
|
}`
|
||||||
|
: "Nicht konfiguriert"
|
||||||
}\n`;
|
}\n`;
|
||||||
statusText += `Bahn 1 Stop: ${
|
statusText += `Bahn 1 Stop: ${
|
||||||
data.lane1Stop ? "Konfiguriert" : "Nicht konfiguriert"
|
data.lane1Stop
|
||||||
|
? `Konfiguriert${
|
||||||
|
data.lane1StopVoltage !== undefined
|
||||||
|
? " (Batterystand: " + data.lane1StopVoltage + " %)"
|
||||||
|
: ""
|
||||||
|
}`
|
||||||
|
: "Nicht konfiguriert"
|
||||||
}\n`;
|
}\n`;
|
||||||
statusText += `Bahn 2 Start: ${
|
statusText += `Bahn 2 Start: ${
|
||||||
data.lane2Start ? "Konfiguriert" : "Nicht konfiguriert"
|
data.lane2Start
|
||||||
|
? `Konfiguriert${
|
||||||
|
data.lane2StartVoltage !== undefined
|
||||||
|
? " (Batterystand: " + data.lane2StartVoltage + " %)"
|
||||||
|
: ""
|
||||||
|
}`
|
||||||
|
: "Nicht konfiguriert"
|
||||||
}\n`;
|
}\n`;
|
||||||
statusText += `Bahn 2 Stop: ${
|
statusText += `Bahn 2 Stop: ${
|
||||||
data.lane2Stop ? "Konfiguriert" : "Nicht konfiguriert"
|
data.lane2Stop
|
||||||
|
? `Konfiguriert${
|
||||||
|
data.lane2StopVoltage !== undefined
|
||||||
|
? " (Batterystand: " + data.lane2StopVoltage + " %)"
|
||||||
|
: ""
|
||||||
|
}`
|
||||||
|
: "Nicht konfiguriert"
|
||||||
}\n`;
|
}\n`;
|
||||||
|
|
||||||
alert(statusText);
|
alert(statusText);
|
||||||
})
|
})
|
||||||
.catch((error) =>
|
.catch((error) =>
|
||||||
showMessage("Fehler beim Laden des Button-Status", "error"),
|
showMessage("Fehler beim Laden des Button-Status", "error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,7 +957,7 @@
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(
|
console.log(
|
||||||
"Aktueller Standort konnte nicht geladen werden:",
|
"Aktueller Standort konnte nicht geladen werden:",
|
||||||
error,
|
error
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -934,10 +966,10 @@
|
|||||||
function updateLocationAccess(licenseLevel) {
|
function updateLocationAccess(licenseLevel) {
|
||||||
const locationSubmitBtn = document.getElementById("locationSubmitBtn");
|
const locationSubmitBtn = document.getElementById("locationSubmitBtn");
|
||||||
const locationRestrictionNotice = document.getElementById(
|
const locationRestrictionNotice = document.getElementById(
|
||||||
"locationRestrictionNotice",
|
"locationRestrictionNotice"
|
||||||
);
|
);
|
||||||
const locationCurrentLevelSpan = document.getElementById(
|
const locationCurrentLevelSpan = document.getElementById(
|
||||||
"currentLocationLicenseLevel",
|
"currentLocationLicenseLevel"
|
||||||
);
|
);
|
||||||
const locationSelect = document.getElementById("locationSelect");
|
const locationSelect = document.getElementById("locationSelect");
|
||||||
|
|
||||||
@@ -975,7 +1007,7 @@
|
|||||||
) {
|
) {
|
||||||
showMessage(
|
showMessage(
|
||||||
"Standort-Konfiguration erfordert Lizenz Level 3 oder höher",
|
"Standort-Konfiguration erfordert Lizenz Level 3 oder höher",
|
||||||
"error",
|
"error"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,59 +157,64 @@ void handleHeartbeatTopic(const char *topic, const char *payload) {
|
|||||||
* berechnet den Ladezustand und sendet ein JSON an das Frontend.
|
* berechnet den Ladezustand und sendet ein JSON an das Frontend.
|
||||||
*/
|
*/
|
||||||
void handleBatteryTopic(const char *topic, const char *payload) {
|
void handleBatteryTopic(const char *topic, const char *payload) {
|
||||||
int batteryLevel = 0;
|
float batteryLevelV = 0;
|
||||||
|
int batteryLevelP = 0;
|
||||||
String topicStr(topic);
|
String topicStr(topic);
|
||||||
int lastSlash = topicStr.lastIndexOf('/');
|
int lastSlash = topicStr.lastIndexOf('/');
|
||||||
if (lastSlash < 0)
|
if (lastSlash < 0)
|
||||||
return;
|
return;
|
||||||
String macStr = topicStr.substring(lastSlash + 1);
|
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)
|
// Parse payload for timestamp (optional, falls im Payload enthalten)
|
||||||
StaticJsonDocument<128> payloadDoc;
|
StaticJsonDocument<128> payloadDoc;
|
||||||
if (payload && strlen(payload) > 0 &&
|
if (payload && strlen(payload) > 0 &&
|
||||||
deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
deserializeJson(payloadDoc, payload) == DeserializationError::Ok) {
|
||||||
if (payloadDoc.containsKey("voltage")) {
|
if (payloadDoc.containsKey("voltage")) {
|
||||||
batteryLevel = payloadDoc["voltage"];
|
batteryLevelV = payloadDoc["voltage"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Berechne die Prozentzahl des Batteriestands für eine 1S LIPO batteryLevel
|
// Berechne die Prozentzahl des Batteriestands für eine 1S LIPO batteryLevel
|
||||||
// sind Volts
|
// sind Volts
|
||||||
// Hier wird angenommen, dass 3.7V 100% entspricht und 3.0V 0%
|
// 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 (batteryLevelV < 3200) {
|
||||||
if (batteryLevel < 3200) {
|
batteryLevelP = 0; // 0% bei 3.2V
|
||||||
batteryLevel = 0; // 0% bei 3.0V
|
} else if (batteryLevelV > 3700) {
|
||||||
} else if (batteryLevel > 3700) {
|
batteryLevelP = 100; // 100% bei 3.7V
|
||||||
batteryLevel = 100; // 100% bei 3.7V
|
|
||||||
} else {
|
} else {
|
||||||
batteryLevel = map(batteryLevel, 3000, 3700, 0, 100); // Linear Mapping
|
batteryLevelP = map(batteryLevelV, 3200, 3700, 0, 100); // Linear Mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
auto macBytes = macStringToBytes(macStr.c_str());
|
||||||
|
String buttonType = "unknown";
|
||||||
|
if (memcmp(macBytes.data(), buttonConfigs.start1.mac, 6) == 0) {
|
||||||
|
buttonType = "start1";
|
||||||
|
buttonConfigs.start1.voltage = batteryLevelP;
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop1.mac, 6) == 0) {
|
||||||
|
buttonType = "stop1";
|
||||||
|
buttonConfigs.stop1.voltage = batteryLevelP;
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.start2.mac, 6) == 0) {
|
||||||
|
buttonType = "start2";
|
||||||
|
buttonConfigs.start2.voltage = batteryLevelP;
|
||||||
|
} else if (memcmp(macBytes.data(), buttonConfigs.stop2.mac, 6) == 0) {
|
||||||
|
buttonType = "stop2";
|
||||||
|
buttonConfigs.stop2.voltage = batteryLevelP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON bauen
|
// JSON bauen
|
||||||
StaticJsonDocument<128> doc;
|
StaticJsonDocument<128> doc;
|
||||||
doc["button"] = buttonType;
|
doc["button"] = buttonType;
|
||||||
doc["mac"] = macStr;
|
doc["mac"] = macStr;
|
||||||
doc["batteryLevel"] = batteryLevel;
|
doc["batteryLevel"] = batteryLevelP;
|
||||||
|
|
||||||
String json;
|
String json;
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
pushUpdateToFrontend(
|
pushUpdateToFrontend(
|
||||||
json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
json); // Diese Funktion schickt das JSON an alle WebSocket-Clients
|
||||||
// Serial.printf("Published heartbeat JSON: %s\n", json.c_str());
|
|
||||||
|
// Serial.printf("Battery level for %s (%s): %d%%\n", buttonType.c_str(),
|
||||||
|
macStr.c_str(), batteryLevelP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
|
||||||
const char *BACKEND_SERVER = "http://db.reptilfpv.de:3000";
|
const char *BACKEND_SERVER = "http://db.reptilfpv.de:3000";
|
||||||
String BACKEND_TOKEN =
|
extern String licence; // Declare licence as an external variable defined elsewhere
|
||||||
licence; // Use the licence as the token for authentication
|
String BACKEND_TOKEN = licence; // Use the licence as the token for authentication
|
||||||
|
|
||||||
bool backendOnline() {
|
bool backendOnline() {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::array<uint8_t, 6> macStringToBytes(const char *macStr) {
|
std::array<uint8_t, 6> macStringToBytes(const char *macStr) {
|
||||||
std::array<uint8_t, 6> bytes;
|
std::array<uint8_t, 6> bytes;
|
||||||
sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &bytes[0], &bytes[1],
|
sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &bytes[0], &bytes[1],
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ struct TimerData {
|
|||||||
struct ButtonConfig {
|
struct ButtonConfig {
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
bool isAssigned = false;
|
bool isAssigned = false;
|
||||||
|
float voltage = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ButtonConfigs {
|
struct ButtonConfigs {
|
||||||
|
|||||||
@@ -49,6 +49,29 @@ String getCurrentTimeJSON() {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void syncTimeWithNTP(const char *ntpServer = "pool.ntp.org",
|
||||||
|
long gmtOffset_sec = 3600, int daylightOffset_sec = 0) {
|
||||||
|
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
|
||||||
|
Serial.println("Warte auf NTP-Zeit (max 5s)...");
|
||||||
|
struct tm timeinfo;
|
||||||
|
unsigned long start = millis();
|
||||||
|
bool synced = false;
|
||||||
|
while (millis() - start < 5000) {
|
||||||
|
if (getLocalTime(&timeinfo, 10)) { // 10ms Timeout pro Versuch
|
||||||
|
synced = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(10); // Kurze Pause, damit der Loop nicht blockiert
|
||||||
|
}
|
||||||
|
if (synced) {
|
||||||
|
Serial.println("\nNTP-Zeit synchronisiert!");
|
||||||
|
Serial.printf("Aktuelle Zeit: %02d:%02d:%02d\n", timeinfo.tm_hour,
|
||||||
|
timeinfo.tm_min, timeinfo.tm_sec);
|
||||||
|
} else {
|
||||||
|
Serial.println("\nNTP-Sync fehlgeschlagen (Timeout nach 5s)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hilfsfunktion: Setzt die Systemzeit auf den angegebenen Zeitstempel.
|
// Hilfsfunktion: Setzt die Systemzeit auf den angegebenen Zeitstempel.
|
||||||
bool setSystemTime(long timestamp) {
|
bool setSystemTime(long timestamp) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|||||||
@@ -143,9 +143,13 @@ void setupRoutes() {
|
|||||||
[](AsyncWebServerRequest *request) {
|
[](AsyncWebServerRequest *request) {
|
||||||
DynamicJsonDocument doc(128);
|
DynamicJsonDocument doc(128);
|
||||||
doc["lane1Start"] = buttonConfigs.start1.isAssigned;
|
doc["lane1Start"] = buttonConfigs.start1.isAssigned;
|
||||||
|
doc["lane1StartVoltage"] = buttonConfigs.start1.voltage;
|
||||||
doc["lane1Stop"] = buttonConfigs.stop1.isAssigned;
|
doc["lane1Stop"] = buttonConfigs.stop1.isAssigned;
|
||||||
|
doc["lane1StopVoltage"] = buttonConfigs.stop1.voltage;
|
||||||
doc["lane2Start"] = buttonConfigs.start2.isAssigned;
|
doc["lane2Start"] = buttonConfigs.start2.isAssigned;
|
||||||
|
doc["lane2StartVoltage"] = buttonConfigs.start2.voltage;
|
||||||
doc["lane2Stop"] = buttonConfigs.stop2.isAssigned;
|
doc["lane2Stop"] = buttonConfigs.stop2.isAssigned;
|
||||||
|
doc["lane2StopVoltage"] = buttonConfigs.stop2.voltage;
|
||||||
String result;
|
String result;
|
||||||
serializeJson(doc, result);
|
serializeJson(doc, result);
|
||||||
request->send(200, "application/json", result);
|
request->send(200, "application/json", result);
|
||||||
@@ -181,7 +185,7 @@ void setupRoutes() {
|
|||||||
if (buttonConfigs.stop2.isAssigned)
|
if (buttonConfigs.stop2.isAssigned)
|
||||||
connected++;
|
connected++;
|
||||||
doc["connectedButtons"] = connected;
|
doc["connectedButtons"] = connected;
|
||||||
|
doc["isOnline"] = isInternetAvailable() ? true : false;
|
||||||
doc["valid"] = checkLicence() > 0 ? "Ja" : "Nein";
|
doc["valid"] = checkLicence() > 0 ? "Ja" : "Nein";
|
||||||
doc["tier"] = checkLicence();
|
doc["tier"] = checkLicence();
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,14 @@
|
|||||||
|
|
||||||
#include "licenceing.h"
|
#include "licenceing.h"
|
||||||
#include "master.h"
|
#include "master.h"
|
||||||
|
#include "timesync.h"
|
||||||
|
|
||||||
String uniqueSSID;
|
String uniqueSSID;
|
||||||
|
|
||||||
PrettyOTA OTAUpdates;
|
PrettyOTA OTAUpdates;
|
||||||
|
|
||||||
String getUniqueSSID();
|
String getUniqueSSID();
|
||||||
|
bool isInternetAvailable();
|
||||||
|
|
||||||
// Initialisiert das WLAN als Access Point oder Station und startet mDNS/OTA.
|
// Initialisiert das WLAN als Access Point oder Station und startet mDNS/OTA.
|
||||||
void setupWifi() {
|
void setupWifi() {
|
||||||
@@ -48,6 +50,9 @@ void setupWifi() {
|
|||||||
Serial.println("Erfolgreich mit WLAN verbunden!");
|
Serial.println("Erfolgreich mit WLAN verbunden!");
|
||||||
Serial.print("IP Adresse: ");
|
Serial.print("IP Adresse: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
|
if (isInternetAvailable) {
|
||||||
|
syncTimeWithNTP();
|
||||||
|
} // Synchronisiere Zeit mit NTP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only wait for connection if ssidSTA and passwordSTA are set
|
// Only wait for connection if ssidSTA and passwordSTA are set
|
||||||
@@ -95,4 +100,9 @@ String getUniqueSSID() {
|
|||||||
return String("AquaCross-") + String(uniqueId);
|
return String("AquaCross-") + String(uniqueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WiFi als Access Point
|
// Prüft, ob das Internet erreichbar ist (z.B. durch Ping auf 8.8.8.8)
|
||||||
|
bool isInternetAvailable() {
|
||||||
|
WiFiClient client;
|
||||||
|
// Versuche, eine Verbindung zu Googles DNS auf Port 53 herzustellen
|
||||||
|
return client.connect("8.8.8.8", 53);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user