#include "WebUI.h" #include "../util/Version.h" #include void WebUI::begin(Settings& settings, WiFiManager& wifi, MoistureSensor& moisture, FaceRenderer& face, WebhookService& webhook, unsigned long bootMs) { auto sendPortalRedirect = [&]() { String target = String("http://") + wifi.apIp().toString() + "/"; _server.sendHeader("Location", target, true); _server.send(302, "text/plain", ""); }; _server.on("/", HTTP_GET, [&]() { String mode = (wifi.mode() == NET_AP_SETUP) ? "Setup AP" : "Station"; String wifiSsid = settings.wifiSsid(); String currentSsid = wifi.ssid(); String page = "

FacePlant

" "

Firmware v" + String(PB_VERSION) + "

" "

Wi-Fi

" "

Mode: " + mode + "

" "

Connected SSID: " + (currentSsid.length() ? currentSsid : "(not connected)") + "

" "

Saved SSID: " + (wifiSsid.length() ? wifiSsid : "(none)") + "

" "

Setup AP: " + String(wifi.setupSsid()) + " / " + wifi.apIp().toString() + "

" "
" "
" "
" "
" "
" "Leave password blank to keep saved password for the same SSID.

" " " "" "

" "
" "
" "

" "

" "
" "
" "

" "" "
" "

Status (JSON)

" "

OTA Update

"; _server.send(200, "text/html", page); }); _server.on("/wifi", HTTP_POST, [&]() { String action = _server.hasArg("action") ? _server.arg("action") : "connect"; if (action == "forget") { wifi.clearAndStartSetupAP(); } else { String ssid = _server.hasArg("ssid") ? _server.arg("ssid") : settings.wifiSsid(); String pass = ""; if (_server.hasArg("pass") && _server.arg("pass").length() > 0) { pass = _server.arg("pass"); } else if (ssid == settings.wifiSsid()) { pass = settings.wifiPass(); } if (ssid.length() > 0) wifi.saveAndConnect(ssid, pass); } _server.sendHeader("Location", "/"); _server.send(303); }); _server.on("/config", HTTP_POST, [&]() { if (_server.hasArg("plant")) settings.setPlantProfile(_server.arg("plant")); settings.setKidsMode(_server.hasArg("kids")); settings.setWebhookEnabled(_server.hasArg("wh_en")); if (_server.hasArg("wh")) settings.setWebhookUrl(_server.arg("wh")); _server.sendHeader("Location", "/"); _server.send(303); }); _server.on("/status", HTTP_GET, [&]() { JsonDocument doc; doc["device"] = "FacePlant"; doc["version"] = PB_VERSION; doc["net_mode"] = (wifi.mode() == NET_AP_SETUP) ? "setup_ap" : "sta"; doc["setup_ssid"] = wifi.setupSsid(); doc["ip"] = wifi.ip().toString(); doc["ssid"] = wifi.ssid(); doc["saved_ssid"] = settings.wifiSsid(); doc["wifi_connected"] = wifi.connected(); doc["moisture_pct"] = moisture.percent(); doc["raw"] = moisture.raw(); doc["kids_mode"] = settings.kidsMode(); doc["dead_mode"] = face.isDeadMode(); doc["uptime_ms"] = millis() - bootMs; String out; serializeJson(doc, out); _server.send(200, "application/json", out); }); // Captive portal compatibility endpoints used by common OS network checkers. _server.on("/generate_204", HTTP_GET, [&]() { sendPortalRedirect(); }); // Android _server.on("/gen_204", HTTP_GET, [&]() { sendPortalRedirect(); }); // Android alt _server.on("/hotspot-detect.html", HTTP_GET, [&]() { sendPortalRedirect(); }); // iOS/macOS _server.on("/library/test/success.html", HTTP_GET, [&]() { sendPortalRedirect(); }); _server.on("/ncsi.txt", HTTP_GET, [&]() { sendPortalRedirect(); }); // Windows _server.on("/connecttest.txt", HTTP_GET, [&]() { sendPortalRedirect(); }); // Windows alt _server.on("/fwlink", HTTP_GET, [&]() { sendPortalRedirect(); }); // Windows alt _server.onNotFound([&]() { if (wifi.mode() == NET_AP_SETUP) { sendPortalRedirect(); return; } _server.send(404, "text/plain", "Not found"); }); _server.begin(); } void WebUI::loop() { _server.handleClient(); }