128 lines
4.8 KiB
C
128 lines
4.8 KiB
C
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include <WiFi.h>
|
|
#include <WebServer.h>
|
|
#include <DNSServer.h>
|
|
#include "config.h"
|
|
|
|
static const char CAPTIVE_PORTAL_HTML[] PROGMEM = R"rawhtml(
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>EPaper Setup</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; max-width: 480px; margin: 40px auto; padding: 16px; }
|
|
h1 { font-size: 1.4em; }
|
|
label { display: block; margin-top: 12px; font-weight: bold; }
|
|
input { width: 100%; padding: 8px; box-sizing: border-box; margin-top: 4px; }
|
|
button { margin-top: 20px; padding: 10px 24px; background: #0078d4; color: #fff;
|
|
border: none; border-radius: 4px; font-size: 1em; cursor: pointer; }
|
|
button:hover { background: #005a9e; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>EPaper Display Setup</h1>
|
|
<form method="POST" action="/save">
|
|
<label for="ssid">WiFi SSID</label>
|
|
<input id="ssid" name="ssid" type="text" placeholder="Netzwerkname" required>
|
|
|
|
<label for="pass">WiFi Password</label>
|
|
<input id="pass" name="pass" type="password" placeholder="Passwort (leer lassen wenn kein Passwort)">
|
|
|
|
<label for="api_url">API URL</label>
|
|
<input id="api_url" name="api_url" type="url" placeholder="http://192.168.1.100:3000" required>
|
|
|
|
<label for="display_id">Display ID</label>
|
|
<input id="display_id" name="display_id" type="text" placeholder="1" value="1">
|
|
|
|
<label for="api_token">API Token (optional)</label>
|
|
<input id="api_token" name="api_token" type="text" placeholder="Bearer Token">
|
|
|
|
<button type="submit">Speichern & Neustart</button>
|
|
</form>
|
|
</body>
|
|
</html>
|
|
)rawhtml";
|
|
|
|
static const char CAPTIVE_PORTAL_SAVED_HTML[] PROGMEM = R"rawhtml(
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Gespeichert</title>
|
|
<style>body{font-family:Arial,sans-serif;text-align:center;padding:40px;}</style>
|
|
</head>
|
|
<body>
|
|
<h1>Konfiguration gespeichert!</h1>
|
|
<p>Das Gerät startet jetzt neu...</p>
|
|
</body>
|
|
</html>
|
|
)rawhtml";
|
|
|
|
/**
|
|
* Start a captive WiFi access point for initial configuration.
|
|
* Creates AP "EPaper-Setup", serves a config form on port 80.
|
|
* POST /save persists the config and reboots.
|
|
* This function never returns.
|
|
*/
|
|
inline void startCaptivePortal(Config& config) {
|
|
const byte DNS_PORT = 53;
|
|
DNSServer dnsServer;
|
|
WebServer server(80);
|
|
|
|
// ── Start AP ──────────────────────────────────────────────────────────────
|
|
WiFi.mode(WIFI_AP);
|
|
WiFi.softAP("EPaper-Setup"); // open network, no password
|
|
|
|
IPAddress apIP = WiFi.softAPIP();
|
|
Serial.print("[Portal] AP started, IP: ");
|
|
Serial.println(apIP);
|
|
|
|
// ── DNS: redirect all queries to us ───────────────────────────────────────
|
|
dnsServer.start(DNS_PORT, "*", apIP);
|
|
|
|
// ── Routes ────────────────────────────────────────────────────────────────
|
|
server.on("/", HTTP_GET, [&server]() {
|
|
server.send_P(200, "text/html", CAPTIVE_PORTAL_HTML);
|
|
});
|
|
|
|
server.on("/save", HTTP_POST, [&server, &config]() {
|
|
if (server.hasArg("ssid") && server.hasArg("api_url")) {
|
|
config.wifi_ssid = server.arg("ssid");
|
|
config.wifi_password = server.arg("pass");
|
|
config.api_url = server.arg("api_url");
|
|
config.display_id = server.arg("display_id").length() > 0
|
|
? server.arg("display_id")
|
|
: "1";
|
|
config.api_token = server.arg("api_token");
|
|
config.save();
|
|
|
|
server.send_P(200, "text/html", CAPTIVE_PORTAL_SAVED_HTML);
|
|
delay(2000);
|
|
ESP.restart();
|
|
} else {
|
|
server.send(400, "text/plain", "Fehlende Felder: ssid und api_url sind Pflichtfelder.");
|
|
}
|
|
});
|
|
|
|
// ── Captive portal redirect (all unknown URLs → /) ────────────────────────
|
|
server.onNotFound([&server, &apIP]() {
|
|
// Some OSes check a specific URL; redirect them all to our form
|
|
server.sendHeader("Location", String("http://") + apIP.toString() + "/", true);
|
|
server.send(302, "text/plain", "");
|
|
});
|
|
|
|
server.begin();
|
|
Serial.println("[Portal] HTTP server started");
|
|
|
|
// ── Main loop (blocks forever) ────────────────────────────────────────────
|
|
for (;;) {
|
|
dnsServer.processNextRequest();
|
|
server.handleClient();
|
|
yield();
|
|
}
|
|
}
|