From 9be13d1df56baa7162882dff8d854b58e2918b2f Mon Sep 17 00:00:00 2001 From: Rune Harlyk Date: Fri, 8 Nov 2024 16:30:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A6=20Moves=20setting=20to=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ESP32-sveltekit/CameraSettingsService.h | 103 +------------ esp32/lib/ESP32-sveltekit/JsonUtils.h | 24 +-- esp32/lib/ESP32-sveltekit/Peripherals.h | 45 +----- esp32/lib/ESP32-sveltekit/ServoController.h | 54 +------ esp32/lib/ESP32-sveltekit/ap_service.h | 2 +- esp32/lib/ESP32-sveltekit/ntp_service.h | 2 +- .../{ => settings}/ap_settings.h | 0 .../settings/camera_settings.h | 109 +++++++++++++ .../{domain => settings}/ntp_settings.h | 0 .../settings/peripherals_settings.h | 49 ++++++ .../ESP32-sveltekit/settings/servo_settings.h | 49 ++++++ .../ESP32-sveltekit/settings/wifi_settings.h | 135 ++++++++++++++++ esp32/lib/ESP32-sveltekit/wifi_service.h | 2 +- esp32/lib/ESP32-sveltekit/wifi_settings.h | 144 ------------------ 14 files changed, 355 insertions(+), 363 deletions(-) rename esp32/lib/ESP32-sveltekit/{ => settings}/ap_settings.h (100%) create mode 100644 esp32/lib/ESP32-sveltekit/settings/camera_settings.h rename esp32/lib/ESP32-sveltekit/{domain => settings}/ntp_settings.h (100%) create mode 100644 esp32/lib/ESP32-sveltekit/settings/peripherals_settings.h create mode 100644 esp32/lib/ESP32-sveltekit/settings/servo_settings.h create mode 100644 esp32/lib/ESP32-sveltekit/settings/wifi_settings.h delete mode 100644 esp32/lib/ESP32-sveltekit/wifi_settings.h diff --git a/esp32/lib/ESP32-sveltekit/CameraSettingsService.h b/esp32/lib/ESP32-sveltekit/CameraSettingsService.h index af9a982..ca9a0ac 100644 --- a/esp32/lib/ESP32-sveltekit/CameraSettingsService.h +++ b/esp32/lib/ESP32-sveltekit/CameraSettingsService.h @@ -1,6 +1,8 @@ #ifndef CameraSettingsService_h #define CameraSettingsService_h +#include + namespace Camera { #include @@ -17,107 +19,6 @@ namespace Camera { #define EVENT_CAMERA_SETTINGS "CameraSettings" #define CAMERA_SETTINGS_PATH "/api/camera/settings" -class CameraSettings { - public: - pixformat_t pixformat; - framesize_t framesize; // 0 - 10 - uint8_t quality; // 0 - 63 - int8_t brightness; //-2 - 2 - int8_t contrast; //-2 - 2 - int8_t saturation; //-2 - 2 - int8_t sharpness; //-2 - 2 - uint8_t denoise; - gainceiling_t gainceiling; - uint8_t whitebal; - uint8_t special_effect; // 0 - 6 - uint8_t wb_mode; // 0 - 4 - uint8_t awb; - uint8_t exposure_ctrl; - uint8_t awb_gain; - uint8_t gain_ctrl; - uint8_t aec; - uint8_t aec2; - int8_t ae_level; //-2 - 2 - uint16_t aec_value; // 0 - 1200 - uint8_t agc; - uint8_t agc_gain; // 0 - 30 - uint8_t bpc; - uint8_t wpc; - uint8_t raw_gma; - uint8_t lenc; - uint8_t hmirror; - uint8_t vflip; - uint8_t dcw; - uint8_t colorbar; - - static void read(CameraSettings &settings, JsonObject &root) { - root["pixformat"] = settings.pixformat; - root["framesize"] = settings.framesize; - root["quality"] = settings.quality; - root["brightness"] = settings.brightness; - root["contrast"] = settings.contrast; - root["saturation"] = settings.saturation; - root["sharpness"] = settings.sharpness; - root["denoise"] = settings.denoise; - root["special_effect"] = settings.special_effect; - root["wb_mode"] = settings.wb_mode; - root["exposure_ctrl"] = settings.exposure_ctrl; - root["gain_ctrl"] = settings.gain_ctrl; - root["awb"] = settings.awb; - root["awb_gain"] = settings.awb_gain; - root["aec"] = settings.aec; - root["aec2"] = settings.aec2; - root["ae_level"] = settings.ae_level; - root["aec_value"] = settings.aec_value; - root["agc"] = settings.agc; - root["agc_gain"] = settings.agc_gain; - root["gainceiling"] = settings.gainceiling; - root["bpc"] = settings.bpc; - root["wpc"] = settings.wpc; - root["raw_gma"] = settings.raw_gma; - root["lenc"] = settings.lenc; - root["hmirror"] = settings.hmirror; - root["vflip"] = settings.vflip; - root["dcw"] = settings.dcw; - root["colorbar"] = settings.colorbar; - } - - static StateUpdateResult update(JsonObject &root, CameraSettings &settings) { - settings.pixformat = root["pixformat"]; - settings.framesize = root["framesize"]; - settings.brightness = root["brightness"]; - settings.contrast = root["contrast"]; - settings.quality = root["quality"]; - settings.contrast = root["contrast"]; - settings.saturation = root["saturation"]; - settings.sharpness = root["sharpness"]; - settings.denoise = root["denoise"]; - settings.exposure_ctrl = root["exposure_ctrl"]; - settings.gain_ctrl = root["gain_ctrl"]; - settings.special_effect = root["special_effect"]; - settings.wb_mode = root["wb_mode"]; - settings.awb = root["awb"]; - settings.awb_gain = root["awb_gain"]; - settings.aec = root["aec"]; - settings.aec2 = root["aec2"]; - settings.ae_level = root["ae_level"]; - settings.aec_value = root["aec_value"]; - settings.agc = root["agc"]; - settings.agc_gain = root["agc_gain"]; - settings.gainceiling = root["gainceiling"]; - settings.bpc = root["bpc"]; - settings.wpc = root["wpc"]; - settings.raw_gma = root["raw_gma"]; - settings.lenc = root["lenc"]; - settings.hmirror = root["hmirror"]; - settings.vflip = root["vflip"]; - settings.dcw = root["dcw"]; - settings.colorbar = root["colorbar"]; - - return StateUpdateResult::CHANGED; - }; -}; - class CameraSettingsService : public StatefulService { public: CameraSettingsService(PsychicHttpServer *server, FS *fs) diff --git a/esp32/lib/ESP32-sveltekit/JsonUtils.h b/esp32/lib/ESP32-sveltekit/JsonUtils.h index 6aa6c85..b26d847 100644 --- a/esp32/lib/ESP32-sveltekit/JsonUtils.h +++ b/esp32/lib/ESP32-sveltekit/JsonUtils.h @@ -1,43 +1,31 @@ #ifndef JsonUtils_h #define JsonUtils_h -/** - * ESP32 SvelteKit - * - * A simple, secure and extensible framework for IoT projects for ESP32 platforms - * with responsive Sveltekit front-end built with TailwindCSS and DaisyUI. - * https://github.com/theelims/ESP32-sveltekit - * - * Copyright (C) 2018 - 2023 rjwats - * Copyright (C) 2023 theelims - * - * All Rights Reserved. This software may be modified and distributed under - * the terms of the LGPL v3 license. See the LICENSE file for details. - **/ - #include #include #include class JsonUtils { public: - static void readIP(JsonObject &root, const String &key, IPAddress &ip, const String &def) { + static void readIP(const JsonObject &root, const String &key, IPAddress &ip, const String &def) { IPAddress defaultIp = {}; if (!defaultIp.fromString(def)) { defaultIp = INADDR_NONE; } readIP(root, key, ip, defaultIp); } - static void readIP(JsonObject &root, const String &key, IPAddress &ip, const IPAddress &defaultIp = INADDR_NONE) { + + static void readIP(const JsonObject &root, const String &key, IPAddress &ip, + const IPAddress &defaultIp = INADDR_NONE) { if (!root[key].is() || !ip.fromString(root[key].as())) { ip = defaultIp; } } + static void writeIP(JsonObject &root, const String &key, const IPAddress &ip) { if (IPUtils::isSet(ip)) { root[key] = ip.toString(); } } }; - -#endif // end JsonUtils +#endif // end JsonUtils \ No newline at end of file diff --git a/esp32/lib/ESP32-sveltekit/Peripherals.h b/esp32/lib/ESP32-sveltekit/Peripherals.h index 1c9c6c9..550b698 100644 --- a/esp32/lib/ESP32-sveltekit/Peripherals.h +++ b/esp32/lib/ESP32-sveltekit/Peripherals.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -55,50 +56,6 @@ */ #define MAX_DISTANCE 200 -/* - * I2C software connection - */ -#ifndef SDA_PIN -#define SDA_PIN SDA -#endif -#ifndef SCL_PIN -#define SCL_PIN SCL -#endif -#ifndef I2C_FREQUENCY -#define I2C_FREQUENCY 100000UL -#endif - -class PinConfig { - public: - int pin; - String mode; - String type; - String role; - - PinConfig(int p, String m, String t, String r) : pin(p), mode(m), type(t), role(r) {} -}; - -class PeripheralsConfiguration { - public: - int sda = SDA_PIN; - int scl = SCL_PIN; - long frequency = I2C_FREQUENCY; - std::vector pins; - - static void read(PeripheralsConfiguration &settings, JsonObject &root) { - root["sda"] = settings.sda; - root["scl"] = settings.scl; - root["frequency"] = settings.frequency; - } - - static StateUpdateResult update(JsonObject &root, PeripheralsConfiguration &settings) { - settings.sda = root["sda"] | SDA_PIN; - settings.scl = root["scl"] | SCL_PIN; - settings.frequency = root["frequency"] | I2C_FREQUENCY; - return StateUpdateResult::CHANGED; - }; -}; - class Peripherals : public StatefulService { public: Peripherals(PsychicHttpServer *server, FS *fs) diff --git a/esp32/lib/ESP32-sveltekit/ServoController.h b/esp32/lib/ESP32-sveltekit/ServoController.h index 7a56810..419c200 100644 --- a/esp32/lib/ESP32-sveltekit/ServoController.h +++ b/esp32/lib/ESP32-sveltekit/ServoController.h @@ -10,63 +10,11 @@ #include #include #include +#include #define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM" #define EVENT_SERVO_STATE "servoState" -typedef struct { - float centerPwm; - float direction; - float centerAngle; - float conversion; - const char *name; - // bool enable; -} servo_settings_t; - -class ServoSettings { - public: - servo_settings_t servos[12] = { - {306, -1, 0, 2.2, "Servo1"}, {306, 1, -45, 2.1055555, "Servo2"}, {306, 1, 90, 1.96923, "Servo3"}, - {306, -1, 0, 2.2, "Servo4"}, {306, -1, 45, 2.1055555, "Servo5"}, {306, -1, -90, 1.96923, "Servo6"}, - {306, 1, 0, 2.2, "Servo7"}, {306, 1, -45, 2.1055555, "Servo8"}, {306, 1, 90, 1.96923, "Servo9"}, - {306, 1, 0, 2.2, "Servo10"}, {306, -1, 45, 2.1055555, "Servo11"}, {306, -1, -90, 1.96923, "Servo12"}}; - - static void read(ServoSettings &settings, JsonObject &root) { - JsonArray servos = root["servos"].to(); - - for (auto &servo : settings.servos) { - JsonObject newServo = servos.add(); - - newServo["center_pwm"] = servo.centerPwm; - newServo["direction"] = servo.direction; - newServo["center_angle"] = servo.centerAngle; - newServo["conversion"] = servo.conversion; - } - } - - static StateUpdateResult update(JsonObject &root, ServoSettings &settings) { - if (root["servos"].is()) { - JsonArray servosJson = root["servos"]; - int i = 0; - for (auto servo : servosJson) { - JsonObject servoObject = servo.as(); - - uint8_t servoId = i; // servoObject["id"].as(); - - settings.servos[servoId].centerPwm = servoObject["center_pwm"].as(); - settings.servos[servoId].centerAngle = servoObject["center_angle"].as(); - settings.servos[servoId].direction = servoObject["direction"].as(); - settings.servos[servoId].conversion = servoObject["conversion"].as(); - - i++; - } - } - ESP_LOGI("ServoController", "Updating servo data"); - - return StateUpdateResult::CHANGED; - }; -}; - class ServoController : public StatefulService { public: ServoController(PsychicHttpServer *server, FS *fs, Peripherals *peripherals) diff --git a/esp32/lib/ESP32-sveltekit/ap_service.h b/esp32/lib/ESP32-sveltekit/ap_service.h index 2b2ce62..c204226 100644 --- a/esp32/lib/ESP32-sveltekit/ap_service.h +++ b/esp32/lib/ESP32-sveltekit/ap_service.h @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include diff --git a/esp32/lib/ESP32-sveltekit/ntp_service.h b/esp32/lib/ESP32-sveltekit/ntp_service.h index c030782..30780f6 100644 --- a/esp32/lib/ESP32-sveltekit/ntp_service.h +++ b/esp32/lib/ESP32-sveltekit/ntp_service.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include diff --git a/esp32/lib/ESP32-sveltekit/ap_settings.h b/esp32/lib/ESP32-sveltekit/settings/ap_settings.h similarity index 100% rename from esp32/lib/ESP32-sveltekit/ap_settings.h rename to esp32/lib/ESP32-sveltekit/settings/ap_settings.h diff --git a/esp32/lib/ESP32-sveltekit/settings/camera_settings.h b/esp32/lib/ESP32-sveltekit/settings/camera_settings.h new file mode 100644 index 0000000..da01e15 --- /dev/null +++ b/esp32/lib/ESP32-sveltekit/settings/camera_settings.h @@ -0,0 +1,109 @@ +#pragma once + +namespace Camera { + +#include +#include +#include + +class CameraSettings { + public: + pixformat_t pixformat; + framesize_t framesize; // 0 - 10 + uint8_t quality; // 0 - 63 + int8_t brightness; //-2 - 2 + int8_t contrast; //-2 - 2 + int8_t saturation; //-2 - 2 + int8_t sharpness; //-2 - 2 + uint8_t denoise; + gainceiling_t gainceiling; + uint8_t whitebal; + uint8_t special_effect; // 0 - 6 + uint8_t wb_mode; // 0 - 4 + uint8_t awb; + uint8_t exposure_ctrl; + uint8_t awb_gain; + uint8_t gain_ctrl; + uint8_t aec; + uint8_t aec2; + int8_t ae_level; //-2 - 2 + uint16_t aec_value; // 0 - 1200 + uint8_t agc; + uint8_t agc_gain; // 0 - 30 + uint8_t bpc; + uint8_t wpc; + uint8_t raw_gma; + uint8_t lenc; + uint8_t hmirror; + uint8_t vflip; + uint8_t dcw; + uint8_t colorbar; + + static void read(CameraSettings &settings, JsonObject &root) { + root["pixformat"] = settings.pixformat; + root["framesize"] = settings.framesize; + root["quality"] = settings.quality; + root["brightness"] = settings.brightness; + root["contrast"] = settings.contrast; + root["saturation"] = settings.saturation; + root["sharpness"] = settings.sharpness; + root["denoise"] = settings.denoise; + root["special_effect"] = settings.special_effect; + root["wb_mode"] = settings.wb_mode; + root["exposure_ctrl"] = settings.exposure_ctrl; + root["gain_ctrl"] = settings.gain_ctrl; + root["awb"] = settings.awb; + root["awb_gain"] = settings.awb_gain; + root["aec"] = settings.aec; + root["aec2"] = settings.aec2; + root["ae_level"] = settings.ae_level; + root["aec_value"] = settings.aec_value; + root["agc"] = settings.agc; + root["agc_gain"] = settings.agc_gain; + root["gainceiling"] = settings.gainceiling; + root["bpc"] = settings.bpc; + root["wpc"] = settings.wpc; + root["raw_gma"] = settings.raw_gma; + root["lenc"] = settings.lenc; + root["hmirror"] = settings.hmirror; + root["vflip"] = settings.vflip; + root["dcw"] = settings.dcw; + root["colorbar"] = settings.colorbar; + } + + static StateUpdateResult update(JsonObject &root, CameraSettings &settings) { + settings.pixformat = root["pixformat"]; + settings.framesize = root["framesize"]; + settings.brightness = root["brightness"]; + settings.contrast = root["contrast"]; + settings.quality = root["quality"]; + settings.contrast = root["contrast"]; + settings.saturation = root["saturation"]; + settings.sharpness = root["sharpness"]; + settings.denoise = root["denoise"]; + settings.exposure_ctrl = root["exposure_ctrl"]; + settings.gain_ctrl = root["gain_ctrl"]; + settings.special_effect = root["special_effect"]; + settings.wb_mode = root["wb_mode"]; + settings.awb = root["awb"]; + settings.awb_gain = root["awb_gain"]; + settings.aec = root["aec"]; + settings.aec2 = root["aec2"]; + settings.ae_level = root["ae_level"]; + settings.aec_value = root["aec_value"]; + settings.agc = root["agc"]; + settings.agc_gain = root["agc_gain"]; + settings.gainceiling = root["gainceiling"]; + settings.bpc = root["bpc"]; + settings.wpc = root["wpc"]; + settings.raw_gma = root["raw_gma"]; + settings.lenc = root["lenc"]; + settings.hmirror = root["hmirror"]; + settings.vflip = root["vflip"]; + settings.dcw = root["dcw"]; + settings.colorbar = root["colorbar"]; + + return StateUpdateResult::CHANGED; + }; +}; +} // namespace Camera \ No newline at end of file diff --git a/esp32/lib/ESP32-sveltekit/domain/ntp_settings.h b/esp32/lib/ESP32-sveltekit/settings/ntp_settings.h similarity index 100% rename from esp32/lib/ESP32-sveltekit/domain/ntp_settings.h rename to esp32/lib/ESP32-sveltekit/settings/ntp_settings.h diff --git a/esp32/lib/ESP32-sveltekit/settings/peripherals_settings.h b/esp32/lib/ESP32-sveltekit/settings/peripherals_settings.h new file mode 100644 index 0000000..6d12715 --- /dev/null +++ b/esp32/lib/ESP32-sveltekit/settings/peripherals_settings.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +/* + * I2C software connection + */ +#ifndef SDA_PIN +#define SDA_PIN SDA +#endif +#ifndef SCL_PIN +#define SCL_PIN SCL +#endif +#ifndef I2C_FREQUENCY +#define I2C_FREQUENCY 100000UL +#endif + +class PinConfig { + public: + int pin; + String mode; + String type; + String role; + + PinConfig(int p, String m, String t, String r) : pin(p), mode(m), type(t), role(r) {} +}; + +class PeripheralsConfiguration { + public: + int sda = SDA_PIN; + int scl = SCL_PIN; + long frequency = I2C_FREQUENCY; + std::vector pins; + + static void read(PeripheralsConfiguration &settings, JsonObject &root) { + root["sda"] = settings.sda; + root["scl"] = settings.scl; + root["frequency"] = settings.frequency; + } + + static StateUpdateResult update(JsonObject &root, PeripheralsConfiguration &settings) { + settings.sda = root["sda"] | SDA_PIN; + settings.scl = root["scl"] | SCL_PIN; + settings.frequency = root["frequency"] | I2C_FREQUENCY; + return StateUpdateResult::CHANGED; + }; +}; \ No newline at end of file diff --git a/esp32/lib/ESP32-sveltekit/settings/servo_settings.h b/esp32/lib/ESP32-sveltekit/settings/servo_settings.h new file mode 100644 index 0000000..fb9dd7c --- /dev/null +++ b/esp32/lib/ESP32-sveltekit/settings/servo_settings.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +typedef struct { + float centerPwm; + float direction; + float centerAngle; + float conversion; + const char *name; + // bool enable; +} servo_settings_t; + +class ServoSettings { + public: + servo_settings_t servos[12] = { + {306, -1, 0, 2.2, "Servo1"}, {306, 1, -45, 2.1055555, "Servo2"}, {306, 1, 90, 1.96923, "Servo3"}, + {306, -1, 0, 2.2, "Servo4"}, {306, -1, 45, 2.1055555, "Servo5"}, {306, -1, -90, 1.96923, "Servo6"}, + {306, 1, 0, 2.2, "Servo7"}, {306, 1, -45, 2.1055555, "Servo8"}, {306, 1, 90, 1.96923, "Servo9"}, + {306, 1, 0, 2.2, "Servo10"}, {306, -1, 45, 2.1055555, "Servo11"}, {306, -1, -90, 1.96923, "Servo12"}}; + static void read(ServoSettings &settings, JsonObject &root) { + JsonArray servos = root["servos"].to(); + for (auto &servo : settings.servos) { + JsonObject newServo = servos.add(); + newServo["center_pwm"] = servo.centerPwm; + newServo["direction"] = servo.direction; + newServo["center_angle"] = servo.centerAngle; + newServo["conversion"] = servo.conversion; + } + } + static StateUpdateResult update(JsonObject &root, ServoSettings &settings) { + if (root["servos"].is()) { + JsonArray servosJson = root["servos"]; + int i = 0; + for (auto servo : servosJson) { + JsonObject servoObject = servo.as(); + uint8_t servoId = i; // servoObject["id"].as(); + settings.servos[servoId].centerPwm = servoObject["center_pwm"].as(); + settings.servos[servoId].centerAngle = servoObject["center_angle"].as(); + settings.servos[servoId].direction = servoObject["direction"].as(); + settings.servos[servoId].conversion = servoObject["conversion"].as(); + i++; + } + } + ESP_LOGI("ServoController", "Updating servo data"); + return StateUpdateResult::CHANGED; + }; +}; \ No newline at end of file diff --git a/esp32/lib/ESP32-sveltekit/settings/wifi_settings.h b/esp32/lib/ESP32-sveltekit/settings/wifi_settings.h new file mode 100644 index 0000000..2ea3661 --- /dev/null +++ b/esp32/lib/ESP32-sveltekit/settings/wifi_settings.h @@ -0,0 +1,135 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FACTORY_WIFI_SSID +#define FACTORY_WIFI_SSID "" +#endif + +#ifndef FACTORY_WIFI_PASSWORD +#define FACTORY_WIFI_PASSWORD "" +#endif + +#ifndef FACTORY_WIFI_HOSTNAME +#define FACTORY_WIFI_HOSTNAME "#{platform}-#{unique_id}" +#endif + +#ifndef FACTORY_WIFI_RSSI_THRESHOLD +#define FACTORY_WIFI_RSSI_THRESHOLD -80 +#endif + +typedef struct { + String ssid; + uint8_t bssid[6]; + int32_t channel; + String password; + bool staticIPConfig; + IPAddress localIP; + IPAddress gatewayIP; + IPAddress subnetMask; + IPAddress dnsIP1; + IPAddress dnsIP2; + bool available; + + void serialize(JsonObject &json) const { + json["ssid"] = ssid; + json["password"] = password; + json["static_ip_config"] = staticIPConfig; + if (staticIPConfig) { + JsonUtils::writeIP(json, "local_ip", localIP); + JsonUtils::writeIP(json, "gateway_ip", gatewayIP); + JsonUtils::writeIP(json, "subnet_mask", subnetMask); + JsonUtils::writeIP(json, "dns_ip_1", dnsIP1); + JsonUtils::writeIP(json, "dns_ip_2", dnsIP2); + } + } + + bool deserialize(const JsonObject &json) { + String newSsid = json["ssid"].as(); + String newPassword = json["password"].as(); + if (newSsid.length() < 1 || newSsid.length() > 31 || newPassword.length() > 64) { + ESP_LOGE("WiFiSettings", "SSID or password length is invalid"); + return false; + } + ssid = newSsid; + password = newPassword; + staticIPConfig = json["static_ip_config"] | false; + if (staticIPConfig) { + JsonUtils::readIP(json, "local_ip", localIP); + JsonUtils::readIP(json, "gateway_ip", gatewayIP); + JsonUtils::readIP(json, "subnet_mask", subnetMask); + JsonUtils::readIP(json, "dns_ip_1", dnsIP1); + JsonUtils::readIP(json, "dns_ip_2", dnsIP2); + if (IPUtils::isNotSet(dnsIP1) && IPUtils::isSet(dnsIP2)) { + dnsIP1 = dnsIP2; + dnsIP2 = INADDR_NONE; + } + if (IPUtils::isNotSet(localIP) || IPUtils::isNotSet(gatewayIP) || IPUtils::isNotSet(subnetMask)) { + staticIPConfig = false; + ESP_LOGW("WiFiSettings", "Invalid static IP configuration - falling back to DHCP"); + } + } + available = false; + return true; + } + +} wifi_settings_t; + +inline wifi_settings_t createDefaultWiFiSettings() { + return wifi_settings_t {.ssid = FACTORY_WIFI_SSID, + .password = FACTORY_WIFI_PASSWORD, + .staticIPConfig = false, + .localIP = INADDR_NONE, + .gatewayIP = INADDR_NONE, + .subnetMask = INADDR_NONE, + .dnsIP1 = INADDR_NONE, + .dnsIP2 = INADDR_NONE, + .available = false}; +} + +class WiFiSettings { + public: + String hostname; + bool priorityBySignalStrength; + std::vector wifiSettings; + static void read(WiFiSettings &settings, JsonObject &root) { + root["hostname"] = settings.hostname; + root["priority_RSSI"] = settings.priorityBySignalStrength; + JsonArray wifiNetworks = root["wifi_networks"].to(); + for (const auto &wifi : settings.wifiSettings) { + JsonObject wifiNetwork = wifiNetworks.add(); + wifi.serialize(wifiNetwork); + } + ESP_LOGV("WiFiSettings", "WiFi Settings read"); + } + static StateUpdateResult update(JsonObject &root, WiFiSettings &settings) { + settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME; + settings.priorityBySignalStrength = root["priority_RSSI"] | true; + settings.wifiSettings.clear(); + if (root["wifi_networks"].is()) { + JsonArray wifiNetworks = root["wifi_networks"]; + int networkCount = 0; + for (JsonObject wifiNetwork : wifiNetworks) { + if (networkCount >= 5) { + ESP_LOGE("WiFiSettings", "Too many wifi networks"); + break; + } + wifi_settings_t newSettings; + if (newSettings.deserialize(wifiNetwork)) { + settings.wifiSettings.push_back(newSettings); + networkCount++; + } + } + } else if (String(FACTORY_WIFI_SSID).length() > 0) { + settings.wifiSettings.push_back(createDefaultWiFiSettings()); + } + ESP_LOGV("WiFiSettings", "WiFi Settings updated"); + return StateUpdateResult::CHANGED; + } +}; \ No newline at end of file diff --git a/esp32/lib/ESP32-sveltekit/wifi_service.h b/esp32/lib/ESP32-sveltekit/wifi_service.h index 4f33f8d..c79e324 100644 --- a/esp32/lib/ESP32-sveltekit/wifi_service.h +++ b/esp32/lib/ESP32-sveltekit/wifi_service.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include class WiFiService : public StatefulService { private: diff --git a/esp32/lib/ESP32-sveltekit/wifi_settings.h b/esp32/lib/ESP32-sveltekit/wifi_settings.h deleted file mode 100644 index 4e141a7..0000000 --- a/esp32/lib/ESP32-sveltekit/wifi_settings.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#ifndef FACTORY_WIFI_RSSI_THRESHOLD -#define FACTORY_WIFI_RSSI_THRESHOLD -80 -#endif - -typedef struct { - String ssid; - String password; - bool staticIPConfig; - IPAddress localIP; - IPAddress gatewayIP; - IPAddress subnetMask; - IPAddress dnsIP1; - IPAddress dnsIP2; - bool available; -} wifi_settings_t; - -class WiFiSettings { - public: - String hostname; - bool priorityBySignalStrength; - std::vector wifiSettings; - - static void read(WiFiSettings &settings, JsonObject &root) { - root["hostname"] = settings.hostname; - root["priority_RSSI"] = settings.priorityBySignalStrength; - - // create JSON array from root - JsonArray wifiNetworks = root["wifi_networks"].to(); - - // iterate over the wifiSettings - for (auto &wifi : settings.wifiSettings) { - // create JSON object for each wifi network - JsonObject wifiNetwork = wifiNetworks.add(); - - // add the ssid and password to the JSON object - wifiNetwork["ssid"] = wifi.ssid; - wifiNetwork["password"] = wifi.password; - wifiNetwork["static_ip_config"] = wifi.staticIPConfig; - - // extended settings - JsonUtils::writeIP(root, "local_ip", wifi.localIP); - JsonUtils::writeIP(root, "gateway_ip", wifi.gatewayIP); - JsonUtils::writeIP(root, "subnet_mask", wifi.subnetMask); - JsonUtils::writeIP(root, "dns_ip_1", wifi.dnsIP1); - JsonUtils::writeIP(root, "dns_ip_2", wifi.dnsIP2); - } - - ESP_LOGV("WiFiSettings", "WiFi Settings read"); - } - - static StateUpdateResult update(JsonObject &root, WiFiSettings &settings) { - settings.hostname = root["hostname"] | format(FACTORY_WIFI_HOSTNAME); - settings.priorityBySignalStrength = root["priority_RSSI"] | true; - - settings.wifiSettings.clear(); - - // create JSON array from root - JsonArray wifiNetworks = root["wifi_networks"]; - if (root["wifi_networks"].is()) { - // iterate over the wifiSettings - int i = 0; - for (auto wifiNetwork : wifiNetworks) { - // max 5 wifi networks - if (i++ >= 5) { - ESP_LOGE("WiFiSettings", "Too many wifi networks"); - break; - } - - // create JSON object for each wifi network - JsonObject wifi = wifiNetwork.as(); - - // Check if SSID length is between 1 and 31 characters and password between 0 and 64 characters - if (wifi["ssid"].as().length() < 1 || wifi["ssid"].as().length() > 31 || - wifi["password"].as().length() > 64) { - ESP_LOGE("WiFiSettings", "SSID or password length is invalid"); - } else { - // add the ssid and password to the JSON object - wifi_settings_t wifiSettings; - - wifiSettings.ssid = wifi["ssid"].as(); - wifiSettings.password = wifi["password"].as(); - wifiSettings.staticIPConfig = wifi["static_ip_config"]; - - // extended settings - JsonUtils::readIP(wifi, "local_ip", wifiSettings.localIP); - JsonUtils::readIP(wifi, "gateway_ip", wifiSettings.gatewayIP); - JsonUtils::readIP(wifi, "subnet_mask", wifiSettings.subnetMask); - JsonUtils::readIP(wifi, "dns_ip_1", wifiSettings.dnsIP1); - JsonUtils::readIP(wifi, "dns_ip_2", wifiSettings.dnsIP2); - - // Swap around the dns servers if 2 is populated but 1 is not - if (IPUtils::isNotSet(wifiSettings.dnsIP1) && IPUtils::isSet(wifiSettings.dnsIP2)) { - wifiSettings.dnsIP1 = wifiSettings.dnsIP2; - wifiSettings.dnsIP2 = INADDR_NONE; - } - - // Turning off static ip config if we don't meet the minimum requirements - // of ipAddress, gateway and subnet. This may change to static ip only - // as sensible defaults can be assumed for gateway and subnet - if (wifiSettings.staticIPConfig && - (IPUtils::isNotSet(wifiSettings.localIP) || IPUtils::isNotSet(wifiSettings.gatewayIP) || - IPUtils::isNotSet(wifiSettings.subnetMask))) { - wifiSettings.staticIPConfig = false; - } - - // reset scan result - wifiSettings.available = false; - settings.wifiSettings.push_back(wifiSettings); - - // increment the wifi network index - i++; - } - } - } else { - // populate with factory defaults if they are present - if (String(FACTORY_WIFI_SSID).length() > 0) { - settings.wifiSettings.push_back(wifi_settings_t { - .ssid = FACTORY_WIFI_SSID, - .password = FACTORY_WIFI_PASSWORD, - .staticIPConfig = false, - .localIP = INADDR_NONE, - .gatewayIP = INADDR_NONE, - .subnetMask = INADDR_NONE, - .dnsIP1 = INADDR_NONE, - .dnsIP2 = INADDR_NONE, - .available = false, - }); - } - } - ESP_LOGV("WiFiSettings", "WiFi Settings updated"); - - return StateUpdateResult::CHANGED; - }; -}; \ No newline at end of file