📦 Moves setting to folder

This commit is contained in:
Rune Harlyk
2024-11-08 16:30:50 +01:00
parent 698b7fbba9
commit 9be13d1df5
14 changed files with 355 additions and 363 deletions
@@ -1,6 +1,8 @@
#ifndef CameraSettingsService_h
#define CameraSettingsService_h
#include <settings/camera_settings.h>
namespace Camera {
#include <CameraService.h>
@@ -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<CameraSettings> {
public:
CameraSettingsService(PsychicHttpServer *server, FS *fs)
+6 -18
View File
@@ -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 <Arduino.h>
#include <IPUtils.h>
#include <ArduinoJson.h>
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<String>() || !ip.fromString(root[key].as<String>())) {
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
+1 -44
View File
@@ -9,6 +9,7 @@
#include <Timing.h>
#include <filesystem.h>
#include <Features.h>
#include <settings/peripherals_settings.h>
#include <list>
#include <SPI.h>
@@ -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<PinConfig> 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<PeripheralsConfiguration> {
public:
Peripherals(PsychicHttpServer *server, FS *fs)
+1 -53
View File
@@ -10,63 +10,11 @@
#include <stateful_service_endpoint.h>
#include <MathUtils.h>
#include <Timing.h>
#include <settings/servo_settings.h>
#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<JsonArray>();
for (auto &servo : settings.servos) {
JsonObject newServo = servos.add<JsonObject>();
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>()) {
JsonArray servosJson = root["servos"];
int i = 0;
for (auto servo : servosJson) {
JsonObject servoObject = servo.as<JsonObject>();
uint8_t servoId = i; // servoObject["id"].as<uint8_t>();
settings.servos[servoId].centerPwm = servoObject["center_pwm"].as<float>();
settings.servos[servoId].centerAngle = servoObject["center_angle"].as<float>();
settings.servos[servoId].direction = servoObject["direction"].as<float>();
settings.servos[servoId].conversion = servoObject["conversion"].as<float>();
i++;
}
}
ESP_LOGI("ServoController", "Updating servo data");
return StateUpdateResult::CHANGED;
};
};
class ServoController : public StatefulService<ServoSettings> {
public:
ServoController(PsychicHttpServer *server, FS *fs, Peripherals *peripherals)
+1 -1
View File
@@ -1,7 +1,7 @@
#include <StatefulService.h>
#include <stateful_service_endpoint.h>
#include <FSPersistence.h>
#include <ap_settings.h>
#include <settings/ap_settings.h>
#include <Timing.h>
#include <WiFi.h>
+1 -1
View File
@@ -5,7 +5,7 @@
#include <FSPersistence.h>
#include <WiFi.h>
#include <stateful_service_endpoint.h>
#include <domain/ntp_settings.h>
#include <settings/ntp_settings.h>
#include <lwip/apps/sntp.h>
#include <time.h>
@@ -0,0 +1,109 @@
#pragma once
namespace Camera {
#include <ArduinoJson.h>
#include <state_result.h>
#include <esp_camera.h>
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
@@ -0,0 +1,49 @@
#pragma once
#include <vector>
#include <ArduinoJson.h>
#include <state_result.h>
/*
* 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<PinConfig> 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;
};
};
@@ -0,0 +1,49 @@
#pragma once
#include <ArduinoJson.h>
#include <state_result.h>
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<JsonArray>();
for (auto &servo : settings.servos) {
JsonObject newServo = servos.add<JsonObject>();
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>()) {
JsonArray servosJson = root["servos"];
int i = 0;
for (auto servo : servosJson) {
JsonObject servoObject = servo.as<JsonObject>();
uint8_t servoId = i; // servoObject["id"].as<uint8_t>();
settings.servos[servoId].centerPwm = servoObject["center_pwm"].as<float>();
settings.servos[servoId].centerAngle = servoObject["center_angle"].as<float>();
settings.servos[servoId].direction = servoObject["direction"].as<float>();
settings.servos[servoId].conversion = servoObject["conversion"].as<float>();
i++;
}
}
ESP_LOGI("ServoController", "Updating servo data");
return StateUpdateResult::CHANGED;
};
};
@@ -0,0 +1,135 @@
#pragma once
#include <WiFi.h>
#include <IPAddress.h>
#include <ArduinoJson.h>
#include <JsonUtils.h>
#include <IPUtils.h>
#include <string_utilities.h>
#include <state_result.h>
#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>();
String newPassword = json["password"].as<String>();
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<wifi_settings_t> wifiSettings;
static void read(WiFiSettings &settings, JsonObject &root) {
root["hostname"] = settings.hostname;
root["priority_RSSI"] = settings.priorityBySignalStrength;
JsonArray wifiNetworks = root["wifi_networks"].to<JsonArray>();
for (const auto &wifi : settings.wifiSettings) {
JsonObject wifiNetwork = wifiNetworks.add<JsonObject>();
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>()) {
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;
}
};
+1 -1
View File
@@ -10,7 +10,7 @@
#include <StatefulService.h>
#include <FSPersistence.h>
#include <stateful_service_endpoint.h>
#include <wifi_settings.h>
#include <settings/wifi_settings.h>
class WiFiService : public StatefulService<WiFiSettings> {
private:
-144
View File
@@ -1,144 +0,0 @@
#pragma once
#include <WiFi.h>
#include <IPAddress.h>
#include <ArduinoJson.h>
#include <JsonUtils.h>
#include <IPUtils.h>
#include <string_utilities.h>
#include <state_result.h>
#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<wifi_settings_t> 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<JsonArray>();
// iterate over the wifiSettings
for (auto &wifi : settings.wifiSettings) {
// create JSON object for each wifi network
JsonObject wifiNetwork = wifiNetworks.add<JsonObject>();
// 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<JsonArray>()) {
// 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<JsonObject>();
// Check if SSID length is between 1 and 31 characters and password between 0 and 64 characters
if (wifi["ssid"].as<String>().length() < 1 || wifi["ssid"].as<String>().length() > 31 ||
wifi["password"].as<String>().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<String>();
wifiSettings.password = wifi["password"].as<String>();
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;
};
};