📦 Moves setting to folder
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
#ifndef CameraSettingsService_h
|
#ifndef CameraSettingsService_h
|
||||||
#define CameraSettingsService_h
|
#define CameraSettingsService_h
|
||||||
|
|
||||||
|
#include <settings/camera_settings.h>
|
||||||
|
|
||||||
namespace Camera {
|
namespace Camera {
|
||||||
|
|
||||||
#include <CameraService.h>
|
#include <CameraService.h>
|
||||||
@@ -17,107 +19,6 @@ namespace Camera {
|
|||||||
#define EVENT_CAMERA_SETTINGS "CameraSettings"
|
#define EVENT_CAMERA_SETTINGS "CameraSettings"
|
||||||
#define CAMERA_SETTINGS_PATH "/api/camera/settings"
|
#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> {
|
class CameraSettingsService : public StatefulService<CameraSettings> {
|
||||||
public:
|
public:
|
||||||
CameraSettingsService(PsychicHttpServer *server, FS *fs)
|
CameraSettingsService(PsychicHttpServer *server, FS *fs)
|
||||||
|
|||||||
@@ -1,43 +1,31 @@
|
|||||||
#ifndef JsonUtils_h
|
#ifndef JsonUtils_h
|
||||||
#define 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 <Arduino.h>
|
||||||
#include <IPUtils.h>
|
#include <IPUtils.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
class JsonUtils {
|
class JsonUtils {
|
||||||
public:
|
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 = {};
|
IPAddress defaultIp = {};
|
||||||
if (!defaultIp.fromString(def)) {
|
if (!defaultIp.fromString(def)) {
|
||||||
defaultIp = INADDR_NONE;
|
defaultIp = INADDR_NONE;
|
||||||
}
|
}
|
||||||
readIP(root, key, ip, defaultIp);
|
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>())) {
|
if (!root[key].is<String>() || !ip.fromString(root[key].as<String>())) {
|
||||||
ip = defaultIp;
|
ip = defaultIp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeIP(JsonObject &root, const String &key, const IPAddress &ip) {
|
static void writeIP(JsonObject &root, const String &key, const IPAddress &ip) {
|
||||||
if (IPUtils::isSet(ip)) {
|
if (IPUtils::isSet(ip)) {
|
||||||
root[key] = ip.toString();
|
root[key] = ip.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end JsonUtils
|
#endif // end JsonUtils
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <Timing.h>
|
#include <Timing.h>
|
||||||
#include <filesystem.h>
|
#include <filesystem.h>
|
||||||
#include <Features.h>
|
#include <Features.h>
|
||||||
|
#include <settings/peripherals_settings.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
@@ -55,50 +56,6 @@
|
|||||||
*/
|
*/
|
||||||
#define MAX_DISTANCE 200
|
#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> {
|
class Peripherals : public StatefulService<PeripheralsConfiguration> {
|
||||||
public:
|
public:
|
||||||
Peripherals(PsychicHttpServer *server, FS *fs)
|
Peripherals(PsychicHttpServer *server, FS *fs)
|
||||||
|
|||||||
@@ -10,63 +10,11 @@
|
|||||||
#include <stateful_service_endpoint.h>
|
#include <stateful_service_endpoint.h>
|
||||||
#include <MathUtils.h>
|
#include <MathUtils.h>
|
||||||
#include <Timing.h>
|
#include <Timing.h>
|
||||||
|
#include <settings/servo_settings.h>
|
||||||
|
|
||||||
#define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM"
|
#define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM"
|
||||||
#define EVENT_SERVO_STATE "servoState"
|
#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> {
|
class ServoController : public StatefulService<ServoSettings> {
|
||||||
public:
|
public:
|
||||||
ServoController(PsychicHttpServer *server, FS *fs, Peripherals *peripherals)
|
ServoController(PsychicHttpServer *server, FS *fs, Peripherals *peripherals)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <stateful_service_endpoint.h>
|
#include <stateful_service_endpoint.h>
|
||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
#include <ap_settings.h>
|
#include <settings/ap_settings.h>
|
||||||
#include <Timing.h>
|
#include <Timing.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <stateful_service_endpoint.h>
|
#include <stateful_service_endpoint.h>
|
||||||
#include <domain/ntp_settings.h>
|
#include <settings/ntp_settings.h>
|
||||||
|
|
||||||
#include <lwip/apps/sntp.h>
|
#include <lwip/apps/sntp.h>
|
||||||
#include <time.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;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
#include <stateful_service_endpoint.h>
|
#include <stateful_service_endpoint.h>
|
||||||
#include <wifi_settings.h>
|
#include <settings/wifi_settings.h>
|
||||||
|
|
||||||
class WiFiService : public StatefulService<WiFiSettings> {
|
class WiFiService : public StatefulService<WiFiSettings> {
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user