Protocol running.

This commit is contained in:
Holger Weber
2026-02-13 00:30:34 +01:00
parent 098c577142
commit 42e9c4d97b
6 changed files with 173 additions and 41 deletions

View File

@@ -1,16 +1,12 @@
#include "EggDuino.h"
#include <ArduinoJson.h>
#include <DNSServer.h>
namespace {
const char *kConfigPath = "/config.json";
const char *kApSsid = "EggDuino";
const uint16_t kDnsPort = 53;
const IPAddress kApIp(192, 168, 4, 1);
const IPAddress kApSubnet(255, 255, 255, 0);
const char *kWifiSsid = "Sternenlabor";
const char *kWifiPassword = "!Sternenlabor99!";
WebServer server(80);
DNSServer dnsServer;
bool configStoreReady = false;
ConfigParameter *findParameter(const String &key) {
@@ -38,12 +34,14 @@ void handleRoot() {
<title>EggDuino Konfiguration</title>
<style>
body { font-family: "Segoe UI", sans-serif; margin: 20px; background: #f3f6fb; color: #1a1a1a; }
main { max-width: 560px; margin: 0 auto; background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
main { max-width: 760px; margin: 0 auto; background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
h1 { margin-top: 0; font-size: 1.35rem; }
label { display: block; margin: 14px 0 6px; font-weight: 600; }
input[type='number'] { width: 100%; padding: 10px; border: 1px solid #c7d2e5; border-radius: 8px; box-sizing: border-box; }
button { margin-top: 18px; border: 0; background: #0b5ed7; color: white; padding: 10px 14px; border-radius: 8px; cursor: pointer; }
#status { margin-top: 12px; min-height: 1.2em; }
#log { margin-top: 20px; border: 1px solid #d6dfef; border-radius: 8px; background: #0f172a; color: #d2e3ff; padding: 10px; height: 220px; overflow-y: auto; white-space: pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.9rem; }
#logTitle { margin-top: 24px; margin-bottom: 8px; font-weight: 700; }
</style>
</head>
<body>
@@ -52,8 +50,12 @@ button { margin-top: 18px; border: 0; background: #0b5ed7; color: white; padding
<form id="cfgForm"></form>
<button id="saveBtn" type="button">Speichern</button>
<div id="status"></div>
<div id="logTitle">Logs</div>
<div id="log"></div>
</main>
<script>
let lastSeq = 0;
async function loadConfig() {
const resp = await fetch('/api/config');
if (!resp.ok) throw new Error('Konfiguration konnte nicht geladen werden');
@@ -93,6 +95,22 @@ async function saveConfig() {
status.textContent = 'Gespeichert';
}
async function pollLogs() {
const box = document.getElementById('log');
const resp = await fetch('/api/logs?since=' + lastSeq);
if (!resp.ok) {
return;
}
const payload = await resp.json();
(payload.logs || []).forEach(entry => {
box.textContent += entry.text + '\n';
});
if (typeof payload.lastSeq === 'number') {
lastSeq = payload.lastSeq;
}
box.scrollTop = box.scrollHeight;
}
(async function init() {
const status = document.getElementById('status');
try {
@@ -109,6 +127,8 @@ async function saveConfig() {
status.textContent = e.message;
}
});
pollLogs();
setInterval(pollLogs, 800);
})();
</script>
</body>
@@ -118,14 +138,6 @@ async function saveConfig() {
server.send(200, "text/html", kPage);
}
void redirectToPortal() {
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.sendHeader("Location", String("http://") + WiFi.softAPIP().toString() + "/", true);
server.send(302, "text/plain", "");
}
void handleGetConfig() {
if (!configStoreReady && !initConfigStore()) {
server.send(500, "text/plain", "Config storage not available");
@@ -160,6 +172,14 @@ void handlePostConfig() {
// penServo.write(penState);
server.send(200, "application/json", buildConfigJson());
}
void handleGetLogs() {
uint32_t since = 0;
if (server.hasArg("since")) {
since = static_cast<uint32_t>(server.arg("since").toInt());
}
server.send(200, "application/json", buildLogsJson(since));
}
} // namespace
ConfigParameter configParameters[] = {
@@ -284,28 +304,30 @@ bool applyConfigJson(const String &payload, String &errorMessage) {
}
void startWebInterface() {
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(kApIp, kApIp, kApSubnet);
WiFi.softAP(kApSsid);
dnsServer.start(kDnsPort, "*", WiFi.softAPIP());
WiFi.mode(WIFI_STA);
WiFi.begin(kWifiSsid, kWifiPassword);
const unsigned long connectStart = millis();
const unsigned long connectTimeoutMs = 20000;
while (WiFi.status() != WL_CONNECTED && millis() - connectStart < connectTimeoutMs) {
delay(250);
}
initConfigStore();
Serial.print("Config AP IP: ");
Serial.println(WiFi.softAPIP());
if (WiFi.status() == WL_CONNECTED) {
Serial.println(String("WLAN verbunden, IP: ") + WiFi.localIP().toString());
} else {
Serial.println("WLAN Verbindung fehlgeschlagen");
}
server.on("/", HTTP_GET, handleRoot);
server.on("/api/config", HTTP_GET, handleGetConfig);
server.on("/api/config", HTTP_POST, handlePostConfig);
server.on("/generate_204", HTTP_GET, redirectToPortal);
server.on("/gen_204", HTTP_GET, redirectToPortal);
server.on("/hotspot-detect.html", HTTP_GET, redirectToPortal);
server.on("/library/test/success.html", HTTP_GET, redirectToPortal);
server.on("/ncsi.txt", HTTP_GET, redirectToPortal);
server.on("/connecttest.txt", HTTP_GET, redirectToPortal);
server.onNotFound(redirectToPortal);
server.on("/api/logs", HTTP_GET, handleGetLogs);
server.onNotFound(handleRoot);
server.begin();
}
void handleWebInterface() {
dnsServer.processNextRequest();
server.handleClient();
}