Consolidate the UI (#1537)

This commit is contained in:
Darrell 2025-02-10 19:54:40 -05:00 committed by GitHub
parent 69c3818653
commit 5ad56da68c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 5815 additions and 3629 deletions

View File

@ -20,6 +20,7 @@ build_flags =
-fipa-pta -fipa-pta
-fno-exceptions -fno-exceptions
-flto=auto -flto=auto
-fpermissive
-Wall -Wall
-Wextra -Wextra
-Wformat=2 -Wformat=2
@ -49,11 +50,10 @@ build_unflags =
-fexceptions -fexceptions
-fno-lto -fno-lto
framework = arduino framework = arduino
lib_ignore = AsyncTCP
lib_deps = lib_deps =
https://github.com/esphome/AsyncTCP.git#v2.0.1 ESP32Async/AsyncTCP
https://github.com/esphome/ESPAsyncWebServer.git#v3.1.0 ESP32Async/ESPAsyncWebServer
https://github.com/ESPresense/AsyncWiFiSettings.git#1.0.10 https://github.com/ESPresense/HeadlessWiFiSettings.git#v1.1.7
https://github.com/ESPresense/NimBLE-Arduino.git https://github.com/ESPresense/NimBLE-Arduino.git
marvinroger/AsyncMqttClient@^0.9.0 marvinroger/AsyncMqttClient@^0.9.0
bblanchon/ArduinoJson@^6.21.3 bblanchon/ArduinoJson@^6.21.3

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "string_utils.h" #include "string_utils.h"
#include <Adafruit_AHTX0.h> #include <Adafruit_AHTX0.h>
@ -41,8 +41,8 @@ namespace AHTX0
void ConnectToWifi() void ConnectToWifi()
{ {
AHTX0_I2c_Bus = AsyncWiFiSettings.integer("AHTX0_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); AHTX0_I2c_Bus = HeadlessWiFiSettings.integer("AHTX0_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
AHTX0_I2c = AsyncWiFiSettings.string("AHTX0_I2c", "", "I2C address (0x38 or 0x39)"); AHTX0_I2c = HeadlessWiFiSettings.string("AHTX0_I2c", "", "I2C address (0x38 or 0x39)");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include "string_utils.h" #include "string_utils.h"
@ -74,8 +74,8 @@ namespace BH1750
void ConnectToWifi() void ConnectToWifi()
{ {
BH1750_I2c_Bus = AsyncWiFiSettings.integer("BH1750_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); BH1750_I2c_Bus = HeadlessWiFiSettings.integer("BH1750_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BH1750_I2c = AsyncWiFiSettings.string("BH1750_I2c", "", "I2C address (0x23 or 0x5C)"); BH1750_I2c = HeadlessWiFiSettings.string("BH1750_I2c", "", "I2C address (0x23 or 0x5C)");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "string_utils.h" #include "string_utils.h"
#include <Adafruit_BME280.h> #include <Adafruit_BME280.h>
@ -52,8 +52,8 @@ namespace BME280
void ConnectToWifi() void ConnectToWifi()
{ {
BME280_I2c_Bus = AsyncWiFiSettings.integer("BME280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); BME280_I2c_Bus = HeadlessWiFiSettings.integer("BME280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BME280_I2c = AsyncWiFiSettings.string("BME280_I2c", "", "I2C address (0x76 or 0x77)"); BME280_I2c = HeadlessWiFiSettings.string("BME280_I2c", "", "I2C address (0x76 or 0x77)");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "string_utils.h" #include "string_utils.h"
#include <Adafruit_BMP085.h> #include <Adafruit_BMP085.h>
@ -39,8 +39,8 @@ namespace BMP180
void ConnectToWifi() void ConnectToWifi()
{ {
BMP180_I2c_Bus = AsyncWiFiSettings.integer("BMP180_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); BMP180_I2c_Bus = HeadlessWiFiSettings.integer("BMP180_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BMP180_I2c = AsyncWiFiSettings.string("BMP180_I2c", "", "I2C address (0x77)"); BMP180_I2c = HeadlessWiFiSettings.string("BMP180_I2c", "", "I2C address (0x77)");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "string_utils.h" #include "string_utils.h"
#include <Adafruit_BMP280.h> #include <Adafruit_BMP280.h>
@ -48,8 +48,8 @@ namespace BMP280
void ConnectToWifi() void ConnectToWifi()
{ {
BMP280_I2c_Bus = AsyncWiFiSettings.integer("BMP280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); BMP280_I2c_Bus = HeadlessWiFiSettings.integer("BMP280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BMP280_I2c = AsyncWiFiSettings.string("BMP280_I2c", "", "I2C address (0x76 or 0x77)"); BMP280_I2c = HeadlessWiFiSettings.string("BMP280_I2c", "", "I2C address (0x76 or 0x77)");
} }
void SerialReport() void SerialReport()

View File

@ -3,7 +3,7 @@
#include "defaults.h" #include "defaults.h"
#include <Arduino.h> #include <Arduino.h>
#include <sstream> #include <sstream>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
namespace BleFingerprintCollection { namespace BleFingerprintCollection {
// Public (externed) // Public (externed)
@ -152,28 +152,28 @@ bool Config(String &id, String &json) {
} }
void ConnectToWifi() { void ConnectToWifi() {
knownMacs = AsyncWiFiSettings.string("known_macs", DEFAULT_KNOWN_MACS, "Known BLE mac addresses (no colons, space seperated)"); knownMacs = HeadlessWiFiSettings.string("known_macs", DEFAULT_KNOWN_MACS, "Known BLE mac addresses (no colons, space seperated)");
knownIrks = AsyncWiFiSettings.string("known_irks", DEFAULT_KNOWN_IRKS, "Known BLE identity resolving keys, should be 32 hex chars space seperated"); knownIrks = HeadlessWiFiSettings.string("known_irks", DEFAULT_KNOWN_IRKS, "Known BLE identity resolving keys, should be 32 hex chars space seperated");
query = AsyncWiFiSettings.string("query", DEFAULT_QUERY, "Query device ids for characteristics (eg. flora:)"); query = HeadlessWiFiSettings.string("query", DEFAULT_QUERY, "Query device ids for characteristics (eg. flora:)");
requeryMs = AsyncWiFiSettings.integer("requery_ms", 30, 3600, DEFAULT_REQUERY_MS / 1000, "Requery interval in seconds") * 1000; requeryMs = HeadlessWiFiSettings.integer("requery_ms", 30, 3600, DEFAULT_REQUERY_MS / 1000, "Requery interval in seconds") * 1000;
countIds = AsyncWiFiSettings.string("count_ids", DEFAULT_COUNT_IDS, "Include id prefixes (space seperated)"); countIds = HeadlessWiFiSettings.string("count_ids", DEFAULT_COUNT_IDS, "Include id prefixes (space seperated)");
countEnter = AsyncWiFiSettings.floating("count_enter", 0, 100, DEFAULT_COUNT_ENTER, "Start counting devices less than distance (in meters)"); countEnter = HeadlessWiFiSettings.floating("count_enter", 0, 100, DEFAULT_COUNT_ENTER, "Start counting devices less than distance (in meters)");
countExit = AsyncWiFiSettings.floating("count_exit", 0, 100, DEFAULT_COUNT_EXIT, "Stop counting devices greater than distance (in meters)"); countExit = HeadlessWiFiSettings.floating("count_exit", 0, 100, DEFAULT_COUNT_EXIT, "Stop counting devices greater than distance (in meters)");
countMs = AsyncWiFiSettings.integer("count_ms", 0, 3000000, DEFAULT_COUNT_MS, "Include devices with age less than (in ms)"); countMs = HeadlessWiFiSettings.integer("count_ms", 0, 3000000, DEFAULT_COUNT_MS, "Include devices with age less than (in ms)");
include = AsyncWiFiSettings.string("include", DEFAULT_INCLUDE, "Include only sending these ids to mqtt (eg. apple:iphone10-6 apple:iphone13-2)"); include = HeadlessWiFiSettings.string("include", DEFAULT_INCLUDE, "Include only sending these ids to mqtt (eg. apple:iphone10-6 apple:iphone13-2)");
exclude = AsyncWiFiSettings.string("exclude", DEFAULT_EXCLUDE, "Exclude sending these ids to mqtt (eg. exp:20 apple:iphone10-6)"); exclude = HeadlessWiFiSettings.string("exclude", DEFAULT_EXCLUDE, "Exclude sending these ids to mqtt (eg. exp:20 apple:iphone10-6)");
maxDistance = AsyncWiFiSettings.floating("max_dist", 0, 100, DEFAULT_MAX_DISTANCE, "Maximum distance to report (in meters)"); maxDistance = HeadlessWiFiSettings.floating("max_dist", 0, 100, DEFAULT_MAX_DISTANCE, "Maximum distance to report (in meters)");
skipDistance = AsyncWiFiSettings.floating("skip_dist", 0, 10, DEFAULT_SKIP_DISTANCE, "Report early if beacon has moved more than this distance (in meters)"); skipDistance = HeadlessWiFiSettings.floating("skip_dist", 0, 10, DEFAULT_SKIP_DISTANCE, "Report early if beacon has moved more than this distance (in meters)");
skipMs = AsyncWiFiSettings.integer("skip_ms", 0, 3000000, DEFAULT_SKIP_MS, "Skip reporting if message age is less that this (in milliseconds)"); skipMs = HeadlessWiFiSettings.integer("skip_ms", 0, 3000000, DEFAULT_SKIP_MS, "Skip reporting if message age is less that this (in milliseconds)");
rxRefRssi = AsyncWiFiSettings.integer("ref_rssi", -100, 100, DEFAULT_RX_REF_RSSI, "Rssi expected from a 0dBm transmitter at 1 meter (NOT used for iBeacons or Eddystone)"); rxRefRssi = HeadlessWiFiSettings.integer("ref_rssi", -100, 100, DEFAULT_RX_REF_RSSI, "Rssi expected from a 0dBm transmitter at 1 meter (NOT used for iBeacons or Eddystone)");
rxAdjRssi = AsyncWiFiSettings.integer("rx_adj_rssi", -100, 100, DEFAULT_RX_ADJ_RSSI, "Rssi adjustment for receiver (use only if you know this device has a weak antenna)"); rxAdjRssi = HeadlessWiFiSettings.integer("rx_adj_rssi", -100, 100, DEFAULT_RX_ADJ_RSSI, "Rssi adjustment for receiver (use only if you know this device has a weak antenna)");
absorption = AsyncWiFiSettings.floating("absorption", -100, 100, DEFAULT_ABSORPTION, "Factor used to account for absorption, reflection, or diffraction"); absorption = HeadlessWiFiSettings.floating("absorption", -100, 100, DEFAULT_ABSORPTION, "Factor used to account for absorption, reflection, or diffraction");
forgetMs = AsyncWiFiSettings.integer("forget_ms", 0, 3000000, DEFAULT_FORGET_MS, "Forget beacon if not seen for (in milliseconds)"); forgetMs = HeadlessWiFiSettings.integer("forget_ms", 0, 3000000, DEFAULT_FORGET_MS, "Forget beacon if not seen for (in milliseconds)");
txRefRssi = AsyncWiFiSettings.integer("tx_ref_rssi", -100, 100, DEFAULT_TX_REF_RSSI, "Rssi expected from this tx power at 1m (used for node iBeacon)"); txRefRssi = HeadlessWiFiSettings.integer("tx_ref_rssi", -100, 100, DEFAULT_TX_REF_RSSI, "Rssi expected from this tx power at 1m (used for node iBeacon)");
std::istringstream iss(knownIrks.c_str()); std::istringstream iss(knownIrks.c_str());
std::string irk_hex; std::string irk_hex;

View File

@ -1,7 +1,7 @@
#include "Button.h" #include "Button.h"
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "GUI.h" #include "GUI.h"
#include "defaults.h" #include "defaults.h"
@ -31,14 +31,14 @@ void Setup() {
void ConnectToWifi() { void ConnectToWifi() {
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"}; std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
button_1Type = AsyncWiFiSettings.dropdown("button_1_type", pinTypes, 0, "Button One pin type"); button_1Type = HeadlessWiFiSettings.dropdown("button_1_type", pinTypes, 0, "Button One pin type");
button_1Pin = AsyncWiFiSettings.integer("button_1_pin", -1, "Button One pin (-1 for disable)"); button_1Pin = HeadlessWiFiSettings.integer("button_1_pin", -1, "Button One pin (-1 for disable)");
button_1Timeout = AsyncWiFiSettings.floating("button_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button One timeout (in seconds)"); button_1Timeout = HeadlessWiFiSettings.floating("button_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button One timeout (in seconds)");
button_1Detected = button_1Type & 0x01 ? LOW : HIGH; button_1Detected = button_1Type & 0x01 ? LOW : HIGH;
button_2Type = AsyncWiFiSettings.dropdown("button_2_type", pinTypes, 0, "Button Two pin type"); button_2Type = HeadlessWiFiSettings.dropdown("button_2_type", pinTypes, 0, "Button Two pin type");
button_2Pin = AsyncWiFiSettings.integer("button_2_pin", -1, "Button Two pin (-1 for disable)"); button_2Pin = HeadlessWiFiSettings.integer("button_2_pin", -1, "Button Two pin (-1 for disable)");
button_2Timeout = AsyncWiFiSettings.floating("button_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button Two timeout (in seconds)"); button_2Timeout = HeadlessWiFiSettings.floating("button_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button Two timeout (in seconds)");
button_2Detected = button_2Type & 0x01 ? LOW : HIGH; button_2Detected = button_2Type & 0x01 ? LOW : HIGH;
} }

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include "string_utils.h" #include "string_utils.h"
@ -106,9 +106,9 @@ namespace DHT
void ConnectToWifi() void ConnectToWifi()
{ {
dht11Pin = AsyncWiFiSettings.integer("dht11_pin", -1, "DHT11 sensor pin (-1 for disable)"); dht11Pin = HeadlessWiFiSettings.integer("dht11_pin", -1, "DHT11 sensor pin (-1 for disable)");
dht22Pin = AsyncWiFiSettings.integer("dht22_pin", -1, "DHT22 sensor pin (-1 for disable)"); dht22Pin = HeadlessWiFiSettings.integer("dht22_pin", -1, "DHT22 sensor pin (-1 for disable)");
dhtTempOffset = AsyncWiFiSettings.floating("dhtTemp_offset", -40, 125, 0.0, "DHT temperature offset"); dhtTempOffset = HeadlessWiFiSettings.floating("dhtTemp_offset", -40, 125, 0.0, "DHT temperature offset");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include "string_utils.h" #include "string_utils.h"
@ -108,8 +108,8 @@ namespace DS18B20
void ConnectToWifi() void ConnectToWifi()
{ {
ds18b20Pin = AsyncWiFiSettings.integer("ds18b20_pin", -1, "DS18B20 sensor pin (-1 for disable)"); ds18b20Pin = HeadlessWiFiSettings.integer("ds18b20_pin", -1, "DS18B20 sensor pin (-1 for disable)");
dsTempOffset = AsyncWiFiSettings.floating("dsTemp_offset", -40, 125, 0.0, "DS18B20 temperature offset"); dsTempOffset = HeadlessWiFiSettings.floating("dsTemp_offset", -40, 125, 0.0, "DS18B20 temperature offset");
} }
void SerialReport() void SerialReport()

View File

@ -4,7 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "defaults.h" #include "defaults.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include "string_utils.h" #include "string_utils.h"
@ -26,8 +26,8 @@ namespace HX711
void ConnectToWifi() void ConnectToWifi()
{ {
sckPin = AsyncWiFiSettings.integer("HX711_sckPin", 0, "HX711 SCK (Clock) pin"); sckPin = HeadlessWiFiSettings.integer("HX711_sckPin", 0, "HX711 SCK (Clock) pin");
doutPin = AsyncWiFiSettings.integer("HX711_doutPin", 0, "HX711 DOUT (Data) pin"); doutPin = HeadlessWiFiSettings.integer("HX711_doutPin", 0, "HX711 DOUT (Data) pin");
} }
void SerialReport() void SerialReport()

View File

@ -134,6 +134,11 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
} }
} }
void onRestart(AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Restarting...");
ESP.restart();
}
void Init(AsyncWebServer *server) { void Init(AsyncWebServer *server) {
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
@ -146,12 +151,10 @@ void Init(AsyncWebServer *server) {
}); });
setupRoutes(server); // from ui_routes.h setupRoutes(server); // from ui_routes.h
server->on("/ui", HTTP_GET, [](AsyncWebServerRequest *request) {
request->redirect("/ui/"); server->on("/restart", HTTP_POST, onRestart);
});
server->on("/json", HTTP_GET, serveJson); server->on("/json", HTTP_GET, serveJson);
// Handle DELETE method for configs
server->on("/json/configs", HTTP_DELETE, [](AsyncWebServerRequest *request) { server->on("/json/configs", HTTP_DELETE, [](AsyncWebServerRequest *request) {
if (!request->hasParam("id")) { if (!request->hasParam("id")) {
request->send(400, "application/json", F("{\"error\":\"Missing required parameter: id\"}")); request->send(400, "application/json", F("{\"error\":\"Missing required parameter: id\"}"));

View File

@ -3,7 +3,7 @@
#include "I2C.h" #include "I2C.h"
#include <Adafruit_BME280.h> #include <Adafruit_BME280.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "defaults.h" #include "defaults.h"
#include "globals.h" #include "globals.h"
@ -18,15 +18,14 @@ int I2C_Bus_2_SDA = 0;
int I2C_Bus_2_SCL = 0; int I2C_Bus_2_SCL = 0;
void ConnectToWifi() { void ConnectToWifi() {
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#i2c-settings' target='_blank'>I2C Settings</a>", false);
I2C_Bus_1_SDA = AsyncWiFiSettings.integer("I2C_Bus_1_SDA", -1, 39, DEFAULT_I2C_BUS_1_SDA, "SDA pin (-1 to disable)"); I2C_Bus_1_SDA = HeadlessWiFiSettings.integer("I2C_Bus_1_SDA", -1, 39, DEFAULT_I2C_BUS_1_SDA, "SDA pin (-1 to disable)");
I2C_Bus_1_SCL = AsyncWiFiSettings.integer("I2C_Bus_1_SCL", -1, 39, DEFAULT_I2C_BUS_1_SCL, "SCL pin (-1 to disable)"); I2C_Bus_1_SCL = HeadlessWiFiSettings.integer("I2C_Bus_1_SCL", -1, 39, DEFAULT_I2C_BUS_1_SCL, "SCL pin (-1 to disable)");
I2C_Bus_2_SDA = AsyncWiFiSettings.integer("I2C_Bus_2_SDA", -1, 39, DEFAULT_I2C_BUS_2_SDA, "SDA pin (-1 to disable)"); I2C_Bus_2_SDA = HeadlessWiFiSettings.integer("I2C_Bus_2_SDA", -1, 39, DEFAULT_I2C_BUS_2_SDA, "SDA pin (-1 to disable)");
I2C_Bus_2_SCL = AsyncWiFiSettings.integer("I2C_Bus_2_SCL", -1, 39, DEFAULT_I2C_BUS_2_SCL, "SCL pin (-1 to disable)"); I2C_Bus_2_SCL = HeadlessWiFiSettings.integer("I2C_Bus_2_SCL", -1, 39, DEFAULT_I2C_BUS_2_SCL, "SCL pin (-1 to disable)");
I2CDebug = AsyncWiFiSettings.checkbox("I2CDebug", false, "Debug I2C addreses. Look at the serial log to get the correct address"); I2CDebug = HeadlessWiFiSettings.checkbox("I2CDebug", false, "Debug I2C addreses. Look at the serial log to get the correct address");
if (I2C_Bus_1_SDA != -1 && I2C_Bus_1_SDA != -1) { if (I2C_Bus_1_SDA != -1 && I2C_Bus_1_SDA != -1) {
I2C_Bus_1_Started = Wire.begin(I2C_Bus_1_SDA, I2C_Bus_1_SCL); I2C_Bus_1_Started = Wire.begin(I2C_Bus_1_SDA, I2C_Bus_1_SCL);

View File

@ -1,7 +1,7 @@
#include "LEDs.h" #include "LEDs.h"
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <WS2812FX.h> #include <WS2812FX.h>
#include "Motion.h" #include "Motion.h"
@ -34,22 +34,20 @@ void ConnectToWifi() {
std::vector<String> ledTypes = {"PWM", "PWM Inverted", "Addressable GRB", "Addressable GRBW", "Addressable RGB", "Addressable RGBW"}; std::vector<String> ledTypes = {"PWM", "PWM Inverted", "Addressable GRB", "Addressable GRBW", "Addressable RGB", "Addressable RGBW"};
std::vector<String> ledControlTypes = {"MQTT", "Status", "Motion", "Count"}; std::vector<String> ledControlTypes = {"MQTT", "Status", "Motion", "Count"};
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#leds' target='_blank'>LEDs</a>", false); led_1_type = HeadlessWiFiSettings.dropdown("led_1_type", ledTypes, DEFAULT_LED1_TYPE, "LED Type");
led_1_pin = HeadlessWiFiSettings.integer("led_1_pin", -1, 39, DEFAULT_LED1_PIN, "Pin (-1 to disable)");
led_1_cnt = HeadlessWiFiSettings.integer("led_1_cnt", -1, 39, DEFAULT_LED1_CNT, "Count (only applies to Addressable LEDs)");
led_1_cntrl = (ControlType)HeadlessWiFiSettings.dropdown("led_1_cntrl", ledControlTypes, DEFAULT_LED1_CNTRL, "LED Control");
led_1_type = AsyncWiFiSettings.dropdown("led_1_type", ledTypes, DEFAULT_LED1_TYPE, "LED Type"); led_2_type = HeadlessWiFiSettings.dropdown("led_2_type", ledTypes, 0, "LED Type");
led_1_pin = AsyncWiFiSettings.integer("led_1_pin", -1, 39, DEFAULT_LED1_PIN, "Pin (-1 to disable)"); led_2_pin = HeadlessWiFiSettings.integer("led_2_pin", -1, 39, -1, "Pin (-1 to disable)");
led_1_cnt = AsyncWiFiSettings.integer("led_1_cnt", -1, 39, DEFAULT_LED1_CNT, "Count (only applies to Addressable LEDs)"); led_2_cnt = HeadlessWiFiSettings.integer("led_2_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)");
led_1_cntrl = (ControlType)AsyncWiFiSettings.dropdown("led_1_cntrl", ledControlTypes, DEFAULT_LED1_CNTRL, "LED Control"); led_2_cntrl = (ControlType)HeadlessWiFiSettings.dropdown("led_2_cntrl", ledControlTypes, 0, "LED Control");
led_2_type = AsyncWiFiSettings.dropdown("led_2_type", ledTypes, 0, "LED Type"); led_3_type = HeadlessWiFiSettings.dropdown("led_3_type", ledTypes, 0, "LED Type");
led_2_pin = AsyncWiFiSettings.integer("led_2_pin", -1, 39, -1, "Pin (-1 to disable)"); led_3_pin = HeadlessWiFiSettings.integer("led_3_pin", -1, 39, -1, "Pin (-1 to disable)");
led_2_cnt = AsyncWiFiSettings.integer("led_2_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)"); led_3_cnt = HeadlessWiFiSettings.integer("led_3_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)");
led_2_cntrl = (ControlType)AsyncWiFiSettings.dropdown("led_2_cntrl", ledControlTypes, 0, "LED Control"); led_3_cntrl = (ControlType)HeadlessWiFiSettings.dropdown("led_3_cntrl", ledControlTypes, 0, "LED Control");
led_3_type = AsyncWiFiSettings.dropdown("led_3_type", ledTypes, 0, "LED Type");
led_3_pin = AsyncWiFiSettings.integer("led_3_pin", -1, 39, -1, "Pin (-1 to disable)");
led_3_cnt = AsyncWiFiSettings.integer("led_3_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)");
led_3_cntrl = (ControlType)AsyncWiFiSettings.dropdown("led_3_cntrl", ledControlTypes, 0, "LED Control");
leds.push_back(newLed(1, led_1_cntrl, led_1_type, led_1_pin, led_1_cnt)); leds.push_back(newLed(1, led_1_cntrl, led_1_type, led_1_pin, led_1_cnt));
leds.push_back(newLed(2, led_2_cntrl, led_2_type, led_2_pin, led_2_cnt)); leds.push_back(newLed(2, led_2_cntrl, led_2_type, led_2_pin, led_2_cnt));

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "BleFingerprint.h" #include "BleFingerprint.h"
#include <NimBLEClient.h> #include <NimBLEClient.h>
#include <NimBLEDevice.h> #include <NimBLEDevice.h>

View File

@ -1,7 +1,7 @@
#include "Motion.h" #include "Motion.h"
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "GUI.h" #include "GUI.h"
#include "defaults.h" #include "defaults.h"
@ -31,14 +31,14 @@ void Setup() {
void ConnectToWifi() { void ConnectToWifi() {
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"}; std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
pirType = AsyncWiFiSettings.dropdown("pir_type", pinTypes, 0, "PIR motion pin type"); pirType = HeadlessWiFiSettings.dropdown("pir_type", pinTypes, 0, "PIR motion pin type");
pirPin = AsyncWiFiSettings.integer("pir_pin", -1, "PIR motion pin (-1 for disable)"); pirPin = HeadlessWiFiSettings.integer("pir_pin", -1, "PIR motion pin (-1 for disable)");
pirTimeout = AsyncWiFiSettings.floating("pir_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "PIR motion timeout (in seconds)"); pirTimeout = HeadlessWiFiSettings.floating("pir_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "PIR motion timeout (in seconds)");
pirDetected = pirType & 0x01 ? LOW : HIGH; pirDetected = pirType & 0x01 ? LOW : HIGH;
radarType = AsyncWiFiSettings.dropdown("radar_type", pinTypes, 0, "Radar motion pin type"); radarType = HeadlessWiFiSettings.dropdown("radar_type", pinTypes, 0, "Radar motion pin type");
radarPin = AsyncWiFiSettings.integer("radar_pin", -1, "Radar motion pin (-1 for disable)"); radarPin = HeadlessWiFiSettings.integer("radar_pin", -1, "Radar motion pin (-1 for disable)");
radarTimeout = AsyncWiFiSettings.floating("radar_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Radar motion timeout (in seconds)"); radarTimeout = HeadlessWiFiSettings.floating("radar_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Radar motion timeout (in seconds)");
radarDetected = radarType & 0x01 ? LOW : HIGH; radarDetected = radarType & 0x01 ? LOW : HIGH;
} }

View File

@ -5,7 +5,7 @@
#include <sstream> #include <sstream>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include "BleFingerprint.h" #include "BleFingerprint.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
namespace NameModelHandler { namespace NameModelHandler {

View File

@ -1,7 +1,7 @@
#ifdef SENSORS #ifdef SENSORS
#include "SHT.h" #include "SHT.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <SHTSensor.h> #include <SHTSensor.h>
#include "defaults.h" #include "defaults.h"
@ -30,7 +30,7 @@ void Setup() {
} }
void ConnectToWifi() { void ConnectToWifi() {
bus = AsyncWiFiSettings.integer("SHT_I2c_Bus", 1, 2, -1, "I2C Bus (-1 to disable)"); bus = HeadlessWiFiSettings.integer("SHT_I2c_Bus", 1, 2, -1, "I2C Bus (-1 to disable)");
} }
void SerialReport() { void SerialReport() {

View File

@ -1,7 +1,7 @@
#ifdef SENSORS #ifdef SENSORS
#include "SensirionSGP30.h" #include "SensirionSGP30.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <SparkFun_SGP30_Arduino_Library.h> #include <SparkFun_SGP30_Arduino_Library.h>
#include "defaults.h" #include "defaults.h"
@ -41,8 +41,8 @@ void Setup() {
} }
void ConnectToWifi() { void ConnectToWifi() {
SGP30_I2c_Bus = AsyncWiFiSettings.integer("SGP30_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); SGP30_I2c_Bus = HeadlessWiFiSettings.integer("SGP30_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
SGP30_I2c = AsyncWiFiSettings.string("SGP30_I2c", "", "I2C address (0x58)"); SGP30_I2c = HeadlessWiFiSettings.string("SGP30_I2c", "", "I2C address (0x58)");
} }
void SerialReport() { void SerialReport() {

View File

@ -1,5 +1,5 @@
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "Network.h" #include "Network.h"
#include "SPIFFS.h" #include "SPIFFS.h"

View File

@ -1,7 +1,7 @@
#include "Switch.h" #include "Switch.h"
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include "GUI.h" #include "GUI.h"
#include "defaults.h" #include "defaults.h"
@ -31,14 +31,14 @@ void Setup() {
void ConnectToWifi() { void ConnectToWifi() {
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"}; std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
switch_1Type = AsyncWiFiSettings.dropdown("switch_1_type", pinTypes, 0, "Switch One pin type"); switch_1Type = HeadlessWiFiSettings.dropdown("switch_1_type", pinTypes, 0, "Switch One pin type");
switch_1Pin = AsyncWiFiSettings.integer("switch_1_pin", -1, "Switch One pin (-1 for disable)"); switch_1Pin = HeadlessWiFiSettings.integer("switch_1_pin", -1, "Switch One pin (-1 for disable)");
switch_1Timeout = AsyncWiFiSettings.floating("switch_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch One timeout (in seconds)"); switch_1Timeout = HeadlessWiFiSettings.floating("switch_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch One timeout (in seconds)");
switch_1Detected = switch_1Type & 0x01 ? LOW : HIGH; switch_1Detected = switch_1Type & 0x01 ? LOW : HIGH;
switch_2Type = AsyncWiFiSettings.dropdown("switch_2_type", pinTypes, 0, "Switch Two pin type"); switch_2Type = HeadlessWiFiSettings.dropdown("switch_2_type", pinTypes, 0, "Switch Two pin type");
switch_2Pin = AsyncWiFiSettings.integer("switch_2_pin", -1, "Switch Two pin (-1 for disable)"); switch_2Pin = HeadlessWiFiSettings.integer("switch_2_pin", -1, "Switch Two pin (-1 for disable)");
switch_2Timeout = AsyncWiFiSettings.floating("switch_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch Two timeout (in seconds)"); switch_2Timeout = HeadlessWiFiSettings.floating("switch_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch Two timeout (in seconds)");
switch_2Detected = switch_2Type & 0x01 ? LOW : HIGH; switch_2Detected = switch_2Type & 0x01 ? LOW : HIGH;
} }

View File

@ -4,7 +4,7 @@
#include "defaults.h" #include "defaults.h"
#include "mqtt.h" #include "mqtt.h"
#include "TSL2561.h" #include "TSL2561.h"
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <Adafruit_TSL2561_U.h> #include <Adafruit_TSL2561_U.h>
#include "string_utils.h" #include "string_utils.h"
@ -23,9 +23,9 @@ namespace TSL2561
void ConnectToWifi() void ConnectToWifi()
{ {
TSL2561_I2c_Bus = AsyncWiFiSettings.integer("TSL2561_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus"); TSL2561_I2c_Bus = HeadlessWiFiSettings.integer("TSL2561_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
TSL2561_I2c = AsyncWiFiSettings.string("TSL2561_I2c", "", "I2C address (0x39, 0x49 or 0x29)"); TSL2561_I2c = HeadlessWiFiSettings.string("TSL2561_I2c", "", "I2C address (0x39, 0x49 or 0x29)");
TSL2561_I2c_Gain = AsyncWiFiSettings.string("TSL2561_I2c_Gain", DEFAULT_TSL2561_I2C_GAIN, "Gain (auto, 1x or 16x)"); TSL2561_I2c_Gain = HeadlessWiFiSettings.string("TSL2561_I2c_Gain", DEFAULT_TSL2561_I2C_GAIN, "Gain (auto, 1x or 16x)");
} }
void SerialReport() void SerialReport()

View File

@ -5,7 +5,7 @@
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
#include "AsyncWiFiSettings.h" #include "HeadlessWiFiSettings.h"
#include "GUI.h" #include "GUI.h"
#include "HttpReleaseUpdate.h" #include "HttpReleaseUpdate.h"
#include "HttpWebServer.h" #include "HttpWebServer.h"
@ -186,10 +186,10 @@ bool SendDiscovery() {
} }
void ConnectToWifi() { void ConnectToWifi() {
autoUpdateEnabled = AsyncWiFiSettings.checkbox("auto_update", DEFAULT_AUTO_UPDATE, "Automatically update"); autoUpdateEnabled = HeadlessWiFiSettings.checkbox("auto_update", DEFAULT_AUTO_UPDATE, "Automatically update");
prerelease = AsyncWiFiSettings.checkbox("prerelease", false, "Include pre-released versions in auto-update"); prerelease = HeadlessWiFiSettings.checkbox("prerelease", false, "Include pre-released versions in auto-update");
arduinoOtaEnabled = AsyncWiFiSettings.checkbox("arduino_ota", DEFAULT_ARDUINO_OTA, "Arduino OTA Update"); arduinoOtaEnabled = HeadlessWiFiSettings.checkbox("arduino_ota", DEFAULT_ARDUINO_OTA, "Arduino OTA Update");
updateUrl = AsyncWiFiSettings.string("update", "", "If set will update from this url on next boot"); updateUrl = HeadlessWiFiSettings.string("update", "", "If set will update from this url on next boot");
} }
void MarkOtaSuccess() { void MarkOtaSuccess() {

View File

@ -132,33 +132,27 @@ void setupNetwork() {
WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);
GUI::Connected(false, false); GUI::Connected(false, false);
#ifdef VERSION room = HeadlessWiFiSettings.string("room", ESPMAC, "Room");
AsyncWiFiSettings.info("ESPresense Version: " + String(VERSION)); HeadlessWiFiSettings.string("wifi-ssid", "", "WiFi SSID");
#endif HeadlessWiFiSettings.pstring("wifi-password", "", "WiFi Password");
room = AsyncWiFiSettings.string("room", ESPMAC, "Room"); auto wifiTimeout = HeadlessWiFiSettings.integer("wifi_timeout", DEFAULT_WIFI_TIMEOUT, "Seconds to wait for WiFi before captive portal (-1 = forever)");
auto wifiTimeout = AsyncWiFiSettings.integer("wifi_timeout", DEFAULT_WIFI_TIMEOUT, "Seconds to wait for WiFi before captive portal (-1 = forever)"); auto portalTimeout = 1000UL * HeadlessWiFiSettings.integer("portal_timeout", DEFAULT_PORTAL_TIMEOUT, "Seconds to wait in captive portal before rebooting");
auto portalTimeout = 1000UL * AsyncWiFiSettings.integer("portal_timeout", DEFAULT_PORTAL_TIMEOUT, "Seconds to wait in captive portal before rebooting");
std::vector<String> ethernetTypes = {"None", "WT32-ETH01", "ESP32-POE", "WESP32", "QuinLED-ESP32", "TwilightLord-ESP32", "ESP32Deux", "KIT-VE", "LilyGO-T-ETH-POE", "GL-inet GL-S10 v2.1 Ethernet", "EST-PoE-32", "LilyGO-T-ETH-Lite (RTL8201)"}; std::vector<String> ethernetTypes = {"None", "WT32-ETH01", "ESP32-POE", "WESP32", "QuinLED-ESP32", "TwilightLord-ESP32", "ESP32Deux", "KIT-VE", "LilyGO-T-ETH-POE", "GL-inet GL-S10 v2.1 Ethernet", "EST-PoE-32", "LilyGO-T-ETH-Lite (RTL8201)"};
ethernetType = AsyncWiFiSettings.dropdown("eth", ethernetTypes, 0, "Ethernet Type"); ethernetType = HeadlessWiFiSettings.dropdown("eth", ethernetTypes, 0, "Ethernet Type");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#mqtt' target='_blank'>MQTT</a>", false); mqttHost = HeadlessWiFiSettings.string("mqtt_host", DEFAULT_MQTT_HOST, "Server");
mqttHost = AsyncWiFiSettings.string("mqtt_host", DEFAULT_MQTT_HOST, "Server"); mqttPort = HeadlessWiFiSettings.integer("mqtt_port", DEFAULT_MQTT_PORT, "Port");
mqttPort = AsyncWiFiSettings.integer("mqtt_port", DEFAULT_MQTT_PORT, "Port"); mqttUser = HeadlessWiFiSettings.pstring("mqtt_user", DEFAULT_MQTT_USER, "Username");
mqttUser = AsyncWiFiSettings.pstring("mqtt_user", DEFAULT_MQTT_USER, "Username"); mqttPass = HeadlessWiFiSettings.pstring("mqtt_pass", DEFAULT_MQTT_PASSWORD, "Password");
mqttPass = AsyncWiFiSettings.pstring("mqtt_pass", DEFAULT_MQTT_PASSWORD, "Password"); discovery = HeadlessWiFiSettings.checkbox("discovery", true, "Send to discovery topic");
discovery = AsyncWiFiSettings.checkbox("discovery", true, "Send to discovery topic"); homeAssistantDiscoveryPrefix = HeadlessWiFiSettings.string("discovery_prefix", DEFAULT_HA_DISCOVERY_PREFIX, "Home Assistant discovery topic prefix");
homeAssistantDiscoveryPrefix = AsyncWiFiSettings.string("discovery_prefix", DEFAULT_HA_DISCOVERY_PREFIX, "Home Assistant discovery topic prefix"); publishTele = HeadlessWiFiSettings.checkbox("pub_tele", true, "Send to telemetry topic");
publishTele = AsyncWiFiSettings.checkbox("pub_tele", true, "Send to telemetry topic"); publishRooms = HeadlessWiFiSettings.checkbox("pub_rooms_dep", false, "Send to rooms topic (deprecated in v4)");
publishRooms = AsyncWiFiSettings.checkbox("pub_rooms_dep", false, "Send to rooms topic (deprecated in v4)"); publishDevices = HeadlessWiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
publishDevices = AsyncWiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#updating' target='_blank'>Updating</a>", false);
Updater::ConnectToWifi(); Updater::ConnectToWifi();
AsyncWiFiSettings.info("<a href='ui/#settings' target='_blank'>Click here to edit other settings!</a>", false); HeadlessWiFiSettings.markExtra();
AsyncWiFiSettings.markExtra();
GUI::ConnectToWifi(); GUI::ConnectToWifi();
@ -184,13 +178,13 @@ void setupNetwork() {
#endif #endif
unsigned int connectProgress = 0; unsigned int connectProgress = 0;
AsyncWiFiSettings.onWaitLoop = [&connectProgress]() { HeadlessWiFiSettings.onWaitLoop = [&connectProgress]() {
GUI::Wifi(connectProgress++); GUI::Wifi(connectProgress++);
SerialImprov::Loop(true); SerialImprov::Loop(true);
return 50; return 50;
}; };
unsigned int portalProgress = 0; unsigned int portalProgress = 0;
AsyncWiFiSettings.onPortalWaitLoop = [&portalProgress, portalTimeout]() { HeadlessWiFiSettings.onPortalWaitLoop = [&portalProgress, portalTimeout]() {
GUI::Portal(portalProgress++); GUI::Portal(portalProgress++);
SerialImprov::Loop(false); SerialImprov::Loop(false);
@ -199,12 +193,12 @@ void setupNetwork() {
return 50; return 50;
}; };
AsyncWiFiSettings.onHttpSetup = HttpWebServer::Init; HeadlessWiFiSettings.onHttpSetup = HttpWebServer::Init;
AsyncWiFiSettings.hostname = "espresense-" + kebabify(room); HeadlessWiFiSettings.hostname = "espresense-" + kebabify(room);
bool success = false; bool success = false;
if (ethernetType > 0) success = Network.connect(ethernetType, 20, AsyncWiFiSettings.hostname.c_str()); if (ethernetType > 0) success = Network.connect(ethernetType, 20, HeadlessWiFiSettings.hostname.c_str());
if (!success && !AsyncWiFiSettings.connect(true, wifiTimeout)) if (!success && !HeadlessWiFiSettings.connect(true, wifiTimeout))
ESP.restart(); ESP.restart();
GUI::Connected(true, false); GUI::Connected(true, false);
@ -263,7 +257,7 @@ void setupNetwork() {
teleTopic = roomsTopic + "/telemetry"; teleTopic = roomsTopic + "/telemetry";
setTopic = roomsTopic + "/+/set"; setTopic = roomsTopic + "/+/set";
configTopic = CHANNEL + String("/settings/+/config"); configTopic = CHANNEL + String("/settings/+/config");
AsyncWiFiSettings.httpSetup(); HeadlessWiFiSettings.httpSetup();
Updater::MarkOtaSuccess(); Updater::MarkOtaSuccess();
} }
@ -356,8 +350,8 @@ void reconnect(TimerHandle_t xTimer) {
Serial.printf("%u Reconnecting to Network...\r\n", xPortGetCoreID()); Serial.printf("%u Reconnecting to Network...\r\n", xPortGetCoreID());
bool success = false; bool success = false;
if (ethernetType > 0) success = Network.connect(ethernetType, 2, AsyncWiFiSettings.hostname.c_str()); if (ethernetType > 0) success = Network.connect(ethernetType, 2, HeadlessWiFiSettings.hostname.c_str());
if (!success && !AsyncWiFiSettings.connect(true, 40)) if (!success && !HeadlessWiFiSettings.connect(true, 40))
ESP.restart(); ESP.restart();
} }
@ -370,7 +364,7 @@ void connectToMqtt() {
mqttClient.onConnect(onMqttConnect); mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onMessage(onMqttMessageRaw); mqttClient.onMessage(onMqttMessageRaw);
mqttClient.setClientId(AsyncWiFiSettings.hostname.c_str()); mqttClient.setClientId(HeadlessWiFiSettings.hostname.c_str());
mqttClient.setServer(mqttHost.c_str(), mqttPort); mqttClient.setServer(mqttHost.c_str(), mqttPort);
mqttClient.setWill(statusTopic.c_str(), 0, true, "offline"); mqttClient.setWill(statusTopic.c_str(), 0, true, "offline");
mqttClient.setCredentials(mqttUser.c_str(), mqttPass.c_str()); mqttClient.setCredentials(mqttUser.c_str(), mqttPass.c_str());

View File

@ -1,6 +1,6 @@
#include <Arduino.h> #include <Arduino.h>
#include <AsyncTCP.h> #include <AsyncTCP.h>
#include <AsyncWiFiSettings.h> #include <HeadlessWiFiSettings.h>
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include <NimBLEDevice.h> #include <NimBLEDevice.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,39 +6,39 @@
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <Arduino.h> #include <Arduino.h>
// app/immutable/entry/app.Cb2VW3WQ.js // app/immutable/entry/app.BJOsbrDb.js
const uint16_t APP_IMMUTABLE_ENTRY_APP_CB2VW3WQ_JS_L = 162; const uint16_t APP_IMMUTABLE_ENTRY_APP_BJOSBRDB_JS_L = 162;
const uint8_t APP_IMMUTABLE_ENTRY_APP_CB2VW3WQ_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_ENTRY_APP_BJOSBRDB_JS[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x44, 0x4e, 0xb5, 0x15, 0x82, 0x31, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x44, 0xce, 0x41, 0x0e, 0x82, 0x40,
0x10, 0x1e, 0x05, 0xa9, 0x0f, 0x6d, 0xa9, 0x90, 0x05, 0x98, 0x80, 0x17, 0xe3, 0xc5, 0x8f, 0x08, 0x0c, 0x05, 0xd0, 0xab, 0x10, 0xd6, 0x15, 0x0e, 0xc0, 0xce, 0xc4, 0xa5, 0x67, 0x30, 0xe3, 0x4c,
0x0e, 0xbb, 0xc3, 0xfd, 0x41, 0xaa, 0x93, 0x4f, 0x4d, 0x38, 0x60, 0xae, 0x77, 0xd5, 0x67, 0xa5, 0x49, 0x11, 0x67, 0x6a, 0xda, 0xd1, 0x80, 0x86, 0xbb, 0x6b, 0xe9, 0xc2, 0xd5, 0xeb, 0xa6, 0xff,
0x8f, 0xc0, 0x69, 0x28, 0x90, 0x34, 0x32, 0x08, 0x1a, 0x12, 0x34, 0x0d, 0x01, 0x81, 0x86, 0x86, 0xff, 0x29, 0x3f, 0x58, 0xea, 0x07, 0x9b, 0xa0, 0x0d, 0xc3, 0xd5, 0x40, 0x48, 0x86, 0x40, 0x34,
0x48, 0xa3, 0x42, 0xa6, 0x11, 0x80, 0xd1, 0x88, 0xcf, 0x7d, 0xc6, 0x30, 0x1c, 0x8f, 0x27, 0x42, 0x12, 0x90, 0x11, 0x21, 0x1b, 0x04, 0xc5, 0xa8, 0x20, 0x46, 0x86, 0x60, 0x94, 0x6d, 0x14, 0xce,
0x1f, 0xa3, 0x2b, 0x93, 0x4d, 0x98, 0x6f, 0xd7, 0xee, 0xb6, 0x1a, 0xdb, 0x32, 0x5c, 0xa8, 0x4b, 0x6d, 0xd7, 0xf5, 0x91, 0x9e, 0x65, 0xd6, 0xfe, 0xf8, 0x3e, 0x8d, 0xe7, 0xc3, 0xba, 0x74, 0x37,
0x97, 0x80, 0x9d, 0x99, 0x12, 0x28, 0x15, 0xa8, 0xff, 0x9e, 0x4b, 0xb3, 0x92, 0x46, 0x54, 0x83, 0x6d, 0x07, 0x5c, 0xf6, 0x06, 0xde, 0xc3, 0x30, 0x72, 0x42, 0xc0, 0xff, 0x2d, 0xea, 0x51, 0x69,
0x91, 0xe5, 0x6b, 0x4b, 0xd7, 0xac, 0xe8, 0x56, 0x40, 0x23, 0xba, 0xd2, 0x4a, 0x04, 0x56, 0x85, 0x8a, 0x75, 0xe2, 0x12, 0x64, 0xf5, 0x76, 0x0a, 0x4a, 0x3e, 0x80, 0x98, 0x67, 0xf5, 0x11, 0x39,
0x26, 0x49, 0xed, 0x62, 0xdf, 0xf2, 0xd2, 0x6a, 0x65, 0xc4, 0xda, 0x9a, 0x15, 0x95, 0x4f, 0x2a, 0xd4, 0x48, 0xf6, 0x52, 0xf7, 0xda, 0xdf, 0xbb, 0xfa, 0x2c, 0x61, 0xae, 0xbe, 0x4c, 0x51, 0x5e,
0xef, 0x3c, 0x32, 0x59, 0x9e, 0xaf, 0x59, 0x73, 0x01, 0x00, 0x73, 0xfb, 0xfb, 0x2a, 0xdf, 0x00, 0x28, 0x97, 0x3b, 0x87, 0xa4, 0xdb, 0xf0, 0x1d, 0x17, 0x00, 0x73, 0xaf, 0xe8, 0xb5, 0xdf, 0x00,
0x00, 0x00 0x00, 0x00
}; };
inline void serveAppImmutableEntryAppCb2Vw3WqJs(AsyncWebServerRequest* request) { inline void serveAppImmutableEntryAppBjOsbrDbJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_ENTRY_APP_CB2VW3WQ_JS, APP_IMMUTABLE_ENTRY_APP_CB2VW3WQ_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_ENTRY_APP_BJOSBRDB_JS, APP_IMMUTABLE_ENTRY_APP_BJOSBRDB_JS_L);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
request->send(response); request->send(response);
} }
// app/immutable/entry/start.7iSqqDB1.js // app/immutable/entry/start.BRWhmY9K.js
const uint16_t APP_IMMUTABLE_ENTRY_START_7ISQQDB1_JS_L = 62; const uint16_t APP_IMMUTABLE_ENTRY_START_BRWHMY9K_JS_L = 62;
const uint8_t APP_IMMUTABLE_ENTRY_START_7ISQQDB1_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_ENTRY_START_BRWHMY9K_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x73, 0x20, 0x61, 0x73, 0x20, 0x74, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x73, 0x20, 0x61, 0x73, 0x20, 0x74, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x74, 0x20, 0x61, 0x73, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x7d, 0x3b, 0x0a 0x7b, 0x74, 0x20, 0x61, 0x73, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x7d, 0x3b, 0x0a
}; };
inline void serveAppImmutableEntryStart_7iSqqDb1Js(AsyncWebServerRequest* request) { inline void serveAppImmutableEntryStartBrWhmY9KJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_ENTRY_START_7ISQQDB1_JS, APP_IMMUTABLE_ENTRY_START_7ISQQDB1_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_ENTRY_START_BRWHMY9K_JS, APP_IMMUTABLE_ENTRY_START_BRWHMY9K_JS_L);
request->send(response); request->send(response);
} }

View File

@ -6,94 +6,109 @@
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <Arduino.h> #include <Arduino.h>
// app/immutable/nodes/0.mRmfOCQ2.js // app/immutable/nodes/0.f-UXSzsA.js
const uint16_t APP_IMMUTABLE_NODES_0_MRMFOCQ2_JS_L = 88; const uint16_t APP_IMMUTABLE_NODES_0_F_UXSZSA_JS_L = 88;
const uint8_t APP_IMMUTABLE_NODES_0_MRMFOCQ2_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_0_F_UXSZSA_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x66, 0x20, 0x61, 0x73, 0x20, 0x65, 0x2c, 0x5f, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x66, 0x20, 0x61, 0x73, 0x20, 0x65, 0x2c, 0x5f, 0x20,
0x61, 0x73, 0x20, 0x6e, 0x7d, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x61, 0x73, 0x20, 0x6e, 0x7d, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75,
0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22,
0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x65, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x65, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d,
0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2c, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x69, 0x76, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2c, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x69, 0x76,
0x65, 0x72, 0x73, 0x61, 0x6c, 0x7d, 0x3b, 0x0a 0x65, 0x72, 0x73, 0x61, 0x6c, 0x7d, 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_0MRmfOcq2Js(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_0FUxSzsAJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_0_MRMFOCQ2_JS, APP_IMMUTABLE_NODES_0_MRMFOCQ2_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_0_F_UXSZSA_JS, APP_IMMUTABLE_NODES_0_F_UXSZSA_JS_L);
request->send(response); request->send(response);
} }
// app/immutable/nodes/1.0EiJ79V4.js // app/immutable/nodes/1.Qt5HEqQj.js
const uint16_t APP_IMMUTABLE_NODES_1_0EIJ79V4_JS_L = 66; const uint16_t APP_IMMUTABLE_NODES_1_QT5HEQQJ_JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_1_0EIJ79V4_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_1_QT5HEQQJ_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x45, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x45, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d, 0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_1_0EiJ79V4Js(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_1Qt5HEqQjJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_1_0EIJ79V4_JS, APP_IMMUTABLE_NODES_1_0EIJ79V4_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_1_QT5HEQQJ_JS, APP_IMMUTABLE_NODES_1_QT5HEQQJ_JS_L);
request->send(response); request->send(response);
} }
// app/immutable/nodes/2.Bxme43Dr.js // app/immutable/nodes/2.CAPvpTL7.js
const uint16_t APP_IMMUTABLE_NODES_2_BXME43DR_JS_L = 66; const uint16_t APP_IMMUTABLE_NODES_2_CAPVPTL7_JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_2_BXME43DR_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_2_CAPVPTL7_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x67, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x67, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d, 0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_2Bxme43DrJs(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_2CaPvpTl7Js(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_2_BXME43DR_JS, APP_IMMUTABLE_NODES_2_BXME43DR_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_2_CAPVPTL7_JS, APP_IMMUTABLE_NODES_2_CAPVPTL7_JS_L);
request->send(response); request->send(response);
} }
// app/immutable/nodes/3.CR6EXnD7.js // app/immutable/nodes/3.BRF1IttE.js
const uint16_t APP_IMMUTABLE_NODES_3_CR6EXND7_JS_L = 66; const uint16_t APP_IMMUTABLE_NODES_3_BRF1ITTE_JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_3_CR6EXND7_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_3_BRF1ITTE_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x69, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x69, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d, 0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_3Cr6EXnD7Js(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_3Brf1IttEJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_3_CR6EXND7_JS, APP_IMMUTABLE_NODES_3_CR6EXND7_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_3_BRF1ITTE_JS, APP_IMMUTABLE_NODES_3_BRF1ITTE_JS_L);
request->send(response); request->send(response);
} }
// app/immutable/nodes/4.DrdVjXcz.js // app/immutable/nodes/4.hR3DFtNr.js
const uint16_t APP_IMMUTABLE_NODES_4_DRDVJXCZ_JS_L = 66; const uint16_t APP_IMMUTABLE_NODES_4_HR3DFTNR_JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_4_DRDVJXCZ_JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_4_HR3DFTNR_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x6a, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x6a, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d, 0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_4DrdVjXczJs(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_4HR3DFtNrJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_4_DRDVJXCZ_JS, APP_IMMUTABLE_NODES_4_DRDVJXCZ_JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_4_HR3DFTNR_JS, APP_IMMUTABLE_NODES_4_HR3DFTNR_JS_L);
request->send(response); request->send(response);
} }
// app/immutable/nodes/5.BXsMqBj-.js // app/immutable/nodes/5.B-_jSokT.js
const uint16_t APP_IMMUTABLE_NODES_5_BXSMQBJ__JS_L = 66; const uint16_t APP_IMMUTABLE_NODES_5_B__JSOKT_JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_5_BXSMQBJ__JS[] PROGMEM = { const uint8_t APP_IMMUTABLE_NODES_5_B__JSOKT_JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x44, 0x6d, 0x32, 0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x51, 0x43, 0x6b, 0x7a, 0x42, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d, 0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a 0x3b, 0x0a
}; };
inline void serveAppImmutableNodes_5BXsMqBjJs(AsyncWebServerRequest* request) { inline void serveAppImmutableNodes_5BJSokTJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_5_BXSMQBJ__JS, APP_IMMUTABLE_NODES_5_BXSMQBJ__JS_L); AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_5_B__JSOKT_JS, APP_IMMUTABLE_NODES_5_B__JSOKT_JS_L);
request->send(response);
}
// app/immutable/nodes/6.pYVBaJC-.js
const uint16_t APP_IMMUTABLE_NODES_6_PYVBAJC__JS_L = 66;
const uint8_t APP_IMMUTABLE_NODES_6_PYVBAJC__JS[] PROGMEM = {
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7b, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x6d, 0x7d, 0x66, 0x72,
0x6f, 0x6d, 0x22, 0x2e, 0x2e, 0x2f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x2f, 0x42, 0x7a, 0x45,
0x66, 0x4d, 0x2d, 0x79, 0x78, 0x2e, 0x6a, 0x73, 0x22, 0x3b, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x7b, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x7d,
0x3b, 0x0a
};
inline void serveAppImmutableNodes_6PYvBaJcJs(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", APP_IMMUTABLE_NODES_6_PYVBAJC__JS, APP_IMMUTABLE_NODES_6_PYVBAJC__JS_L);
request->send(response); request->send(response);
} }

View File

@ -7,51 +7,50 @@
#include <Arduino.h> #include <Arduino.h>
// devices.html // devices.html
const uint16_t DEVICES_HTML_L = 685; const uint16_t DEVICES_HTML_L = 672;
const uint8_t DEVICES_HTML[] PROGMEM = { const uint8_t DEVICES_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x9d, 0x54, 0xc7, 0x96, 0xe3, 0x2a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x93, 0xe5, 0xb6, 0xe3, 0x20,
0x10, 0x5d, 0xbb, 0xbf, 0xa2, 0x9a, 0x17, 0x2c, 0x9d, 0x23, 0xa1, 0xce, 0xd1, 0xea, 0x17, 0x67, 0x10, 0x80, 0x7f, 0xf7, 0x3e, 0xc5, 0x5c, 0x56, 0x9a, 0x9c, 0xd3, 0x90, 0x75, 0x6d, 0xee, 0xba,
0x36, 0x93, 0x73, 0x0e, 0x58, 0x94, 0x2d, 0xc6, 0x08, 0xd4, 0x80, 0xed, 0x8e, 0xff, 0x3e, 0xa0, 0xbb, 0xbb, 0x90, 0x30, 0x6d, 0xd8, 0x12, 0xc8, 0x01, 0x6a, 0x57, 0xde, 0x7d, 0x21, 0xb2, 0xee,
0x30, 0x39, 0x6f, 0x24, 0xa8, 0x70, 0x2b, 0xdc, 0x2a, 0x46, 0xab, 0x5c, 0x17, 0xee, 0xb4, 0x46, 0xfb, 0x07, 0x9d, 0xf9, 0xc6, 0xc7, 0x9b, 0x5c, 0x17, 0x6e, 0x5d, 0x23, 0x94, 0xae, 0x92, 0x5b,
0x28, 0x5d, 0x25, 0x8f, 0x56, 0x46, 0xe1, 0x07, 0x92, 0xa9, 0x69, 0x4e, 0x50, 0x91, 0xa3, 0x95, 0x1b, 0xe3, 0xb0, 0x81, 0x64, 0x6a, 0x9a, 0x11, 0x54, 0x64, 0x6b, 0x63, 0x30, 0x2e, 0x91, 0x71,
0xc1, 0xa8, 0x44, 0xc6, 0xfd, 0x7f, 0x30, 0xaa, 0xd0, 0x31, 0x28, 0x4a, 0x66, 0x2c, 0xba, 0x9c, 0xbf, 0x0f, 0xc6, 0x15, 0x3a, 0x06, 0x45, 0xc9, 0x8c, 0x45, 0x97, 0x91, 0xb9, 0x9b, 0x24, 0xa7,
0xcc, 0xdd, 0x24, 0xdd, 0x23, 0x90, 0x35, 0x2a, 0x29, 0xd4, 0x0c, 0x0c, 0xca, 0x9c, 0x88, 0x42, 0x08, 0xa4, 0xcd, 0x97, 0x14, 0x6a, 0x06, 0x06, 0x65, 0x46, 0x44, 0xa1, 0x15, 0x81, 0xd2, 0xe0,
0x2b, 0x02, 0xa5, 0xc1, 0x49, 0x4e, 0x68, 0x36, 0x61, 0x8b, 0x20, 0xa0, 0x76, 0x31, 0x0d, 0xa6, 0x24, 0x23, 0x34, 0x9d, 0xb0, 0x45, 0x78, 0xa0, 0x76, 0x31, 0x6d, 0x45, 0x3b, 0x8a, 0x62, 0x15,
0xef, 0x50, 0x14, 0xab, 0x30, 0x27, 0x0b, 0x81, 0xcb, 0x5a, 0x1b, 0x47, 0xc0, 0xdb, 0x38, 0x54, 0x66, 0x64, 0x21, 0x70, 0x59, 0x6b, 0xe3, 0x08, 0x78, 0x19, 0x87, 0xca, 0x53, 0x97, 0x82, 0xbb,
0x1e, 0x75, 0x29, 0xb8, 0x2b, 0x73, 0x8e, 0xde, 0x0d, 0xd3, 0xe6, 0x92, 0x80, 0x50, 0xc2, 0x09, 0x32, 0xe3, 0xe8, 0xd5, 0x30, 0x69, 0x2e, 0x23, 0x10, 0x4a, 0x38, 0xc1, 0x64, 0x62, 0x0b, 0x26,
0x26, 0x53, 0x5b, 0x30, 0x89, 0xf9, 0x7a, 0x0f, 0x64, 0x0b, 0x23, 0x6a, 0x17, 0x8e, 0x83, 0x2c, 0x31, 0x3b, 0xdc, 0x83, 0x6c, 0x61, 0x44, 0xed, 0xc2, 0x71, 0x90, 0xa6, 0x70, 0x4f, 0x41, 0xcd,
0x83, 0x5b, 0x0a, 0x6a, 0x36, 0x45, 0x90, 0x9a, 0x71, 0xd0, 0x06, 0x96, 0x25, 0xaa, 0x90, 0xac, 0xa6, 0x08, 0x52, 0x33, 0x0e, 0xda, 0xc0, 0xb2, 0x44, 0x15, 0x9c, 0x55, 0x53, 0xa1, 0xa6, 0xe0,
0x9a, 0x0a, 0x35, 0x05, 0x57, 0x62, 0x85, 0x36, 0x81, 0x31, 0x5a, 0x07, 0x4e, 0x03, 0xe3, 0xdc, 0x4a, 0xac, 0xd0, 0x8e, 0x20, 0x47, 0xeb, 0xc0, 0x69, 0x60, 0x9c, 0x7b, 0xac, 0xf7, 0x1a, 0xfd,
0xc3, 0xfa, 0xac, 0xd1, 0xff, 0xe0, 0x75, 0x28, 0xf1, 0x75, 0x23, 0x5f, 0x68, 0xc1, 0xe1, 0xea, 0x06, 0xef, 0x43, 0x88, 0xef, 0x9b, 0xf7, 0x85, 0x16, 0x1c, 0xae, 0xde, 0x7b, 0x72, 0x29, 0x60,
0xad, 0x07, 0xff, 0x05, 0x58, 0x31, 0x81, 0x48, 0x6a, 0x1f, 0xf5, 0x9e, 0xd3, 0xc6, 0x83, 0xd3, 0xc5, 0x04, 0x22, 0xa9, 0xbd, 0xd5, 0x47, 0x4e, 0x1b, 0x0f, 0xa7, 0x0d, 0x06, 0xb2, 0x2c, 0x83,
0x06, 0x06, 0xf2, 0x3c, 0x87, 0x21, 0x67, 0x66, 0x36, 0x84, 0x8b, 0x0b, 0x88, 0x56, 0xa3, 0x61, 0x21, 0x67, 0x66, 0x36, 0x84, 0xdd, 0x5d, 0x88, 0x36, 0xa3, 0x61, 0xf3, 0x3e, 0x0c, 0xa8, 0x2f,
0x23, 0x1f, 0x06, 0xa8, 0x0f, 0xcd, 0x63, 0xf8, 0xf3, 0x4f, 0x58, 0x0a, 0xc5, 0xf5, 0x92, 0x56, 0xc5, 0x63, 0x38, 0x78, 0x10, 0x96, 0x42, 0x71, 0xbd, 0xa4, 0x15, 0x73, 0x45, 0x79, 0x07, 0xb9,
0xcc, 0x15, 0xe5, 0x0d, 0xe4, 0x82, 0x45, 0xc3, 0xa8, 0xf6, 0xdd, 0x41, 0x63, 0xd3, 0x42, 0x4b, 0x60, 0xd1, 0x30, 0xaa, 0x7d, 0x76, 0xd0, 0xd8, 0xa4, 0xd0, 0x52, 0x1b, 0x1f, 0x56, 0xd0, 0x3e,
0x6d, 0x7c, 0x59, 0xc1, 0xfb, 0x00, 0x02, 0x62, 0x3c, 0x8c, 0x5b, 0x53, 0xb4, 0x71, 0x0c, 0xe7, 0x03, 0x81, 0x18, 0x0f, 0xe3, 0x56, 0x14, 0x6d, 0x1c, 0xc3, 0x4e, 0x70, 0x62, 0xe0, 0x0b, 0x34,
0x21, 0x89, 0x81, 0x27, 0x68, 0x5e, 0xa1, 0x72, 0xb4, 0x3f, 0x5c, 0x91, 0xd8, 0xdc, 0x0b, 0xc9, 0xaf, 0x50, 0x39, 0xda, 0x1f, 0xae, 0x48, 0x6c, 0xee, 0x85, 0x64, 0xd6, 0xde, 0x16, 0xd6, 0x51,
0xac, 0xbd, 0x2e, 0xac, 0xa3, 0xbe, 0x9c, 0xa8, 0xcd, 0x28, 0x3e, 0x0c, 0x3e, 0x97, 0x80, 0xd2, 0x1f, 0x4e, 0xd4, 0x7a, 0x14, 0x9f, 0x0d, 0x3a, 0x7b, 0x80, 0xd2, 0xe2, 0x9f, 0xeb, 0x1b, 0xac,
0xe2, 0x8f, 0xfb, 0x1b, 0xac, 0xf4, 0x02, 0x3f, 0x86, 0x08, 0x2d, 0xce, 0xde, 0xf7, 0xf8, 0x1d, 0xf4, 0x02, 0xbf, 0x46, 0x84, 0x14, 0xa7, 0x9f, 0x73, 0xdc, 0x57, 0xf9, 0x53, 0x69, 0x59, 0x5d,
0xcb, 0x3d, 0xb5, 0xac, 0xae, 0x33, 0x51, 0x55, 0x73, 0xc7, 0xc6, 0x12, 0x33, 0x8f, 0x84, 0xce, 0xa7, 0xa2, 0xaa, 0xe6, 0x8e, 0xe5, 0x12, 0x53, 0x4f, 0x42, 0x67, 0x53, 0x1f, 0x2c, 0xae, 0xe8,
0x66, 0xbe, 0x58, 0x3c, 0xa1, 0xff, 0x6e, 0xfd, 0x9f, 0xde, 0xc2, 0x5b, 0x5b, 0xb4, 0xb0, 0x96, 0xa5, 0xd3, 0xeb, 0xe7, 0x37, 0xef, 0xe4, 0x47, 0x69, 0x61, 0x2d, 0x69, 0xdb, 0xc2, 0xba, 0xb5,
0xb4, 0x63, 0x61, 0xdd, 0xa9, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0xc9, 0xc0, 0x54, 0x9a, 0xcf, 0x25, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0x4d, 0xc3, 0x54, 0x9a, 0xcf, 0x25, 0xfa, 0x94, 0x84, 0xca, 0x91,
0xfa, 0x96, 0x04, 0xe6, 0xc8, 0x57, 0xe0, 0x51, 0x39, 0x73, 0x9a, 0x59, 0xc7, 0x8c, 0xa3, 0xbb, 0x9f, 0xe0, 0x51, 0x39, 0xb3, 0x4e, 0xad, 0x63, 0xc6, 0xd1, 0x8b, 0x0f, 0x9f, 0x95, 0xd5, 0x8b,
0xe2, 0xde, 0xf1, 0xf1, 0xff, 0xff, 0xae, 0xd3, 0x37, 0xf6, 0x97, 0xb0, 0x8a, 0x72, 0xae, 0x66, 0xd3, 0xb7, 0xe8, 0x07, 0xfb, 0x4f, 0xac, 0xa2, 0x9c, 0xab, 0x99, 0x4d, 0x2f, 0x6e, 0x5f, 0x99,
0x36, 0xfb, 0xbf, 0xda, 0xb8, 0xf3, 0xdf, 0xec, 0xec, 0xdf, 0x00, 0xf3, 0xeb, 0x29, 0x79, 0x19, 0xdc, 0x49, 0xd6, 0x2b, 0x8f, 0xf9, 0x0f, 0x97, 0xfc, 0x1b, 0xbd, 0x78, 0xf3, 0x9e, 0xcd, 0xcd,
0xfd, 0x6f, 0xbc, 0xf1, 0xf0, 0xd1, 0xe6, 0xa3, 0x3b, 0x1d, 0xd2, 0x28, 0xeb, 0x36, 0x66, 0x34, 0xe5, 0xbc, 0x23, 0x8d, 0xd3, 0x6e, 0x62, 0xc6, 0xb9, 0xe6, 0x6b, 0xe0, 0xcc, 0xb1, 0xc4, 0x2e,
0xd6, 0xfc, 0x14, 0x38, 0x73, 0x2c, 0xb5, 0x0b, 0x94, 0x0e, 0x67, 0xc2, 0xa5, 0x1d, 0x6a, 0x1a, 0x50, 0x3a, 0x9c, 0x09, 0x97, 0x74, 0xd4, 0x24, 0x3c, 0x67, 0xa4, 0xf4, 0x69, 0x37, 0xad, 0x79,
0xc4, 0x39, 0x29, 0x7d, 0xdb, 0x4d, 0x1b, 0x9e, 0x8b, 0x05, 0x34, 0x5d, 0xca, 0x09, 0x17, 0xb6, 0x2e, 0x16, 0xd0, 0x64, 0x29, 0x23, 0x5c, 0xd8, 0x5a, 0xb2, 0xf5, 0x99, 0x7e, 0x2c, 0x1a, 0xec,
0x96, 0xec, 0xf4, 0xa0, 0x5f, 0x8b, 0x06, 0xf6, 0xe3, 0x89, 0x1f, 0xb4, 0xdc, 0x0e, 0x5e, 0xbd, 0xd7, 0x1d, 0x3f, 0x68, 0x6b, 0x3b, 0x78, 0xf7, 0xee, 0x13, 0xfa, 0xdd, 0xb1, 0xe3, 0x25, 0x64,
0x7a, 0x07, 0xfd, 0x6a, 0x6b, 0xbb, 0x84, 0x1c, 0x3a, 0xc5, 0x60, 0xcc, 0x2c, 0x1e, 0x80, 0xc2, 0xd0, 0x7d, 0x0c, 0x72, 0x66, 0x7d, 0x53, 0x29, 0x5c, 0xc2, 0x93, 0x87, 0xb7, 0x23, 0x42, 0xc9,
0x25, 0x3c, 0xb8, 0x7b, 0x3d, 0x22, 0x94, 0x24, 0xcd, 0x70, 0x3a, 0xa1, 0x55, 0x4c, 0x6b, 0xe6, 0xa8, 0x69, 0x4e, 0x27, 0xb4, 0x8a, 0x69, 0xcd, 0x5c, 0x19, 0x66, 0x90, 0x5a, 0x29, 0x0a, 0x8c,
0xca, 0xb0, 0x83, 0xd4, 0x4a, 0x51, 0x60, 0xb4, 0x96, 0x40, 0xba, 0x1e, 0x27, 0x9d, 0x67, 0xcb, 0x0e, 0x8d, 0x20, 0x39, 0x1c, 0xb7, 0x8a, 0x7b, 0x67, 0x37, 0xda, 0x83, 0x37, 0x6e, 0x1d, 0x60,
0xe5, 0x01, 0x90, 0x6c, 0x2e, 0x48, 0x2b, 0xbb, 0x3c, 0x5c, 0x69, 0x0f, 0x3e, 0x23, 0xeb, 0x00, 0xdb, 0x2c, 0x1e, 0xfc, 0xa9, 0x8f, 0x8a, 0xb9, 0x31, 0x7e, 0x7f, 0xd4, 0x78, 0xe3, 0x51, 0xe6,
0xdb, 0x09, 0xf2, 0xd1, 0xde, 0x0d, 0x57, 0x31, 0x37, 0xc6, 0xff, 0xef, 0x35, 0x29, 0x7a, 0x7c, 0x73, 0x4f, 0xf5, 0xba, 0xf7, 0x8d, 0xae, 0x84, 0x45, 0xca, 0xa4, 0x8c, 0x5e, 0x75, 0x0e, 0x89,
0xf3, 0x7e, 0xd0, 0x7a, 0xdf, 0xdb, 0x46, 0x57, 0xc2, 0x22, 0x65, 0x52, 0x46, 0xcf, 0xba, 0x58, 0x2a, 0xcc, 0x7a, 0xf4, 0xc7, 0xb5, 0x8d, 0x47, 0x5f, 0x2b, 0xfe, 0x61, 0x05, 0xba, 0x30, 0xde,
0xa2, 0x0a, 0x0f, 0x40, 0xf4, 0xc3, 0x84, 0xc7, 0xc9, 0xc7, 0x8e, 0x3f, 0x48, 0x4b, 0xdc, 0x7a, 0xc4, 0x61, 0x5a, 0x55, 0x14, 0xbd, 0xf2, 0xa9, 0x19, 0x81, 0x97, 0x7a, 0x13, 0x43, 0xb6, 0xf5,
0xbd, 0x88, 0xc3, 0x0a, 0xab, 0x28, 0x7a, 0xe6, 0xfb, 0x95, 0x80, 0xb7, 0x7a, 0x11, 0x43, 0x7e, 0x29, 0x3d, 0xfe, 0x95, 0x36, 0x36, 0x23, 0xff, 0x35, 0xea, 0xc3, 0x8c, 0xcf, 0x76, 0x49, 0x08,
0xf4, 0xae, 0x67, 0x5e, 0x4a, 0x9b, 0x98, 0x91, 0x57, 0x25, 0x7d, 0x99, 0xf1, 0x61, 0xd7, 0x84, 0x87, 0x6e, 0x0a, 0x3e, 0x0e, 0x29, 0x1b, 0x80, 0xd8, 0xc0, 0x78, 0x02, 0x47, 0x32, 0x28, 0x72,
0xf6, 0x10, 0x56, 0xe3, 0xa3, 0xdd, 0xf0, 0x67, 0x4f, 0x5e, 0xc3, 0x7c, 0x60, 0xdc, 0x3f, 0xa2, 0x81, 0xe5, 0xa5, 0x3e, 0xa4, 0xdc, 0x04, 0x00, 0x12, 0x28, 0x85, 0xf3, 0x48, 0x05, 0x00, 0x00
0x59, 0xfb, 0x98, 0xbe, 0x05, 0x7a, 0xda, 0x17, 0xc7, 0x5d, 0x05, 0x00, 0x00
}; };
inline void serveDevicesHtml(AsyncWebServerRequest* request) { inline void serveDevicesHtml(AsyncWebServerRequest* request) {
@ -61,51 +60,50 @@ inline void serveDevicesHtml(AsyncWebServerRequest* request) {
} }
// fingerprints.html // fingerprints.html
const uint16_t FINGERPRINTS_HTML_L = 685; const uint16_t FINGERPRINTS_HTML_L = 672;
const uint8_t FINGERPRINTS_HTML[] PROGMEM = { const uint8_t FINGERPRINTS_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x9d, 0x54, 0xc7, 0x96, 0xe3, 0x2a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x93, 0xe5, 0xb6, 0xe3, 0x20,
0x10, 0x5d, 0xbb, 0xbf, 0xa2, 0x9a, 0x17, 0x2c, 0x9d, 0x23, 0xa1, 0xce, 0xd1, 0xea, 0x17, 0x67, 0x10, 0x80, 0x7f, 0xf7, 0x3e, 0xc5, 0x5c, 0x56, 0x9a, 0x9c, 0xd3, 0x90, 0x75, 0x6d, 0xee, 0xba,
0x36, 0x93, 0x73, 0x0e, 0x58, 0x94, 0x2d, 0xc6, 0x08, 0xd4, 0x80, 0xed, 0x8e, 0xff, 0x3e, 0xa0, 0xbb, 0xbb, 0x90, 0x30, 0x6d, 0xd8, 0x12, 0xc8, 0x01, 0x6a, 0x57, 0xde, 0x7d, 0x21, 0xb2, 0xee,
0x30, 0x39, 0x6f, 0x24, 0xa8, 0x70, 0x2b, 0xdc, 0x2a, 0x46, 0xab, 0x5c, 0x17, 0xee, 0xb4, 0x46, 0xfb, 0x07, 0x9d, 0xf9, 0xc6, 0xc7, 0x9b, 0x5c, 0x17, 0x6e, 0x5d, 0x23, 0x94, 0xae, 0x92, 0x5b,
0x28, 0x5d, 0x25, 0x8f, 0x56, 0x46, 0xe1, 0x07, 0x92, 0xa9, 0x69, 0x4e, 0x50, 0x91, 0xa3, 0x95, 0x1b, 0xe3, 0xb0, 0x81, 0x64, 0x6a, 0x9a, 0x11, 0x54, 0x64, 0x6b, 0x63, 0x30, 0x2e, 0x91, 0x71,
0xc1, 0xa8, 0x44, 0xc6, 0xfd, 0x7f, 0x30, 0xaa, 0xd0, 0x31, 0x28, 0x4a, 0x66, 0x2c, 0xba, 0x9c, 0xbf, 0x0f, 0xc6, 0x15, 0x3a, 0x06, 0x45, 0xc9, 0x8c, 0x45, 0x97, 0x91, 0xb9, 0x9b, 0x24, 0xa7,
0xcc, 0xdd, 0x24, 0xdd, 0x23, 0x90, 0x35, 0x2a, 0x29, 0xd4, 0x0c, 0x0c, 0xca, 0x9c, 0x88, 0x42, 0x08, 0xa4, 0xcd, 0x97, 0x14, 0x6a, 0x06, 0x06, 0x65, 0x46, 0x44, 0xa1, 0x15, 0x81, 0xd2, 0xe0,
0x2b, 0x02, 0xa5, 0xc1, 0x49, 0x4e, 0x68, 0x36, 0x61, 0x8b, 0x20, 0xa0, 0x76, 0x31, 0x0d, 0xa6, 0x24, 0x23, 0x34, 0x9d, 0xb0, 0x45, 0x78, 0xa0, 0x76, 0x31, 0x6d, 0x45, 0x3b, 0x8a, 0x62, 0x15,
0xef, 0x50, 0x14, 0xab, 0x30, 0x27, 0x0b, 0x81, 0xcb, 0x5a, 0x1b, 0x47, 0xc0, 0xdb, 0x38, 0x54, 0x66, 0x64, 0x21, 0x70, 0x59, 0x6b, 0xe3, 0x08, 0x78, 0x19, 0x87, 0xca, 0x53, 0x97, 0x82, 0xbb,
0x1e, 0x75, 0x29, 0xb8, 0x2b, 0x73, 0x8e, 0xde, 0x0d, 0xd3, 0xe6, 0x92, 0x80, 0x50, 0xc2, 0x09, 0x32, 0xe3, 0xe8, 0xd5, 0x30, 0x69, 0x2e, 0x23, 0x10, 0x4a, 0x38, 0xc1, 0x64, 0x62, 0x0b, 0x26,
0x26, 0x53, 0x5b, 0x30, 0x89, 0xf9, 0x7a, 0x0f, 0x64, 0x0b, 0x23, 0x6a, 0x17, 0x8e, 0x83, 0x2c, 0x31, 0x3b, 0xdc, 0x83, 0x6c, 0x61, 0x44, 0xed, 0xc2, 0x71, 0x90, 0xa6, 0x70, 0x4f, 0x41, 0xcd,
0x83, 0x5b, 0x0a, 0x6a, 0x36, 0x45, 0x90, 0x9a, 0x71, 0xd0, 0x06, 0x96, 0x25, 0xaa, 0x90, 0xac, 0xa6, 0x08, 0x52, 0x33, 0x0e, 0xda, 0xc0, 0xb2, 0x44, 0x15, 0x9c, 0x55, 0x53, 0xa1, 0xa6, 0xe0,
0x9a, 0x0a, 0x35, 0x05, 0x57, 0x62, 0x85, 0x36, 0x81, 0x31, 0x5a, 0x07, 0x4e, 0x03, 0xe3, 0xdc, 0x4a, 0xac, 0xd0, 0x8e, 0x20, 0x47, 0xeb, 0xc0, 0x69, 0x60, 0x9c, 0x7b, 0xac, 0xf7, 0x1a, 0xfd,
0xc3, 0xfa, 0xac, 0xd1, 0xff, 0xe0, 0x75, 0x28, 0xf1, 0x75, 0x23, 0x5f, 0x68, 0xc1, 0xe1, 0xea, 0x06, 0xef, 0x43, 0x88, 0xef, 0x9b, 0xf7, 0x85, 0x16, 0x1c, 0xae, 0xde, 0x7b, 0x72, 0x29, 0x60,
0xad, 0x07, 0xff, 0x05, 0x58, 0x31, 0x81, 0x48, 0x6a, 0x1f, 0xf5, 0x9e, 0xd3, 0xc6, 0x83, 0xd3, 0xc5, 0x04, 0x22, 0xa9, 0xbd, 0xd5, 0x47, 0x4e, 0x1b, 0x0f, 0xa7, 0x0d, 0x06, 0xb2, 0x2c, 0x83,
0x06, 0x06, 0xf2, 0x3c, 0x87, 0x21, 0x67, 0x66, 0x36, 0x84, 0x8b, 0x0b, 0x88, 0x56, 0xa3, 0x61, 0x21, 0x67, 0x66, 0x36, 0x84, 0xdd, 0x5d, 0x88, 0x36, 0xa3, 0x61, 0xf3, 0x3e, 0x0c, 0xa8, 0x2f,
0x23, 0x1f, 0x06, 0xa8, 0x0f, 0xcd, 0x63, 0xf8, 0xf3, 0x4f, 0x58, 0x0a, 0xc5, 0xf5, 0x92, 0x56, 0xc5, 0x63, 0x38, 0x78, 0x10, 0x96, 0x42, 0x71, 0xbd, 0xa4, 0x15, 0x73, 0x45, 0x79, 0x07, 0xb9,
0xcc, 0x15, 0xe5, 0x0d, 0xe4, 0x82, 0x45, 0xc3, 0xa8, 0xf6, 0xdd, 0x41, 0x63, 0xd3, 0x42, 0x4b, 0x60, 0xd1, 0x30, 0xaa, 0x7d, 0x76, 0xd0, 0xd8, 0xa4, 0xd0, 0x52, 0x1b, 0x1f, 0x56, 0xd0, 0x3e,
0x6d, 0x7c, 0x59, 0xc1, 0xfb, 0x00, 0x02, 0x62, 0x3c, 0x8c, 0x5b, 0x53, 0xb4, 0x71, 0x0c, 0xe7, 0x03, 0x81, 0x18, 0x0f, 0xe3, 0x56, 0x14, 0x6d, 0x1c, 0xc3, 0x4e, 0x70, 0x62, 0xe0, 0x0b, 0x34,
0x21, 0x89, 0x81, 0x27, 0x68, 0x5e, 0xa1, 0x72, 0xb4, 0x3f, 0x5c, 0x91, 0xd8, 0xdc, 0x0b, 0xc9, 0xaf, 0x50, 0x39, 0xda, 0x1f, 0xae, 0x48, 0x6c, 0xee, 0x85, 0x64, 0xd6, 0xde, 0x16, 0xd6, 0x51,
0xac, 0xbd, 0x2e, 0xac, 0xa3, 0xbe, 0x9c, 0xa8, 0xcd, 0x28, 0x3e, 0x0c, 0x3e, 0x97, 0x80, 0xd2, 0x1f, 0x4e, 0xd4, 0x7a, 0x14, 0x9f, 0x0d, 0x3a, 0x7b, 0x80, 0xd2, 0xe2, 0x9f, 0xeb, 0x1b, 0xac,
0xe2, 0x8f, 0xfb, 0x1b, 0xac, 0xf4, 0x02, 0x3f, 0x86, 0x08, 0x2d, 0xce, 0xde, 0xf7, 0xf8, 0x1d, 0xf4, 0x02, 0xbf, 0x46, 0x84, 0x14, 0xa7, 0x9f, 0x73, 0xdc, 0x57, 0xf9, 0x53, 0x69, 0x59, 0x5d,
0xcb, 0x3d, 0xb5, 0xac, 0xae, 0x33, 0x51, 0x55, 0x73, 0xc7, 0xc6, 0x12, 0x33, 0x8f, 0x84, 0xce, 0xa7, 0xa2, 0xaa, 0xe6, 0x8e, 0xe5, 0x12, 0x53, 0x4f, 0x42, 0x67, 0x53, 0x1f, 0x2c, 0xae, 0xe8,
0x66, 0xbe, 0x58, 0x3c, 0xa1, 0xff, 0x6e, 0xfd, 0x9f, 0xde, 0xc2, 0x5b, 0x5b, 0xb4, 0xb0, 0x96, 0xa5, 0xd3, 0xeb, 0xe7, 0x37, 0xef, 0xe4, 0x47, 0x69, 0x61, 0x2d, 0x69, 0xdb, 0xc2, 0xba, 0xb5,
0xb4, 0x63, 0x61, 0xdd, 0xa9, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0xc9, 0xc0, 0x54, 0x9a, 0xcf, 0x25, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0x4d, 0xc3, 0x54, 0x9a, 0xcf, 0x25, 0xfa, 0x94, 0x84, 0xca, 0x91,
0xfa, 0x96, 0x04, 0xe6, 0xc8, 0x57, 0xe0, 0x51, 0x39, 0x73, 0x9a, 0x59, 0xc7, 0x8c, 0xa3, 0xbb, 0x9f, 0xe0, 0x51, 0x39, 0xb3, 0x4e, 0xad, 0x63, 0xc6, 0xd1, 0x8b, 0x0f, 0x9f, 0x95, 0xd5, 0x8b,
0xe2, 0xde, 0xf1, 0xf1, 0xff, 0xff, 0xae, 0xd3, 0x37, 0xf6, 0x97, 0xb0, 0x8a, 0x72, 0xae, 0x66, 0xd3, 0xb7, 0xe8, 0x07, 0xfb, 0x4f, 0xac, 0xa2, 0x9c, 0xab, 0x99, 0x4d, 0x2f, 0x6e, 0x5f, 0x99,
0x36, 0xfb, 0xbf, 0xda, 0xb8, 0xf3, 0xdf, 0xec, 0xec, 0xdf, 0x00, 0xf3, 0xeb, 0x29, 0x79, 0x19, 0xdc, 0x49, 0xd6, 0x2b, 0x8f, 0xf9, 0x0f, 0x97, 0xfc, 0x1b, 0xbd, 0x78, 0xf3, 0x9e, 0xcd, 0xcd,
0xfd, 0x6f, 0xbc, 0xf1, 0xf0, 0xd1, 0xe6, 0xa3, 0x3b, 0x1d, 0xd2, 0x28, 0xeb, 0x36, 0x66, 0x34, 0xe5, 0xbc, 0x23, 0x8d, 0xd3, 0x6e, 0x62, 0xc6, 0xb9, 0xe6, 0x6b, 0xe0, 0xcc, 0xb1, 0xc4, 0x2e,
0xd6, 0xfc, 0x14, 0x38, 0x73, 0x2c, 0xb5, 0x0b, 0x94, 0x0e, 0x67, 0xc2, 0xa5, 0x1d, 0x6a, 0x1a, 0x50, 0x3a, 0x9c, 0x09, 0x97, 0x74, 0xd4, 0x24, 0x3c, 0x67, 0xa4, 0xf4, 0x69, 0x37, 0xad, 0x79,
0xc4, 0x39, 0x29, 0x7d, 0xdb, 0x4d, 0x1b, 0x9e, 0x8b, 0x05, 0x34, 0x5d, 0xca, 0x09, 0x17, 0xb6, 0x2e, 0x16, 0xd0, 0x64, 0x29, 0x23, 0x5c, 0xd8, 0x5a, 0xb2, 0xf5, 0x99, 0x7e, 0x2c, 0x1a, 0xec,
0x96, 0xec, 0xf4, 0xa0, 0x5f, 0x8b, 0x06, 0xf6, 0xe3, 0x89, 0x1f, 0xb4, 0xdc, 0x0e, 0x5e, 0xbd, 0xd7, 0x1d, 0x3f, 0x68, 0x6b, 0x3b, 0x78, 0xf7, 0xee, 0x13, 0xfa, 0xdd, 0xb1, 0xe3, 0x25, 0x64,
0x7a, 0x07, 0xfd, 0x6a, 0x6b, 0xbb, 0x84, 0x1c, 0x3a, 0xc5, 0x60, 0xcc, 0x2c, 0x1e, 0x80, 0xc2, 0xd0, 0x7d, 0x0c, 0x72, 0x66, 0x7d, 0x53, 0x29, 0x5c, 0xc2, 0x93, 0x87, 0xb7, 0x23, 0x42, 0xc9,
0x25, 0x3c, 0xb8, 0x7b, 0x3d, 0x22, 0x94, 0x24, 0xcd, 0x70, 0x3a, 0xa1, 0x55, 0x4c, 0x6b, 0xe6, 0xa8, 0x69, 0x4e, 0x27, 0xb4, 0x8a, 0x69, 0xcd, 0x5c, 0x19, 0x66, 0x90, 0x5a, 0x29, 0x0a, 0x8c,
0xca, 0xb0, 0x83, 0xd4, 0x4a, 0x51, 0x60, 0xb4, 0x96, 0x40, 0xba, 0x1e, 0x27, 0x9d, 0x67, 0xcb, 0x0e, 0x8d, 0x20, 0x39, 0x1c, 0xb7, 0x8a, 0x7b, 0x67, 0x37, 0xda, 0x83, 0x37, 0x6e, 0x1d, 0x60,
0xe5, 0x01, 0x90, 0x6c, 0x2e, 0x48, 0x2b, 0xbb, 0x3c, 0x5c, 0x69, 0x0f, 0x3e, 0x23, 0xeb, 0x00, 0xdb, 0x2c, 0x1e, 0xfc, 0xa9, 0x8f, 0x8a, 0xb9, 0x31, 0x7e, 0x7f, 0xd4, 0x78, 0xe3, 0x51, 0xe6,
0xdb, 0x09, 0xf2, 0xd1, 0xde, 0x0d, 0x57, 0x31, 0x37, 0xc6, 0xff, 0xef, 0x35, 0x29, 0x7a, 0x7c, 0x73, 0x4f, 0xf5, 0xba, 0xf7, 0x8d, 0xae, 0x84, 0x45, 0xca, 0xa4, 0x8c, 0x5e, 0x75, 0x0e, 0x89,
0xf3, 0x7e, 0xd0, 0x7a, 0xdf, 0xdb, 0x46, 0x57, 0xc2, 0x22, 0x65, 0x52, 0x46, 0xcf, 0xba, 0x58, 0x2a, 0xcc, 0x7a, 0xf4, 0xc7, 0xb5, 0x8d, 0x47, 0x5f, 0x2b, 0xfe, 0x61, 0x05, 0xba, 0x30, 0xde,
0xa2, 0x0a, 0x0f, 0x40, 0xf4, 0xc3, 0x84, 0xc7, 0xc9, 0xc7, 0x8e, 0x3f, 0x48, 0x4b, 0xdc, 0x7a, 0xc4, 0x61, 0x5a, 0x55, 0x14, 0xbd, 0xf2, 0xa9, 0x19, 0x81, 0x97, 0x7a, 0x13, 0x43, 0xb6, 0xf5,
0xbd, 0x88, 0xc3, 0x0a, 0xab, 0x28, 0x7a, 0xe6, 0xfb, 0x95, 0x80, 0xb7, 0x7a, 0x11, 0x43, 0x7e, 0x29, 0x3d, 0xfe, 0x95, 0x36, 0x36, 0x23, 0xff, 0x35, 0xea, 0xc3, 0x8c, 0xcf, 0x76, 0x49, 0x08,
0xf4, 0xae, 0x67, 0x5e, 0x4a, 0x9b, 0x98, 0x91, 0x57, 0x25, 0x7d, 0x99, 0xf1, 0x61, 0xd7, 0x84, 0x87, 0x6e, 0x0a, 0x3e, 0x0e, 0x29, 0x1b, 0x80, 0xd8, 0xc0, 0x78, 0x02, 0x47, 0x32, 0x28, 0x72,
0xf6, 0x10, 0x56, 0xe3, 0xa3, 0xdd, 0xf0, 0x67, 0x4f, 0x5e, 0xc3, 0x7c, 0x60, 0xdc, 0x3f, 0xa2, 0x81, 0xe5, 0xa5, 0x3e, 0xa4, 0xdc, 0x04, 0x00, 0x12, 0x28, 0x85, 0xf3, 0x48, 0x05, 0x00, 0x00
0x59, 0xfb, 0x98, 0xbe, 0x05, 0x7a, 0xda, 0x17, 0xc7, 0x5d, 0x05, 0x00, 0x00
}; };
inline void serveFingerprintsHtml(AsyncWebServerRequest* request) { inline void serveFingerprintsHtml(AsyncWebServerRequest* request) {
@ -115,51 +113,50 @@ inline void serveFingerprintsHtml(AsyncWebServerRequest* request) {
} }
// index.html // index.html
const uint16_t INDEX_HTML_L = 685; const uint16_t INDEX_HTML_L = 672;
const uint8_t INDEX_HTML[] PROGMEM = { const uint8_t INDEX_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x9d, 0x54, 0xc7, 0x96, 0xe3, 0x2a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x93, 0xe5, 0xb6, 0xe3, 0x20,
0x10, 0x5d, 0xbb, 0xbf, 0xa2, 0x9a, 0x17, 0x2c, 0x9d, 0x23, 0xa1, 0xce, 0xd1, 0xea, 0x17, 0x67, 0x10, 0x80, 0x7f, 0xf7, 0x3e, 0xc5, 0x5c, 0x56, 0x9a, 0x9c, 0xd3, 0x90, 0x75, 0x6d, 0xee, 0xba,
0x36, 0x93, 0x73, 0x0e, 0x58, 0x94, 0x2d, 0xc6, 0x08, 0xd4, 0x80, 0xed, 0x8e, 0xff, 0x3e, 0xa0, 0xbb, 0xbb, 0x90, 0x30, 0x6d, 0xd8, 0x12, 0xc8, 0x01, 0x6a, 0x57, 0xde, 0x7d, 0x21, 0xb2, 0xee,
0x30, 0x39, 0x6f, 0x24, 0xa8, 0x70, 0x2b, 0xdc, 0x2a, 0x46, 0xab, 0x5c, 0x17, 0xee, 0xb4, 0x46, 0xfb, 0x07, 0x9d, 0xf9, 0xc6, 0xc7, 0x9b, 0x5c, 0x17, 0x6e, 0x5d, 0x23, 0x94, 0xae, 0x92, 0x5b,
0x28, 0x5d, 0x25, 0x8f, 0x56, 0x46, 0xe1, 0x07, 0x92, 0xa9, 0x69, 0x4e, 0x50, 0x91, 0xa3, 0x95, 0x1b, 0xe3, 0xb0, 0x81, 0x64, 0x6a, 0x9a, 0x11, 0x54, 0x64, 0x6b, 0x63, 0x30, 0x2e, 0x91, 0x71,
0xc1, 0xa8, 0x44, 0xc6, 0xfd, 0x7f, 0x30, 0xaa, 0xd0, 0x31, 0x28, 0x4a, 0x66, 0x2c, 0xba, 0x9c, 0xbf, 0x0f, 0xc6, 0x15, 0x3a, 0x06, 0x45, 0xc9, 0x8c, 0x45, 0x97, 0x91, 0xb9, 0x9b, 0x24, 0xa7,
0xcc, 0xdd, 0x24, 0xdd, 0x23, 0x90, 0x35, 0x2a, 0x29, 0xd4, 0x0c, 0x0c, 0xca, 0x9c, 0x88, 0x42, 0x08, 0xa4, 0xcd, 0x97, 0x14, 0x6a, 0x06, 0x06, 0x65, 0x46, 0x44, 0xa1, 0x15, 0x81, 0xd2, 0xe0,
0x2b, 0x02, 0xa5, 0xc1, 0x49, 0x4e, 0x68, 0x36, 0x61, 0x8b, 0x20, 0xa0, 0x76, 0x31, 0x0d, 0xa6, 0x24, 0x23, 0x34, 0x9d, 0xb0, 0x45, 0x78, 0xa0, 0x76, 0x31, 0x6d, 0x45, 0x3b, 0x8a, 0x62, 0x15,
0xef, 0x50, 0x14, 0xab, 0x30, 0x27, 0x0b, 0x81, 0xcb, 0x5a, 0x1b, 0x47, 0xc0, 0xdb, 0x38, 0x54, 0x66, 0x64, 0x21, 0x70, 0x59, 0x6b, 0xe3, 0x08, 0x78, 0x19, 0x87, 0xca, 0x53, 0x97, 0x82, 0xbb,
0x1e, 0x75, 0x29, 0xb8, 0x2b, 0x73, 0x8e, 0xde, 0x0d, 0xd3, 0xe6, 0x92, 0x80, 0x50, 0xc2, 0x09, 0x32, 0xe3, 0xe8, 0xd5, 0x30, 0x69, 0x2e, 0x23, 0x10, 0x4a, 0x38, 0xc1, 0x64, 0x62, 0x0b, 0x26,
0x26, 0x53, 0x5b, 0x30, 0x89, 0xf9, 0x7a, 0x0f, 0x64, 0x0b, 0x23, 0x6a, 0x17, 0x8e, 0x83, 0x2c, 0x31, 0x3b, 0xdc, 0x83, 0x6c, 0x61, 0x44, 0xed, 0xc2, 0x71, 0x90, 0xa6, 0x70, 0x4f, 0x41, 0xcd,
0x83, 0x5b, 0x0a, 0x6a, 0x36, 0x45, 0x90, 0x9a, 0x71, 0xd0, 0x06, 0x96, 0x25, 0xaa, 0x90, 0xac, 0xa6, 0x08, 0x52, 0x33, 0x0e, 0xda, 0xc0, 0xb2, 0x44, 0x15, 0x9c, 0x55, 0x53, 0xa1, 0xa6, 0xe0,
0x9a, 0x0a, 0x35, 0x05, 0x57, 0x62, 0x85, 0x36, 0x81, 0x31, 0x5a, 0x07, 0x4e, 0x03, 0xe3, 0xdc, 0x4a, 0xac, 0xd0, 0x8e, 0x20, 0x47, 0xeb, 0xc0, 0x69, 0x60, 0x9c, 0x7b, 0xac, 0xf7, 0x1a, 0xfd,
0xc3, 0xfa, 0xac, 0xd1, 0xff, 0xe0, 0x75, 0x28, 0xf1, 0x75, 0x23, 0x5f, 0x68, 0xc1, 0xe1, 0xea, 0x06, 0xef, 0x43, 0x88, 0xef, 0x9b, 0xf7, 0x85, 0x16, 0x1c, 0xae, 0xde, 0x7b, 0x72, 0x29, 0x60,
0xad, 0x07, 0xff, 0x05, 0x58, 0x31, 0x81, 0x48, 0x6a, 0x1f, 0xf5, 0x9e, 0xd3, 0xc6, 0x83, 0xd3, 0xc5, 0x04, 0x22, 0xa9, 0xbd, 0xd5, 0x47, 0x4e, 0x1b, 0x0f, 0xa7, 0x0d, 0x06, 0xb2, 0x2c, 0x83,
0x06, 0x06, 0xf2, 0x3c, 0x87, 0x21, 0x67, 0x66, 0x36, 0x84, 0x8b, 0x0b, 0x88, 0x56, 0xa3, 0x61, 0x21, 0x67, 0x66, 0x36, 0x84, 0xdd, 0x5d, 0x88, 0x36, 0xa3, 0x61, 0xf3, 0x3e, 0x0c, 0xa8, 0x2f,
0x23, 0x1f, 0x06, 0xa8, 0x0f, 0xcd, 0x63, 0xf8, 0xf3, 0x4f, 0x58, 0x0a, 0xc5, 0xf5, 0x92, 0x56, 0xc5, 0x63, 0x38, 0x78, 0x10, 0x96, 0x42, 0x71, 0xbd, 0xa4, 0x15, 0x73, 0x45, 0x79, 0x07, 0xb9,
0xcc, 0x15, 0xe5, 0x0d, 0xe4, 0x82, 0x45, 0xc3, 0xa8, 0xf6, 0xdd, 0x41, 0x63, 0xd3, 0x42, 0x4b, 0x60, 0xd1, 0x30, 0xaa, 0x7d, 0x76, 0xd0, 0xd8, 0xa4, 0xd0, 0x52, 0x1b, 0x1f, 0x56, 0xd0, 0x3e,
0x6d, 0x7c, 0x59, 0xc1, 0xfb, 0x00, 0x02, 0x62, 0x3c, 0x8c, 0x5b, 0x53, 0xb4, 0x71, 0x0c, 0xe7, 0x03, 0x81, 0x18, 0x0f, 0xe3, 0x56, 0x14, 0x6d, 0x1c, 0xc3, 0x4e, 0x70, 0x62, 0xe0, 0x0b, 0x34,
0x21, 0x89, 0x81, 0x27, 0x68, 0x5e, 0xa1, 0x72, 0xb4, 0x3f, 0x5c, 0x91, 0xd8, 0xdc, 0x0b, 0xc9, 0xaf, 0x50, 0x39, 0xda, 0x1f, 0xae, 0x48, 0x6c, 0xee, 0x85, 0x64, 0xd6, 0xde, 0x16, 0xd6, 0x51,
0xac, 0xbd, 0x2e, 0xac, 0xa3, 0xbe, 0x9c, 0xa8, 0xcd, 0x28, 0x3e, 0x0c, 0x3e, 0x97, 0x80, 0xd2, 0x1f, 0x4e, 0xd4, 0x7a, 0x14, 0x9f, 0x0d, 0x3a, 0x7b, 0x80, 0xd2, 0xe2, 0x9f, 0xeb, 0x1b, 0xac,
0xe2, 0x8f, 0xfb, 0x1b, 0xac, 0xf4, 0x02, 0x3f, 0x86, 0x08, 0x2d, 0xce, 0xde, 0xf7, 0xf8, 0x1d, 0xf4, 0x02, 0xbf, 0x46, 0x84, 0x14, 0xa7, 0x9f, 0x73, 0xdc, 0x57, 0xf9, 0x53, 0x69, 0x59, 0x5d,
0xcb, 0x3d, 0xb5, 0xac, 0xae, 0x33, 0x51, 0x55, 0x73, 0xc7, 0xc6, 0x12, 0x33, 0x8f, 0x84, 0xce, 0xa7, 0xa2, 0xaa, 0xe6, 0x8e, 0xe5, 0x12, 0x53, 0x4f, 0x42, 0x67, 0x53, 0x1f, 0x2c, 0xae, 0xe8,
0x66, 0xbe, 0x58, 0x3c, 0xa1, 0xff, 0x6e, 0xfd, 0x9f, 0xde, 0xc2, 0x5b, 0x5b, 0xb4, 0xb0, 0x96, 0xa5, 0xd3, 0xeb, 0xe7, 0x37, 0xef, 0xe4, 0x47, 0x69, 0x61, 0x2d, 0x69, 0xdb, 0xc2, 0xba, 0xb5,
0xb4, 0x63, 0x61, 0xdd, 0xa9, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0xc9, 0xc0, 0x54, 0x9a, 0xcf, 0x25, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0x4d, 0xc3, 0x54, 0x9a, 0xcf, 0x25, 0xfa, 0x94, 0x84, 0xca, 0x91,
0xfa, 0x96, 0x04, 0xe6, 0xc8, 0x57, 0xe0, 0x51, 0x39, 0x73, 0x9a, 0x59, 0xc7, 0x8c, 0xa3, 0xbb, 0x9f, 0xe0, 0x51, 0x39, 0xb3, 0x4e, 0xad, 0x63, 0xc6, 0xd1, 0x8b, 0x0f, 0x9f, 0x95, 0xd5, 0x8b,
0xe2, 0xde, 0xf1, 0xf1, 0xff, 0xff, 0xae, 0xd3, 0x37, 0xf6, 0x97, 0xb0, 0x8a, 0x72, 0xae, 0x66, 0xd3, 0xb7, 0xe8, 0x07, 0xfb, 0x4f, 0xac, 0xa2, 0x9c, 0xab, 0x99, 0x4d, 0x2f, 0x6e, 0x5f, 0x99,
0x36, 0xfb, 0xbf, 0xda, 0xb8, 0xf3, 0xdf, 0xec, 0xec, 0xdf, 0x00, 0xf3, 0xeb, 0x29, 0x79, 0x19, 0xdc, 0x49, 0xd6, 0x2b, 0x8f, 0xf9, 0x0f, 0x97, 0xfc, 0x1b, 0xbd, 0x78, 0xf3, 0x9e, 0xcd, 0xcd,
0xfd, 0x6f, 0xbc, 0xf1, 0xf0, 0xd1, 0xe6, 0xa3, 0x3b, 0x1d, 0xd2, 0x28, 0xeb, 0x36, 0x66, 0x34, 0xe5, 0xbc, 0x23, 0x8d, 0xd3, 0x6e, 0x62, 0xc6, 0xb9, 0xe6, 0x6b, 0xe0, 0xcc, 0xb1, 0xc4, 0x2e,
0xd6, 0xfc, 0x14, 0x38, 0x73, 0x2c, 0xb5, 0x0b, 0x94, 0x0e, 0x67, 0xc2, 0xa5, 0x1d, 0x6a, 0x1a, 0x50, 0x3a, 0x9c, 0x09, 0x97, 0x74, 0xd4, 0x24, 0x3c, 0x67, 0xa4, 0xf4, 0x69, 0x37, 0xad, 0x79,
0xc4, 0x39, 0x29, 0x7d, 0xdb, 0x4d, 0x1b, 0x9e, 0x8b, 0x05, 0x34, 0x5d, 0xca, 0x09, 0x17, 0xb6, 0x2e, 0x16, 0xd0, 0x64, 0x29, 0x23, 0x5c, 0xd8, 0x5a, 0xb2, 0xf5, 0x99, 0x7e, 0x2c, 0x1a, 0xec,
0x96, 0xec, 0xf4, 0xa0, 0x5f, 0x8b, 0x06, 0xf6, 0xe3, 0x89, 0x1f, 0xb4, 0xdc, 0x0e, 0x5e, 0xbd, 0xd7, 0x1d, 0x3f, 0x68, 0x6b, 0x3b, 0x78, 0xf7, 0xee, 0x13, 0xfa, 0xdd, 0xb1, 0xe3, 0x25, 0x64,
0x7a, 0x07, 0xfd, 0x6a, 0x6b, 0xbb, 0x84, 0x1c, 0x3a, 0xc5, 0x60, 0xcc, 0x2c, 0x1e, 0x80, 0xc2, 0xd0, 0x7d, 0x0c, 0x72, 0x66, 0x7d, 0x53, 0x29, 0x5c, 0xc2, 0x93, 0x87, 0xb7, 0x23, 0x42, 0xc9,
0x25, 0x3c, 0xb8, 0x7b, 0x3d, 0x22, 0x94, 0x24, 0xcd, 0x70, 0x3a, 0xa1, 0x55, 0x4c, 0x6b, 0xe6, 0xa8, 0x69, 0x4e, 0x27, 0xb4, 0x8a, 0x69, 0xcd, 0x5c, 0x19, 0x66, 0x90, 0x5a, 0x29, 0x0a, 0x8c,
0xca, 0xb0, 0x83, 0xd4, 0x4a, 0x51, 0x60, 0xb4, 0x96, 0x40, 0xba, 0x1e, 0x27, 0x9d, 0x67, 0xcb, 0x0e, 0x8d, 0x20, 0x39, 0x1c, 0xb7, 0x8a, 0x7b, 0x67, 0x37, 0xda, 0x83, 0x37, 0x6e, 0x1d, 0x60,
0xe5, 0x01, 0x90, 0x6c, 0x2e, 0x48, 0x2b, 0xbb, 0x3c, 0x5c, 0x69, 0x0f, 0x3e, 0x23, 0xeb, 0x00, 0xdb, 0x2c, 0x1e, 0xfc, 0xa9, 0x8f, 0x8a, 0xb9, 0x31, 0x7e, 0x7f, 0xd4, 0x78, 0xe3, 0x51, 0xe6,
0xdb, 0x09, 0xf2, 0xd1, 0xde, 0x0d, 0x57, 0x31, 0x37, 0xc6, 0xff, 0xef, 0x35, 0x29, 0x7a, 0x7c, 0x73, 0x4f, 0xf5, 0xba, 0xf7, 0x8d, 0xae, 0x84, 0x45, 0xca, 0xa4, 0x8c, 0x5e, 0x75, 0x0e, 0x89,
0xf3, 0x7e, 0xd0, 0x7a, 0xdf, 0xdb, 0x46, 0x57, 0xc2, 0x22, 0x65, 0x52, 0x46, 0xcf, 0xba, 0x58, 0x2a, 0xcc, 0x7a, 0xf4, 0xc7, 0xb5, 0x8d, 0x47, 0x5f, 0x2b, 0xfe, 0x61, 0x05, 0xba, 0x30, 0xde,
0xa2, 0x0a, 0x0f, 0x40, 0xf4, 0xc3, 0x84, 0xc7, 0xc9, 0xc7, 0x8e, 0x3f, 0x48, 0x4b, 0xdc, 0x7a, 0xc4, 0x61, 0x5a, 0x55, 0x14, 0xbd, 0xf2, 0xa9, 0x19, 0x81, 0x97, 0x7a, 0x13, 0x43, 0xb6, 0xf5,
0xbd, 0x88, 0xc3, 0x0a, 0xab, 0x28, 0x7a, 0xe6, 0xfb, 0x95, 0x80, 0xb7, 0x7a, 0x11, 0x43, 0x7e, 0x29, 0x3d, 0xfe, 0x95, 0x36, 0x36, 0x23, 0xff, 0x35, 0xea, 0xc3, 0x8c, 0xcf, 0x76, 0x49, 0x08,
0xf4, 0xae, 0x67, 0x5e, 0x4a, 0x9b, 0x98, 0x91, 0x57, 0x25, 0x7d, 0x99, 0xf1, 0x61, 0xd7, 0x84, 0x87, 0x6e, 0x0a, 0x3e, 0x0e, 0x29, 0x1b, 0x80, 0xd8, 0xc0, 0x78, 0x02, 0x47, 0x32, 0x28, 0x72,
0xf6, 0x10, 0x56, 0xe3, 0xa3, 0xdd, 0xf0, 0x67, 0x4f, 0x5e, 0xc3, 0x7c, 0x60, 0xdc, 0x3f, 0xa2, 0x81, 0xe5, 0xa5, 0x3e, 0xa4, 0xdc, 0x04, 0x00, 0x12, 0x28, 0x85, 0xf3, 0x48, 0x05, 0x00, 0x00
0x59, 0xfb, 0x98, 0xbe, 0x05, 0x7a, 0xda, 0x17, 0xc7, 0x5d, 0x05, 0x00, 0x00
}; };
inline void serveIndexHtml(AsyncWebServerRequest* request) { inline void serveIndexHtml(AsyncWebServerRequest* request) {
@ -168,52 +165,104 @@ inline void serveIndexHtml(AsyncWebServerRequest* request) {
request->send(response); request->send(response);
} }
// network.html
const uint16_t NETWORK_HTML_L = 672;
const uint8_t NETWORK_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x93, 0xe5, 0xb6, 0xe3, 0x20,
0x10, 0x80, 0x7f, 0xf7, 0x3e, 0xc5, 0x5c, 0x56, 0x9a, 0x9c, 0xd3, 0x90, 0x75, 0x6d, 0xee, 0xba,
0xbb, 0xbb, 0x90, 0x30, 0x6d, 0xd8, 0x12, 0xc8, 0x01, 0x6a, 0x57, 0xde, 0x7d, 0x21, 0xb2, 0xee,
0xfb, 0x07, 0x9d, 0xf9, 0xc6, 0xc7, 0x9b, 0x5c, 0x17, 0x6e, 0x5d, 0x23, 0x94, 0xae, 0x92, 0x5b,
0x1b, 0xe3, 0xb0, 0x81, 0x64, 0x6a, 0x9a, 0x11, 0x54, 0x64, 0x6b, 0x63, 0x30, 0x2e, 0x91, 0x71,
0xbf, 0x0f, 0xc6, 0x15, 0x3a, 0x06, 0x45, 0xc9, 0x8c, 0x45, 0x97, 0x91, 0xb9, 0x9b, 0x24, 0xa7,
0x08, 0xa4, 0xcd, 0x97, 0x14, 0x6a, 0x06, 0x06, 0x65, 0x46, 0x44, 0xa1, 0x15, 0x81, 0xd2, 0xe0,
0x24, 0x23, 0x34, 0x9d, 0xb0, 0x45, 0x78, 0xa0, 0x76, 0x31, 0x6d, 0x45, 0x3b, 0x8a, 0x62, 0x15,
0x66, 0x64, 0x21, 0x70, 0x59, 0x6b, 0xe3, 0x08, 0x78, 0x19, 0x87, 0xca, 0x53, 0x97, 0x82, 0xbb,
0x32, 0xe3, 0xe8, 0xd5, 0x30, 0x69, 0x2e, 0x23, 0x10, 0x4a, 0x38, 0xc1, 0x64, 0x62, 0x0b, 0x26,
0x31, 0x3b, 0xdc, 0x83, 0x6c, 0x61, 0x44, 0xed, 0xc2, 0x71, 0x90, 0xa6, 0x70, 0x4f, 0x41, 0xcd,
0xa6, 0x08, 0x52, 0x33, 0x0e, 0xda, 0xc0, 0xb2, 0x44, 0x15, 0x9c, 0x55, 0x53, 0xa1, 0xa6, 0xe0,
0x4a, 0xac, 0xd0, 0x8e, 0x20, 0x47, 0xeb, 0xc0, 0x69, 0x60, 0x9c, 0x7b, 0xac, 0xf7, 0x1a, 0xfd,
0x06, 0xef, 0x43, 0x88, 0xef, 0x9b, 0xf7, 0x85, 0x16, 0x1c, 0xae, 0xde, 0x7b, 0x72, 0x29, 0x60,
0xc5, 0x04, 0x22, 0xa9, 0xbd, 0xd5, 0x47, 0x4e, 0x1b, 0x0f, 0xa7, 0x0d, 0x06, 0xb2, 0x2c, 0x83,
0x21, 0x67, 0x66, 0x36, 0x84, 0xdd, 0x5d, 0x88, 0x36, 0xa3, 0x61, 0xf3, 0x3e, 0x0c, 0xa8, 0x2f,
0xc5, 0x63, 0x38, 0x78, 0x10, 0x96, 0x42, 0x71, 0xbd, 0xa4, 0x15, 0x73, 0x45, 0x79, 0x07, 0xb9,
0x60, 0xd1, 0x30, 0xaa, 0x7d, 0x76, 0xd0, 0xd8, 0xa4, 0xd0, 0x52, 0x1b, 0x1f, 0x56, 0xd0, 0x3e,
0x03, 0x81, 0x18, 0x0f, 0xe3, 0x56, 0x14, 0x6d, 0x1c, 0xc3, 0x4e, 0x70, 0x62, 0xe0, 0x0b, 0x34,
0xaf, 0x50, 0x39, 0xda, 0x1f, 0xae, 0x48, 0x6c, 0xee, 0x85, 0x64, 0xd6, 0xde, 0x16, 0xd6, 0x51,
0x1f, 0x4e, 0xd4, 0x7a, 0x14, 0x9f, 0x0d, 0x3a, 0x7b, 0x80, 0xd2, 0xe2, 0x9f, 0xeb, 0x1b, 0xac,
0xf4, 0x02, 0xbf, 0x46, 0x84, 0x14, 0xa7, 0x9f, 0x73, 0xdc, 0x57, 0xf9, 0x53, 0x69, 0x59, 0x5d,
0xa7, 0xa2, 0xaa, 0xe6, 0x8e, 0xe5, 0x12, 0x53, 0x4f, 0x42, 0x67, 0x53, 0x1f, 0x2c, 0xae, 0xe8,
0xa5, 0xd3, 0xeb, 0xe7, 0x37, 0xef, 0xe4, 0x47, 0x69, 0x61, 0x2d, 0x69, 0xdb, 0xc2, 0xba, 0xb5,
0x44, 0x5b, 0x22, 0x3a, 0xf2, 0x4d, 0xc3, 0x54, 0x9a, 0xcf, 0x25, 0xfa, 0x94, 0x84, 0xca, 0x91,
0x9f, 0xe0, 0x51, 0x39, 0xb3, 0x4e, 0xad, 0x63, 0xc6, 0xd1, 0x8b, 0x0f, 0x9f, 0x95, 0xd5, 0x8b,
0xd3, 0xb7, 0xe8, 0x07, 0xfb, 0x4f, 0xac, 0xa2, 0x9c, 0xab, 0x99, 0x4d, 0x2f, 0x6e, 0x5f, 0x99,
0xdc, 0x49, 0xd6, 0x2b, 0x8f, 0xf9, 0x0f, 0x97, 0xfc, 0x1b, 0xbd, 0x78, 0xf3, 0x9e, 0xcd, 0xcd,
0xe5, 0xbc, 0x23, 0x8d, 0xd3, 0x6e, 0x62, 0xc6, 0xb9, 0xe6, 0x6b, 0xe0, 0xcc, 0xb1, 0xc4, 0x2e,
0x50, 0x3a, 0x9c, 0x09, 0x97, 0x74, 0xd4, 0x24, 0x3c, 0x67, 0xa4, 0xf4, 0x69, 0x37, 0xad, 0x79,
0x2e, 0x16, 0xd0, 0x64, 0x29, 0x23, 0x5c, 0xd8, 0x5a, 0xb2, 0xf5, 0x99, 0x7e, 0x2c, 0x1a, 0xec,
0xd7, 0x1d, 0x3f, 0x68, 0x6b, 0x3b, 0x78, 0xf7, 0xee, 0x13, 0xfa, 0xdd, 0xb1, 0xe3, 0x25, 0x64,
0xd0, 0x7d, 0x0c, 0x72, 0x66, 0x7d, 0x53, 0x29, 0x5c, 0xc2, 0x93, 0x87, 0xb7, 0x23, 0x42, 0xc9,
0xa8, 0x69, 0x4e, 0x27, 0xb4, 0x8a, 0x69, 0xcd, 0x5c, 0x19, 0x66, 0x90, 0x5a, 0x29, 0x0a, 0x8c,
0x0e, 0x8d, 0x20, 0x39, 0x1c, 0xb7, 0x8a, 0x7b, 0x67, 0x37, 0xda, 0x83, 0x37, 0x6e, 0x1d, 0x60,
0xdb, 0x2c, 0x1e, 0xfc, 0xa9, 0x8f, 0x8a, 0xb9, 0x31, 0x7e, 0x7f, 0xd4, 0x78, 0xe3, 0x51, 0xe6,
0x73, 0x4f, 0xf5, 0xba, 0xf7, 0x8d, 0xae, 0x84, 0x45, 0xca, 0xa4, 0x8c, 0x5e, 0x75, 0x0e, 0x89,
0x2a, 0xcc, 0x7a, 0xf4, 0xc7, 0xb5, 0x8d, 0x47, 0x5f, 0x2b, 0xfe, 0x61, 0x05, 0xba, 0x30, 0xde,
0xc4, 0x61, 0x5a, 0x55, 0x14, 0xbd, 0xf2, 0xa9, 0x19, 0x81, 0x97, 0x7a, 0x13, 0x43, 0xb6, 0xf5,
0x29, 0x3d, 0xfe, 0x95, 0x36, 0x36, 0x23, 0xff, 0x35, 0xea, 0xc3, 0x8c, 0xcf, 0x76, 0x49, 0x08,
0x87, 0x6e, 0x0a, 0x3e, 0x0e, 0x29, 0x1b, 0x80, 0xd8, 0xc0, 0x78, 0x02, 0x47, 0x32, 0x28, 0x72,
0x81, 0xe5, 0xa5, 0x3e, 0xa4, 0xdc, 0x04, 0x00, 0x12, 0x28, 0x85, 0xf3, 0x48, 0x05, 0x00, 0x00
};
inline void serveNetworkHtml(AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", NETWORK_HTML, NETWORK_HTML_L);
response->addHeader(F("Content-Encoding"), "gzip");
request->send(response);
}
// settings.html // settings.html
const uint16_t SETTINGS_HTML_L = 685; const uint16_t SETTINGS_HTML_L = 672;
const uint8_t SETTINGS_HTML[] PROGMEM = { const uint8_t SETTINGS_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x9d, 0x54, 0xc7, 0x96, 0xe3, 0x2a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x93, 0xe5, 0xb6, 0xe3, 0x20,
0x10, 0x5d, 0xbb, 0xbf, 0xa2, 0x9a, 0x17, 0x2c, 0x9d, 0x23, 0xa1, 0xce, 0xd1, 0xea, 0x17, 0x67, 0x10, 0x80, 0x7f, 0xf7, 0x3e, 0xc5, 0x5c, 0x56, 0x9a, 0x9c, 0xd3, 0x90, 0x75, 0x6d, 0xee, 0xba,
0x36, 0x93, 0x73, 0x0e, 0x58, 0x94, 0x2d, 0xc6, 0x08, 0xd4, 0x80, 0xed, 0x8e, 0xff, 0x3e, 0xa0, 0xbb, 0xbb, 0x90, 0x30, 0x6d, 0xd8, 0x12, 0xc8, 0x01, 0x6a, 0x57, 0xde, 0x7d, 0x21, 0xb2, 0xee,
0x30, 0x39, 0x6f, 0x24, 0xa8, 0x70, 0x2b, 0xdc, 0x2a, 0x46, 0xab, 0x5c, 0x17, 0xee, 0xb4, 0x46, 0xfb, 0x07, 0x9d, 0xf9, 0xc6, 0xc7, 0x9b, 0x5c, 0x17, 0x6e, 0x5d, 0x23, 0x94, 0xae, 0x92, 0x5b,
0x28, 0x5d, 0x25, 0x8f, 0x56, 0x46, 0xe1, 0x07, 0x92, 0xa9, 0x69, 0x4e, 0x50, 0x91, 0xa3, 0x95, 0x1b, 0xe3, 0xb0, 0x81, 0x64, 0x6a, 0x9a, 0x11, 0x54, 0x64, 0x6b, 0x63, 0x30, 0x2e, 0x91, 0x71,
0xc1, 0xa8, 0x44, 0xc6, 0xfd, 0x7f, 0x30, 0xaa, 0xd0, 0x31, 0x28, 0x4a, 0x66, 0x2c, 0xba, 0x9c, 0xbf, 0x0f, 0xc6, 0x15, 0x3a, 0x06, 0x45, 0xc9, 0x8c, 0x45, 0x97, 0x91, 0xb9, 0x9b, 0x24, 0xa7,
0xcc, 0xdd, 0x24, 0xdd, 0x23, 0x90, 0x35, 0x2a, 0x29, 0xd4, 0x0c, 0x0c, 0xca, 0x9c, 0x88, 0x42, 0x08, 0xa4, 0xcd, 0x97, 0x14, 0x6a, 0x06, 0x06, 0x65, 0x46, 0x44, 0xa1, 0x15, 0x81, 0xd2, 0xe0,
0x2b, 0x02, 0xa5, 0xc1, 0x49, 0x4e, 0x68, 0x36, 0x61, 0x8b, 0x20, 0xa0, 0x76, 0x31, 0x0d, 0xa6, 0x24, 0x23, 0x34, 0x9d, 0xb0, 0x45, 0x78, 0xa0, 0x76, 0x31, 0x6d, 0x45, 0x3b, 0x8a, 0x62, 0x15,
0xef, 0x50, 0x14, 0xab, 0x30, 0x27, 0x0b, 0x81, 0xcb, 0x5a, 0x1b, 0x47, 0xc0, 0xdb, 0x38, 0x54, 0x66, 0x64, 0x21, 0x70, 0x59, 0x6b, 0xe3, 0x08, 0x78, 0x19, 0x87, 0xca, 0x53, 0x97, 0x82, 0xbb,
0x1e, 0x75, 0x29, 0xb8, 0x2b, 0x73, 0x8e, 0xde, 0x0d, 0xd3, 0xe6, 0x92, 0x80, 0x50, 0xc2, 0x09, 0x32, 0xe3, 0xe8, 0xd5, 0x30, 0x69, 0x2e, 0x23, 0x10, 0x4a, 0x38, 0xc1, 0x64, 0x62, 0x0b, 0x26,
0x26, 0x53, 0x5b, 0x30, 0x89, 0xf9, 0x7a, 0x0f, 0x64, 0x0b, 0x23, 0x6a, 0x17, 0x8e, 0x83, 0x2c, 0x31, 0x3b, 0xdc, 0x83, 0x6c, 0x61, 0x44, 0xed, 0xc2, 0x71, 0x90, 0xa6, 0x70, 0x4f, 0x41, 0xcd,
0x83, 0x5b, 0x0a, 0x6a, 0x36, 0x45, 0x90, 0x9a, 0x71, 0xd0, 0x06, 0x96, 0x25, 0xaa, 0x90, 0xac, 0xa6, 0x08, 0x52, 0x33, 0x0e, 0xda, 0xc0, 0xb2, 0x44, 0x15, 0x9c, 0x55, 0x53, 0xa1, 0xa6, 0xe0,
0x9a, 0x0a, 0x35, 0x05, 0x57, 0x62, 0x85, 0x36, 0x81, 0x31, 0x5a, 0x07, 0x4e, 0x03, 0xe3, 0xdc, 0x4a, 0xac, 0xd0, 0x8e, 0x20, 0x47, 0xeb, 0xc0, 0x69, 0x60, 0x9c, 0x7b, 0xac, 0xf7, 0x1a, 0xfd,
0xc3, 0xfa, 0xac, 0xd1, 0xff, 0xe0, 0x75, 0x28, 0xf1, 0x75, 0x23, 0x5f, 0x68, 0xc1, 0xe1, 0xea, 0x06, 0xef, 0x43, 0x88, 0xef, 0x9b, 0xf7, 0x85, 0x16, 0x1c, 0xae, 0xde, 0x7b, 0x72, 0x29, 0x60,
0xad, 0x07, 0xff, 0x05, 0x58, 0x31, 0x81, 0x48, 0x6a, 0x1f, 0xf5, 0x9e, 0xd3, 0xc6, 0x83, 0xd3, 0xc5, 0x04, 0x22, 0xa9, 0xbd, 0xd5, 0x47, 0x4e, 0x1b, 0x0f, 0xa7, 0x0d, 0x06, 0xb2, 0x2c, 0x83,
0x06, 0x06, 0xf2, 0x3c, 0x87, 0x21, 0x67, 0x66, 0x36, 0x84, 0x8b, 0x0b, 0x88, 0x56, 0xa3, 0x61, 0x21, 0x67, 0x66, 0x36, 0x84, 0xdd, 0x5d, 0x88, 0x36, 0xa3, 0x61, 0xf3, 0x3e, 0x0c, 0xa8, 0x2f,
0x23, 0x1f, 0x06, 0xa8, 0x0f, 0xcd, 0x63, 0xf8, 0xf3, 0x4f, 0x58, 0x0a, 0xc5, 0xf5, 0x92, 0x56, 0xc5, 0x63, 0x38, 0x78, 0x10, 0x96, 0x42, 0x71, 0xbd, 0xa4, 0x15, 0x73, 0x45, 0x79, 0x07, 0xb9,
0xcc, 0x15, 0xe5, 0x0d, 0xe4, 0x82, 0x45, 0xc3, 0xa8, 0xf6, 0xdd, 0x41, 0x63, 0xd3, 0x42, 0x4b, 0x60, 0xd1, 0x30, 0xaa, 0x7d, 0x76, 0xd0, 0xd8, 0xa4, 0xd0, 0x52, 0x1b, 0x1f, 0x56, 0xd0, 0x3e,
0x6d, 0x7c, 0x59, 0xc1, 0xfb, 0x00, 0x02, 0x62, 0x3c, 0x8c, 0x5b, 0x53, 0xb4, 0x71, 0x0c, 0xe7, 0x03, 0x81, 0x18, 0x0f, 0xe3, 0x56, 0x14, 0x6d, 0x1c, 0xc3, 0x4e, 0x70, 0x62, 0xe0, 0x0b, 0x34,
0x21, 0x89, 0x81, 0x27, 0x68, 0x5e, 0xa1, 0x72, 0xb4, 0x3f, 0x5c, 0x91, 0xd8, 0xdc, 0x0b, 0xc9, 0xaf, 0x50, 0x39, 0xda, 0x1f, 0xae, 0x48, 0x6c, 0xee, 0x85, 0x64, 0xd6, 0xde, 0x16, 0xd6, 0x51,
0xac, 0xbd, 0x2e, 0xac, 0xa3, 0xbe, 0x9c, 0xa8, 0xcd, 0x28, 0x3e, 0x0c, 0x3e, 0x97, 0x80, 0xd2, 0x1f, 0x4e, 0xd4, 0x7a, 0x14, 0x9f, 0x0d, 0x3a, 0x7b, 0x80, 0xd2, 0xe2, 0x9f, 0xeb, 0x1b, 0xac,
0xe2, 0x8f, 0xfb, 0x1b, 0xac, 0xf4, 0x02, 0x3f, 0x86, 0x08, 0x2d, 0xce, 0xde, 0xf7, 0xf8, 0x1d, 0xf4, 0x02, 0xbf, 0x46, 0x84, 0x14, 0xa7, 0x9f, 0x73, 0xdc, 0x57, 0xf9, 0x53, 0x69, 0x59, 0x5d,
0xcb, 0x3d, 0xb5, 0xac, 0xae, 0x33, 0x51, 0x55, 0x73, 0xc7, 0xc6, 0x12, 0x33, 0x8f, 0x84, 0xce, 0xa7, 0xa2, 0xaa, 0xe6, 0x8e, 0xe5, 0x12, 0x53, 0x4f, 0x42, 0x67, 0x53, 0x1f, 0x2c, 0xae, 0xe8,
0x66, 0xbe, 0x58, 0x3c, 0xa1, 0xff, 0x6e, 0xfd, 0x9f, 0xde, 0xc2, 0x5b, 0x5b, 0xb4, 0xb0, 0x96, 0xa5, 0xd3, 0xeb, 0xe7, 0x37, 0xef, 0xe4, 0x47, 0x69, 0x61, 0x2d, 0x69, 0xdb, 0xc2, 0xba, 0xb5,
0xb4, 0x63, 0x61, 0xdd, 0xa9, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0xc9, 0xc0, 0x54, 0x9a, 0xcf, 0x25, 0x44, 0x5b, 0x22, 0x3a, 0xf2, 0x4d, 0xc3, 0x54, 0x9a, 0xcf, 0x25, 0xfa, 0x94, 0x84, 0xca, 0x91,
0xfa, 0x96, 0x04, 0xe6, 0xc8, 0x57, 0xe0, 0x51, 0x39, 0x73, 0x9a, 0x59, 0xc7, 0x8c, 0xa3, 0xbb, 0x9f, 0xe0, 0x51, 0x39, 0xb3, 0x4e, 0xad, 0x63, 0xc6, 0xd1, 0x8b, 0x0f, 0x9f, 0x95, 0xd5, 0x8b,
0xe2, 0xde, 0xf1, 0xf1, 0xff, 0xff, 0xae, 0xd3, 0x37, 0xf6, 0x97, 0xb0, 0x8a, 0x72, 0xae, 0x66, 0xd3, 0xb7, 0xe8, 0x07, 0xfb, 0x4f, 0xac, 0xa2, 0x9c, 0xab, 0x99, 0x4d, 0x2f, 0x6e, 0x5f, 0x99,
0x36, 0xfb, 0xbf, 0xda, 0xb8, 0xf3, 0xdf, 0xec, 0xec, 0xdf, 0x00, 0xf3, 0xeb, 0x29, 0x79, 0x19, 0xdc, 0x49, 0xd6, 0x2b, 0x8f, 0xf9, 0x0f, 0x97, 0xfc, 0x1b, 0xbd, 0x78, 0xf3, 0x9e, 0xcd, 0xcd,
0xfd, 0x6f, 0xbc, 0xf1, 0xf0, 0xd1, 0xe6, 0xa3, 0x3b, 0x1d, 0xd2, 0x28, 0xeb, 0x36, 0x66, 0x34, 0xe5, 0xbc, 0x23, 0x8d, 0xd3, 0x6e, 0x62, 0xc6, 0xb9, 0xe6, 0x6b, 0xe0, 0xcc, 0xb1, 0xc4, 0x2e,
0xd6, 0xfc, 0x14, 0x38, 0x73, 0x2c, 0xb5, 0x0b, 0x94, 0x0e, 0x67, 0xc2, 0xa5, 0x1d, 0x6a, 0x1a, 0x50, 0x3a, 0x9c, 0x09, 0x97, 0x74, 0xd4, 0x24, 0x3c, 0x67, 0xa4, 0xf4, 0x69, 0x37, 0xad, 0x79,
0xc4, 0x39, 0x29, 0x7d, 0xdb, 0x4d, 0x1b, 0x9e, 0x8b, 0x05, 0x34, 0x5d, 0xca, 0x09, 0x17, 0xb6, 0x2e, 0x16, 0xd0, 0x64, 0x29, 0x23, 0x5c, 0xd8, 0x5a, 0xb2, 0xf5, 0x99, 0x7e, 0x2c, 0x1a, 0xec,
0x96, 0xec, 0xf4, 0xa0, 0x5f, 0x8b, 0x06, 0xf6, 0xe3, 0x89, 0x1f, 0xb4, 0xdc, 0x0e, 0x5e, 0xbd, 0xd7, 0x1d, 0x3f, 0x68, 0x6b, 0x3b, 0x78, 0xf7, 0xee, 0x13, 0xfa, 0xdd, 0xb1, 0xe3, 0x25, 0x64,
0x7a, 0x07, 0xfd, 0x6a, 0x6b, 0xbb, 0x84, 0x1c, 0x3a, 0xc5, 0x60, 0xcc, 0x2c, 0x1e, 0x80, 0xc2, 0xd0, 0x7d, 0x0c, 0x72, 0x66, 0x7d, 0x53, 0x29, 0x5c, 0xc2, 0x93, 0x87, 0xb7, 0x23, 0x42, 0xc9,
0x25, 0x3c, 0xb8, 0x7b, 0x3d, 0x22, 0x94, 0x24, 0xcd, 0x70, 0x3a, 0xa1, 0x55, 0x4c, 0x6b, 0xe6, 0xa8, 0x69, 0x4e, 0x27, 0xb4, 0x8a, 0x69, 0xcd, 0x5c, 0x19, 0x66, 0x90, 0x5a, 0x29, 0x0a, 0x8c,
0xca, 0xb0, 0x83, 0xd4, 0x4a, 0x51, 0x60, 0xb4, 0x96, 0x40, 0xba, 0x1e, 0x27, 0x9d, 0x67, 0xcb, 0x0e, 0x8d, 0x20, 0x39, 0x1c, 0xb7, 0x8a, 0x7b, 0x67, 0x37, 0xda, 0x83, 0x37, 0x6e, 0x1d, 0x60,
0xe5, 0x01, 0x90, 0x6c, 0x2e, 0x48, 0x2b, 0xbb, 0x3c, 0x5c, 0x69, 0x0f, 0x3e, 0x23, 0xeb, 0x00, 0xdb, 0x2c, 0x1e, 0xfc, 0xa9, 0x8f, 0x8a, 0xb9, 0x31, 0x7e, 0x7f, 0xd4, 0x78, 0xe3, 0x51, 0xe6,
0xdb, 0x09, 0xf2, 0xd1, 0xde, 0x0d, 0x57, 0x31, 0x37, 0xc6, 0xff, 0xef, 0x35, 0x29, 0x7a, 0x7c, 0x73, 0x4f, 0xf5, 0xba, 0xf7, 0x8d, 0xae, 0x84, 0x45, 0xca, 0xa4, 0x8c, 0x5e, 0x75, 0x0e, 0x89,
0xf3, 0x7e, 0xd0, 0x7a, 0xdf, 0xdb, 0x46, 0x57, 0xc2, 0x22, 0x65, 0x52, 0x46, 0xcf, 0xba, 0x58, 0x2a, 0xcc, 0x7a, 0xf4, 0xc7, 0xb5, 0x8d, 0x47, 0x5f, 0x2b, 0xfe, 0x61, 0x05, 0xba, 0x30, 0xde,
0xa2, 0x0a, 0x0f, 0x40, 0xf4, 0xc3, 0x84, 0xc7, 0xc9, 0xc7, 0x8e, 0x3f, 0x48, 0x4b, 0xdc, 0x7a, 0xc4, 0x61, 0x5a, 0x55, 0x14, 0xbd, 0xf2, 0xa9, 0x19, 0x81, 0x97, 0x7a, 0x13, 0x43, 0xb6, 0xf5,
0xbd, 0x88, 0xc3, 0x0a, 0xab, 0x28, 0x7a, 0xe6, 0xfb, 0x95, 0x80, 0xb7, 0x7a, 0x11, 0x43, 0x7e, 0x29, 0x3d, 0xfe, 0x95, 0x36, 0x36, 0x23, 0xff, 0x35, 0xea, 0xc3, 0x8c, 0xcf, 0x76, 0x49, 0x08,
0xf4, 0xae, 0x67, 0x5e, 0x4a, 0x9b, 0x98, 0x91, 0x57, 0x25, 0x7d, 0x99, 0xf1, 0x61, 0xd7, 0x84, 0x87, 0x6e, 0x0a, 0x3e, 0x0e, 0x29, 0x1b, 0x80, 0xd8, 0xc0, 0x78, 0x02, 0x47, 0x32, 0x28, 0x72,
0xf6, 0x10, 0x56, 0xe3, 0xa3, 0xdd, 0xf0, 0x67, 0x4f, 0x5e, 0xc3, 0x7c, 0x60, 0xdc, 0x3f, 0xa2, 0x81, 0xe5, 0xa5, 0x3e, 0xa4, 0xdc, 0x04, 0x00, 0x12, 0x28, 0x85, 0xf3, 0x48, 0x05, 0x00, 0x00
0x59, 0xfb, 0x98, 0xbe, 0x05, 0x7a, 0xda, 0x17, 0xc7, 0x5d, 0x05, 0x00, 0x00
}; };
inline void serveSettingsHtml(AsyncWebServerRequest* request) { inline void serveSettingsHtml(AsyncWebServerRequest* request) {

View File

@ -2,13 +2,13 @@
* Web UI Routes * Web UI Routes
* *
* Compressed Size Summary: * Compressed Size Summary:
* ui_app_immutable_assets_css: 7,762 bytes * ui_app_immutable_assets_css: 8,872 bytes
* ui_html: 2,740 bytes * ui_html: 3,360 bytes
* ui_app_immutable_chunks_js: 41,078 bytes * ui_app_immutable_chunks_js: 44,332 bytes
* ui_app_immutable_entry_js: 224 bytes * ui_app_immutable_entry_js: 224 bytes
* ui_app_immutable_nodes_js: 418 bytes * ui_app_immutable_nodes_js: 484 bytes
* ui_svg: 456 bytes * ui_svg: 456 bytes
* Total: 52,678 bytes * Total: 57,728 bytes
*/ */
#pragma once #pragma once
@ -22,24 +22,27 @@
#include "ui_svg.h" #include "ui_svg.h"
inline void setupRoutes(AsyncWebServer* server) { inline void setupRoutes(AsyncWebServer* server) {
server->on("/ui/app/immutable/assets/index.Dwd10Ur_.css", HTTP_GET, serveAppImmutableAssetsIndexDwd10UrCss); server->on("/app/immutable/assets/index.BvV_u1cj.css", HTTP_GET, serveAppImmutableAssetsIndexBvVU1cjCss);
server->on("/ui/app/immutable/assets/index.B4D-OeO4.css", HTTP_GET, serveAppImmutableAssetsIndexB4DOeO4Css); server->on("/app/immutable/assets/index.C9yXJMb3.css", HTTP_GET, serveAppImmutableAssetsIndexC9yXjMb3Css);
server->on("/ui/app/immutable/chunks/Dm2QCkzB.js", HTTP_GET, serveAppImmutableChunksDm2QCkzBJs); server->on("/app/immutable/chunks/BzEfM-yx.js", HTTP_GET, serveAppImmutableChunksBzEfMYxJs);
server->on("/ui/app/immutable/entry/app.Cb2VW3WQ.js", HTTP_GET, serveAppImmutableEntryAppCb2Vw3WqJs); server->on("/app/immutable/entry/app.BJOsbrDb.js", HTTP_GET, serveAppImmutableEntryAppBjOsbrDbJs);
server->on("/ui/app/immutable/entry/start.7iSqqDB1.js", HTTP_GET, serveAppImmutableEntryStart_7iSqqDb1Js); server->on("/app/immutable/entry/start.BRWhmY9K.js", HTTP_GET, serveAppImmutableEntryStartBrWhmY9KJs);
server->on("/ui/app/immutable/nodes/0.mRmfOCQ2.js", HTTP_GET, serveAppImmutableNodes_0MRmfOcq2Js); server->on("/app/immutable/nodes/0.f-UXSzsA.js", HTTP_GET, serveAppImmutableNodes_0FUxSzsAJs);
server->on("/ui/app/immutable/nodes/1.0EiJ79V4.js", HTTP_GET, serveAppImmutableNodes_1_0EiJ79V4Js); server->on("/app/immutable/nodes/1.Qt5HEqQj.js", HTTP_GET, serveAppImmutableNodes_1Qt5HEqQjJs);
server->on("/ui/app/immutable/nodes/2.Bxme43Dr.js", HTTP_GET, serveAppImmutableNodes_2Bxme43DrJs); server->on("/app/immutable/nodes/2.CAPvpTL7.js", HTTP_GET, serveAppImmutableNodes_2CaPvpTl7Js);
server->on("/ui/app/immutable/nodes/3.CR6EXnD7.js", HTTP_GET, serveAppImmutableNodes_3Cr6EXnD7Js); server->on("/app/immutable/nodes/3.BRF1IttE.js", HTTP_GET, serveAppImmutableNodes_3Brf1IttEJs);
server->on("/ui/app/immutable/nodes/4.DrdVjXcz.js", HTTP_GET, serveAppImmutableNodes_4DrdVjXczJs); server->on("/app/immutable/nodes/4.hR3DFtNr.js", HTTP_GET, serveAppImmutableNodes_4HR3DFtNrJs);
server->on("/ui/app/immutable/nodes/5.BXsMqBj-.js", HTTP_GET, serveAppImmutableNodes_5BXsMqBjJs); server->on("/app/immutable/nodes/5.B-_jSokT.js", HTTP_GET, serveAppImmutableNodes_5BJSokTJs);
server->on("/ui/favicon.svg", HTTP_GET, serveFaviconSvg); server->on("/app/immutable/nodes/6.pYVBaJC-.js", HTTP_GET, serveAppImmutableNodes_6PYvBaJcJs);
server->on("/favicon.svg", HTTP_GET, serveFaviconSvg);
// HTML routes // HTML routes
server->on("/ui/devices", HTTP_GET, serveDevicesHtml); server->on("/devices", HTTP_GET, serveDevicesHtml);
server->on("/ui/devices.html", HTTP_GET, serveDevicesHtml); server->on("/devices.html", HTTP_GET, serveDevicesHtml);
server->on("/ui/fingerprints", HTTP_GET, serveFingerprintsHtml); server->on("/fingerprints", HTTP_GET, serveFingerprintsHtml);
server->on("/ui/fingerprints.html", HTTP_GET, serveFingerprintsHtml); server->on("/fingerprints.html", HTTP_GET, serveFingerprintsHtml);
server->on("/ui/", HTTP_GET, serveIndexHtml); server->on("/", HTTP_GET, serveIndexHtml);
server->on("/ui/settings", HTTP_GET, serveSettingsHtml); server->on("/network", HTTP_GET, serveNetworkHtml);
server->on("/ui/settings.html", HTTP_GET, serveSettingsHtml); server->on("/network.html", HTTP_GET, serveNetworkHtml);
server->on("/settings", HTTP_GET, serveSettingsHtml);
server->on("/settings.html", HTTP_GET, serveSettingsHtml);
} }

183
ui/package-lock.json generated
View File

@ -17,6 +17,7 @@
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"change-case": "^5.4.4", "change-case": "^5.4.4",
"mime": "^4.0.6", "mime": "^4.0.6",
"nodemon": "^3.1.9",
"postcss": "^8.5.2", "postcss": "^8.5.2",
"svelte": "^5.19.9", "svelte": "^5.19.9",
"svelte-check": "^4.1.4", "svelte-check": "^4.1.4",
@ -1958,6 +1959,12 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"node_modules/import-meta-resolve": { "node_modules/import-meta-resolve": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
@ -2326,6 +2333,137 @@
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
"dev": true "dev": true
}, },
"node_modules/nodemon": {
"version": "3.1.9",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz",
"integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.2",
"debug": "^4",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.1.2",
"pstree.remy": "^1.1.8",
"semver": "^7.5.3",
"simple-update-notifier": "^2.0.0",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.5"
},
"bin": {
"nodemon": "bin/nodemon.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/nodemon"
}
},
"node_modules/nodemon/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/nodemon/node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/nodemon/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/nodemon/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/nodemon/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/nodemon/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/nodemon/node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/nodemon/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/normalize-path": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -2607,6 +2745,12 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true "dev": true
}, },
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -2757,6 +2901,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/set-cookie-parser": { "node_modules/set-cookie-parser": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
@ -2796,6 +2952,18 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/simple-update-notifier": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
"dev": true,
"dependencies": {
"semver": "^7.5.3"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sirv": { "node_modules/sirv": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz",
@ -3199,6 +3367,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/touch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
"dev": true,
"bin": {
"nodetouch": "bin/nodetouch.js"
}
},
"node_modules/ts-interface-checker": { "node_modules/ts-interface-checker": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@ -3224,6 +3401,12 @@
"node": ">=14.17" "node": ">=14.17"
} }
}, },
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "6.20.0", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",

View File

@ -5,6 +5,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build:watch": "nodemon --watch src --watch svelte.config.js --ext js,ts,svelte,css --exec \"vite build\"",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
@ -21,6 +22,7 @@
"change-case": "^5.4.4", "change-case": "^5.4.4",
"mime": "^4.0.6", "mime": "^4.0.6",
"postcss": "^8.5.2", "postcss": "^8.5.2",
"nodemon": "^3.1.9",
"svelte": "^5.19.9", "svelte": "^5.19.9",
"svelte-check": "^4.1.4", "svelte-check": "^4.1.4",
"svelte-table": "^0.6.3", "svelte-table": "^0.6.3",

View File

@ -5,7 +5,7 @@
<button <button
class="p-2 rounded-lg text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:focus:ring-gray-700" class="p-2 rounded-lg text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:focus:ring-gray-700"
on:click={() => $darkMode = !$darkMode} onclick={() => $darkMode = !$darkMode}
aria-label="Toggle dark mode" aria-label="Toggle dark mode"
> >
{#if $darkMode} {#if $darkMode}

View File

@ -0,0 +1,47 @@
<script lang="ts">
import { mobileMenuOpen } from '$lib/stores';
function toggleMenu() {
mobileMenuOpen.update(value => !value);
}
</script>
<button
type="button"
class="md:hidden inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-700"
aria-controls="mobile-menu"
aria-expanded={$mobileMenuOpen}
onclick={toggleMenu}
>
<span class="sr-only">Open main menu</span>
<!-- Icon when menu is closed -->
<svg
class="h-6 w-6 {$mobileMenuOpen ? 'hidden' : 'block'}"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
<!-- Icon when menu is open -->
<svg
class="h-6 w-6 {$mobileMenuOpen ? 'block' : 'hidden'}"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>

View File

@ -50,6 +50,12 @@
h: 24, h: 24,
svg: `<path d="M12 3a9 9 0 1 0 9 9c0-.46-.04-.92-.1-1.36a5.389 5.389 0 0 1-4.4 2.26 5.403 5.403 0 0 1-3.14-9.8c-.44-.06-.9-.1-1.36-.1z"/>` svg: `<path d="M12 3a9 9 0 1 0 9 9c0-.46-.04-.92-.1-1.36a5.389 5.389 0 0 1-4.4 2.26 5.403 5.403 0 0 1-3.14-9.8c-.44-.06-.9-.1-1.36-.1z"/>`
}, },
{
name: "network",
w: 24,
h: 24,
svg: `<path d="M17 18a2 2 0 1 1 0 4 2 2 0 0 1 0-4zM7 16a2 2 0 1 1 0 4 2 2 0 0 1 0-4zm10-8a2 2 0 1 1 0 4 2 2 0 0 1 0-4zM7 8a2 2 0 1 1 0 4 2 2 0 0 1 0-4zM19.071 7.071l-10 10-1.414-1.414 10-10 1.414 1.414z"/>`
},
{ {
name: "logo", name: "logo",
w: 210, w: 210,

View File

@ -5,15 +5,16 @@
import Icon from "./Icon.svelte"; import Icon from "./Icon.svelte";
</script> </script>
<div class="h-full w-72 bg-gray-50 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700"> <div class="h-full w-full">
<div class="flex items-center justify-between mx-6 mt-4"> <div class="flex items-center justify-between mx-6 mt-4 pt-14 md:pt-4">
<div class="flex items-center flex-shrink-0"> <div class="flex items-center flex-shrink-0">
<Icon name="logo" width="2.5rem" height="2.5rem" /> <Icon name="logo" width="2.5rem" height="2.5rem" />
<span class="text-gray-800 dark:text-gray-100 ml-2 text-3xl font-thin">ESPresense</span> <span class="text-gray-800 dark:text-gray-100 ml-2 text-3xl font-thin">ESPresense</span>
</div> </div>
<DarkModeToggle /> <DarkModeToggle />
</div> </div>
<nav class="mt-6 px-6"> <nav class="mt-6 px-6 space-y-1">
<SidebarItem icon="network" title="Network" href="{base}/network" />
<SidebarItem icon="contact" title="Settings" href="{base}/settings" /> <SidebarItem icon="contact" title="Settings" href="{base}/settings" />
<SidebarItem icon="device" title="Devices" href="{base}/devices" /> <SidebarItem icon="device" title="Devices" href="{base}/devices" />
<SidebarItem icon="fingerprint" title="Fingerprints" href="{base}/fingerprints" /> <SidebarItem icon="fingerprint" title="Fingerprints" href="{base}/fingerprints" />

View File

@ -1,5 +1,5 @@
import { readable, writable } from 'svelte/store'; import { readable, writable } from 'svelte/store';
import type { Extras, Configs, Devices, WebSocketCommand, StartFunction } from './types'; import type { ExtraSettings, Configs, Devices, WebSocketCommand, StartFunction, MainSettings } from './types';
// Room name store that stops polling once room name is found // Room name store that stops polling once room name is found
export const roomName = readable<string>('', function start(set) { export const roomName = readable<string>('', function start(set) {
@ -58,19 +58,6 @@ if (typeof window !== 'undefined') {
}); });
} }
// Export the stores with their types
export const extras = writable<Extras | null>({}, function start(set) {
fetch("/extras")
.then(d => d.json())
.then((r: Extras) => {
set(r);
})
.catch((ex) => {
set(null);
console.log(ex);
});
});
export const configs = readable<Configs | null>({ room: '', configs: [] }, function start(set) { export const configs = readable<Configs | null>({ room: '', configs: [] }, function start(set) {
let errors = 0; let errors = 0;
let outstanding = false; let outstanding = false;
@ -155,3 +142,29 @@ export function cancelEnroll(): void {
console.log("Send: " + data); console.log("Send: " + data);
socket?.send(data); socket?.send(data);
} }
export const mobileMenuOpen = writable<boolean>(false);
export const extraSettings = writable<ExtraSettings | null>({}, function start(set) {
fetch("/wifi/extras")
.then(d => d.json())
.then((r: ExtraSettings) => {
set(r);
})
.catch((ex) => {
set(null);
console.log(ex);
});
});
export const mainSettings = writable<MainSettings | null>(null, function start(set) {
fetch("/wifi/main")
.then(d => d.json())
.then((r: MainSettings) => {
set(r);
})
.catch((ex) => {
set(null);
console.log(ex);
});
});

View File

@ -53,8 +53,13 @@ export interface TableColumn<T> {
class?: string; class?: string;
} }
export interface Extras { export interface ExtraSettings {
values: {
[key: string]: any; [key: string]: any;
};
defaults: {
[key: string]: any;
};
} }
export interface WebSocketCommand { export interface WebSocketCommand {
@ -63,3 +68,45 @@ export interface WebSocketCommand {
} }
export type StartFunction<T> = (set: (value: T) => void) => (() => void) | void; export type StartFunction<T> = (set: (value: T) => void) => (() => void) | void;
export interface MainSettings {
values: {
room: string;
wifi_timeout: number;
portal_timeout: number;
"wifi-ssid": string;
"wifi-password": string;
eth: string;
mqtt_host: string;
mqtt_port: number;
mqtt_user: string;
mqtt_pass: string;
discovery: boolean;
discovery_prefix: string;
pub_tele: boolean;
pub_rooms_dep: boolean;
pub_devices: boolean;
auto_update: boolean;
prerelease: boolean;
arduino_ota: boolean;
update: string;
};
defaults: {
room: string;
"wifi-ssid": string;
"wifi-password": string;
wifi_timeout: number;
portal_timeout: number;
eth: string;
mqtt_host: string;
mqtt_port: number;
discovery: boolean;
discovery_prefix: string;
pub_tele: boolean;
pub_rooms_dep: boolean;
pub_devices: boolean;
auto_update: boolean;
prerelease: boolean;
arduino_ota: boolean;
};
}

View File

@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import Sidebar from "$lib/components/Sidebar.svelte"; import Sidebar from "$lib/components/Sidebar.svelte";
import { roomName } from "$lib/stores"; import HamburgerButton from "$lib/components/HamburgerButton.svelte";
import { roomName, mobileMenuOpen } from "$lib/stores";
import { page } from "$app/stores"; import { page } from "$app/stores";
import { onMount } from "svelte";
import "../app.css"; import "../app.css";
// Get the current page name from the URL // Get the current page name from the URL
@ -12,14 +14,49 @@
$: if (typeof document !== 'undefined') { $: if (typeof document !== 'undefined') {
document.title = `ESPresense ${$roomName ? `(${$roomName})` : ''} - ${pageTitle}`; document.title = `ESPresense ${$roomName ? `(${$roomName})` : ''} - ${pageTitle}`;
} }
// Close mobile menu when clicking outside
function handleClickOutside(event: MouseEvent) {
const target = event.target as HTMLElement;
if ($mobileMenuOpen && !target.closest('nav') && !target.closest('button')) {
mobileMenuOpen.set(false);
}
}
// Close mobile menu on route change
$: if ($page) {
mobileMenuOpen.set(false);
}
// Prevent body scroll when mobile menu is open
$: if (typeof document !== 'undefined') {
if ($mobileMenuOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
}
</script> </script>
<div class="flex h-screen bg-gray-100 dark:bg-gray-900"> <div class="flex h-screen bg-gray-100 dark:bg-gray-900" on:click={handleClickOutside}>
<nav class="flex-none w-72 bg-gray-50 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700"> <!-- Mobile menu overlay -->
{#if $mobileMenuOpen}
<div class="fixed inset-0 bg-gray-600 bg-opacity-75 transition-opacity md:hidden" />
{/if}
<!-- Mobile menu button -->
<div class="fixed top-4 left-4 z-40 md:hidden">
<HamburgerButton />
</div>
<!-- Sidebar -->
<nav class="fixed md:static inset-y-0 left-0 transform {$mobileMenuOpen ? 'translate-x-0' : '-translate-x-full'} md:translate-x-0 w-72 bg-gray-50 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 transition-transform duration-300 ease-in-out z-30">
<Sidebar /> <Sidebar />
</nav> </nav>
<main class="flex-1 overflow-auto bg-white dark:bg-gray-900">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4"> <!-- Main content -->
<main class="flex-1 overflow-auto bg-white dark:bg-gray-900 md:ml-72">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 mt-14 md:mt-0">
<slot /> <slot />
</div> </div>
</main> </main>

View File

@ -4,7 +4,7 @@ import { base } from '$app/paths';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
onMount(() => { onMount(() => {
goto(`${base}/settings`); goto(`${base}/network`);
}); });
</script> </script>

View File

@ -0,0 +1,323 @@
<script lang="ts">
import { onMount, onDestroy } from "svelte";
import { mainSettings } from "$lib/stores";
import type { MainSettings } from "$lib/types";
let s = $state(false);
let wifiNetworks: Record<string, number> = $state({});
let isScanning = $state(false);
let isDestroyed = false;
async function fetchWifiNetworks() {
if (isScanning || isDestroyed) return; // Prevent concurrent scans and post-destroy scans
try {
isScanning = true;
const response = await fetch("/wifi/scan");
const data = await response.json();
if (data.networks) {
wifiNetworks = data.networks;
} else {
console.error("Unexpected response format:", data);
}
} catch (error) {
console.error("Failed to fetch Wi-Fi networks:", error);
} finally {
isScanning = false;
// Schedule next scan after 5 seconds
if (!isDestroyed) {
setTimeout(fetchWifiNetworks, 5000);
}
}
}
function startScanCycle() {
requestAnimationFrame(fetchWifiNetworks);
}
onMount(() => {
startScanCycle();
});
onDestroy(() => {
isDestroyed = true;
});
async function handleSubmit(event: SubmitEvent) {
try {
event.preventDefault();
s = true;
const form = event.target as HTMLFormElement;
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
if (typeof value === "string") {
params.append(key, value);
}
}
await fetch("/wifi/main", { method: "POST", body: params });
try {
await fetch("/restart", { method: "POST", signal: AbortSignal.timeout(1000)});
} catch (error) {
// often the restart request will fail, so we ignore the error
}
// Reload settings after save, with retries
let retries = 5;
let data;
while (retries > 0) {
try {
const response = await fetch("/wifi/main");
data = await response.json();
mainSettings.set(data);
break; // Exit loop on success
} catch (error) {
retries--;
if (retries === 0) {
console.error("Failed to reload settings after multiple retries:", error);
// Optionally display an error message to the user
break;
}
// Wait for 1 second before retrying
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
} finally {
s = false;
}
}
// Make sure your store's data keys match the names below.
const mainSettingsData = $derived($mainSettings as MainSettings);
</script>
<div class="bg-gray-100 dark:bg-gray-800 rounded-lg shadow p-6">
{#if mainSettingsData != null && $mainSettings?.defaults != null && $mainSettings?.values != null}
<form onsubmit={handleSubmit} class="space-y-6">
<!-- Room Configuration -->
<h2 class="text-xl font-semibold">Room Configuration</h2>
<div>
<label class="block text-sm font-medium">Room Name</label>
<input type="text" name="room" bind:value={$mainSettings.values.room} placeholder={$mainSettings.defaults.room} class="mt-1 block w-full rounded-md" />
</div>
<!-- WiFi Configuration -->
<h2 class="text-xl font-semibold">WiFi Configuration</h2>
<div class="mb-2">
<label class="block text-sm font-medium mb-1">WiFi SSID</label>
<input
type="text"
name="wifi-ssid"
bind:value={$mainSettings.values["wifi-ssid"]}
placeholder="Enter WiFi SSID"
class="block w-full rounded-xl border-gray-600 bg-gray-800 dark:text-white px-4 py-3 text-base focus:border-blue-500 focus:ring-blue-500"
/>
</div>
<div>
<div class="bg-gray-50 dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-600">
<div class="px-4 py-3 flex items-center justify-between border-b border-gray-200 dark:border-gray-700">
<label class="text-base font-medium dark:text-white">Available Networks</label>
{#if isScanning}
<div class="ios-spinner"></div>
{/if}
</div>
<ul class="divide-y divide-gray-200 dark:divide-gray-700">
{#each Object.entries(wifiNetworks) as [ssid, rssi]}
<li
onclick={() => {$mainSettings.values["wifi-ssid"] = ssid}}
class="flex items-center cursor-pointer px-4 py-3 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
>
<div class="flex-grow">
<div class="text-base dark:text-white">{ssid}</div>
</div>
<div class="flex items-center space-x-2">
<div class="flex" title={`Signal Strength: ${rssi} dBm`}>
{#each Array(3) as _, i}
<div
class={`w-1.5 h-3 mx-0.5 rounded-sm transform origin-bottom ${
Math.abs(rssi) < (90 - i * 15)
? 'bg-blue-500 dark:bg-blue-400'
: 'bg-gray-300 dark:bg-gray-600'
}`}
style={`transform: scale(1, ${0.6 + i * 0.2})`}
/>
{/each}
</div>
</div>
</li>
{/each}
</ul>
</div>
</div>
<div>
<label class="block text-sm font-medium">WiFi Password</label>
<input type="password" name="wifi-password" bind:value={$mainSettings.values["wifi-password"]} placeholder="Enter WiFi Password" class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium"> Seconds to wait for WiFi before captive portal (-1 = forever) </label>
<input type="number" name="wifi_timeout" bind:value={$mainSettings.values.wifi_timeout} placeholder={String($mainSettings.defaults.wifi_timeout)} step="1" min="-2147483648" max="2147483647" class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium"> Seconds to wait in captive portal before rebooting </label>
<input type="number" name="portal_timeout" bind:value={$mainSettings.values.portal_timeout} placeholder={String($mainSettings.defaults.portal_timeout)} step="1" min="-2147483648" max="2147483647" class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium">Ethernet Type</label>
<select name="eth" bind:value={$mainSettings.values.eth} class="mt-1 block w-full rounded-md">
<option value="0">None</option>
<option value="1">WT32-ETH01</option>
<option value="2">ESP32-POE</option>
<option value="3">WESP32</option>
<option value="4">QuinLED-ESP32</option>
<option value="5">TwilightLord-ESP32</option>
<option value="6">ESP32Deux</option>
<option value="7">KIT-VE</option>
<option value="8">LilyGO-T-ETH-POE</option>
<option value="9">GL-inet GL-S10 v2.1 Ethernet</option>
<option value="10">EST-PoE-32</option>
</select>
</div>
<!-- MQTT Configuration -->
<h2 class="text-xl font-semibold">MQTT Configuration</h2>
<div>
<label class="block text-sm font-medium">Server</label>
<input type="text" name="mqtt_host" bind:value={$mainSettings.values.mqtt_host} placeholder={$mainSettings.defaults.mqtt_host} class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium">Port</label>
<input type="number" name="mqtt_port" bind:value={$mainSettings.values.mqtt_port} placeholder={String($mainSettings.defaults.mqtt_port)} step="1" min="-2147483648" max="2147483647" class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium">Username</label>
<!-- Using a password input as in the legacy page -->
<input type="password" name="mqtt_user" bind:value={$mainSettings.values.mqtt_user} class="mt-1 block w-full rounded-md" />
</div>
<div>
<label class="block text-sm font-medium">Password</label>
<input type="password" name="mqtt_pass" bind:value={$mainSettings.values.mqtt_pass} class="mt-1 block w-full rounded-md" />
</div>
<div class="space-y-4">
<label class="flex items-center space-x-2">
<input type="checkbox" name="discovery" value="1" bind:checked={$mainSettings.values.discovery} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Send to discovery topic</span>
</label>
<div class="ml-6">
<label class="block text-sm font-medium"> Home Assistant discovery topic prefix </label>
<input type="text" name="discovery_prefix" bind:value={$mainSettings.values.discovery_prefix} placeholder={$mainSettings.defaults.discovery_prefix} class="mt-1 block w-full rounded-md" />
</div>
<label class="flex items-center space-x-2">
<input type="checkbox" name="pub_tele" value="1" bind:checked={$mainSettings.values.pub_tele} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Send to telemetry topic</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" name="pub_devices" value="1" bind:checked={$mainSettings.values.pub_devices} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Send to devices topic</span>
</label>
</div>
<!-- Updating -->
<h2 class="text-xl font-semibold">Updating</h2>
<div class="space-y-4">
<label class="flex items-center space-x-2">
<input type="checkbox" name="auto_update" value="1" bind:checked={$mainSettings.values.auto_update} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Automatically update</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" name="prerelease" value="1" bind:checked={$mainSettings.values.prerelease} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Include pre-released versions in auto-update</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" name="arduino_ota" value="1" bind:checked={$mainSettings.values.arduino_ota} class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
<span>Arduino OTA Update</span>
</label>
<div>
<label class="block text-sm font-medium"> Update URL (if set will update from this url on next boot) </label>
<input type="text" name="update" bind:value={$mainSettings.values.update} class="mt-1 block w-full rounded-md" />
</div>
</div>
<div class="flex justify-end">
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg dark:bg-blue-500 dark:hover:bg-blue-600 dark:focus:ring-blue-800">
{s ? "Saving..." : "Save"}
</button>
</div>
</form>
{/if}
</div>
<style>
:global(input:not([type="checkbox"])) {
@apply border-2 border-gray-300 bg-white focus:border-blue-500 focus:ring-blue-500;
}
:global(.dark input:not([type="checkbox"])) {
@apply border-gray-500 bg-gray-900 text-white;
}
:global(select) {
@apply border-2 border-gray-300 bg-white text-gray-900 focus:border-blue-500 focus:ring-blue-500;
}
:global(.dark select) {
@apply border-gray-500 bg-gray-900 text-white;
}
:global(input[type="checkbox"]) {
@apply h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500;
}
:global(.dark input[type="checkbox"]) {
@apply border-gray-600;
}
:global(h2) {
@apply text-gray-900 mb-4;
}
:global(.dark h2) {
@apply text-white;
}
:global(label) {
@apply text-gray-700 mb-1;
}
:global(.dark label) {
@apply text-white;
}
.ios-spinner {
width: 16px;
height: 16px;
border: 2px solid transparent;
border-top-color: #3b82f6;
border-right-color: #3b82f6;
border-bottom-color: #3b82f6;
border-radius: 50%;
animation: spin 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
opacity: 0.8;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
:global(.dark .ios-spinner) {
border-top-color: #60a5fa;
border-right-color: #60a5fa;
border-bottom-color: #60a5fa;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,12 @@ const config = {
adapter: adapter(), adapter: adapter(),
prerender: { prerender: {
crawl: false, crawl: false,
entries: ['/', '/settings', '/devices', '/fingerprints'], entries: ['/', '/settings', '/devices', '/fingerprints', '/network'],
handleHttpError: 'warn', handleHttpError: 'warn',
}, },
appDir: 'app', appDir: 'app',
paths: { paths: {
base: '/ui' base: ''
}, },
version: { version: {
name: '', name: '',

View File

@ -10,7 +10,7 @@ export default defineConfig({
include: '**/*.(js|ts|svelte)', include: '**/*.(js|ts|svelte)',
functions: ['console.*', 'assert.*'], functions: ['console.*', 'assert.*'],
}), }),
cppPlugin({ basePath: '/ui', outPrefix: 'ui_' }) cppPlugin({ basePath: '', outPrefix: 'ui_' })
], ],
build: { build: {
sourcemap: false, sourcemap: false,
@ -22,10 +22,11 @@ export default defineConfig({
}, },
server: { server: {
proxy: { proxy: {
'/json': 'http://192.168.128.165', '/json': 'http://192.168.129.176',
'/extras': 'http://192.168.128.165', '/wifi': 'http://192.168.129.176',
'/restart': 'http://192.168.129.176',
'/ws': { '/ws': {
target: 'ws://192.168.128.165', target: 'ws://192.168.129.176',
ws: true, ws: true,
} }
} }

File diff suppressed because one or more lines are too long