From 21e8dbe264ce5f31c0df986f0b35fb33a6fc6b98 Mon Sep 17 00:00:00 2001 From: Lorow Date: Tue, 19 Aug 2025 00:03:31 +0200 Subject: [PATCH] Add PoC PWN duty cycle adjustment command for FaceFocus --- .../CommandManager/CommandManager.cpp | 63 ++++++++++------ .../CommandManager/CommandManager.hpp | 1 + .../commands/device_commands.cpp | 35 ++++++++- .../commands/device_commands.hpp | 2 + components/LEDManager/CMakeLists.txt | 2 +- .../LEDManager/LEDManager/LEDManager.cpp | 71 +++++++++++-------- .../LEDManager/LEDManager/LEDManager.hpp | 4 +- .../ProjectConfig/ProjectConfig/Models.hpp | 48 ++++++++----- .../ProjectConfig/ProjectConfig.cpp | 39 ++++++---- .../ProjectConfig/ProjectConfig.hpp | 12 ++-- main/openiris_main.cpp | 10 ++- sdkconfig.board.project_babble | 2 +- tools/openiris_setup.py | 37 +++++++++- 13 files changed, 227 insertions(+), 99 deletions(-) diff --git a/components/CommandManager/CommandManager/CommandManager.cpp b/components/CommandManager/CommandManager/CommandManager.cpp index 7932a1d..c4f897f 100644 --- a/components/CommandManager/CommandManager/CommandManager.cpp +++ b/components/CommandManager/CommandManager/CommandManager.cpp @@ -23,53 +23,76 @@ std::unordered_map commandTypeMap = { {"connect_wifi", CommandType::CONNECT_WIFI}, {"switch_mode", CommandType::SWITCH_MODE}, {"get_device_mode", CommandType::GET_DEVICE_MODE}, + {"set_led_duty_cycle", CommandType::SET_LED_DUTY_CYCLE}, }; -std::function CommandManager::createCommand(const CommandType type, std::string_view json) const { +std::function CommandManager::createCommand(const CommandType type, std::string_view json) const +{ switch (type) { case CommandType::PING: - return { PingCommand }; + return {PingCommand}; case CommandType::PAUSE: - return [json] { return PauseCommand(json); }; + return [json] + { return PauseCommand(json); }; case CommandType::SET_STREAMING_MODE: - return [this, json] {return setDeviceModeCommand(this->registry, json); }; + return [this, json] + { return setDeviceModeCommand(this->registry, json); }; case CommandType::UPDATE_OTA_CREDENTIALS: - return [this, json] { return updateOTACredentialsCommand(this->registry, json); }; + return [this, json] + { return updateOTACredentialsCommand(this->registry, json); }; case CommandType::SET_WIFI: - return [this, json] { return setWiFiCommand(this->registry, json); }; + return [this, json] + { return setWiFiCommand(this->registry, json); }; case CommandType::UPDATE_WIFI: - return [this, json] { return updateWiFiCommand(this->registry, json); }; + return [this, json] + { return updateWiFiCommand(this->registry, json); }; case CommandType::UPDATE_AP_WIFI: - return [this, json] { return updateAPWiFiCommand(this->registry, json); }; + return [this, json] + { return updateAPWiFiCommand(this->registry, json); }; case CommandType::DELETE_NETWORK: - return [this, json] { return deleteWiFiCommand(this->registry, json); }; + return [this, json] + { return deleteWiFiCommand(this->registry, json); }; case CommandType::SET_MDNS: - return [this, json] { return setMDNSCommand(this->registry, json); }; + return [this, json] + { return setMDNSCommand(this->registry, json); }; case CommandType::UPDATE_CAMERA: - return [this, json] { return updateCameraCommand(this->registry, json); }; + return [this, json] + { return updateCameraCommand(this->registry, json); }; case CommandType::RESTART_CAMERA: - return [this, json] { return restartCameraCommand(this->registry, json); }; + return [this, json] + { return restartCameraCommand(this->registry, json); }; case CommandType::GET_CONFIG: - return [this] { return getConfigCommand(this->registry); }; + return [this] + { return getConfigCommand(this->registry); }; case CommandType::SAVE_CONFIG: - return [this] { return saveConfigCommand(this->registry); }; + return [this] + { return saveConfigCommand(this->registry); }; case CommandType::RESET_CONFIG: - return [this, json] { return resetConfigCommand(this->registry, json); }; + return [this, json] + { return resetConfigCommand(this->registry, json); }; case CommandType::RESTART_DEVICE: return restartDeviceCommand; case CommandType::SCAN_NETWORKS: - return [this] { return scanNetworksCommand(this->registry); }; + return [this] + { return scanNetworksCommand(this->registry); }; case CommandType::START_STREAMING: return startStreamingCommand; case CommandType::GET_WIFI_STATUS: - return [this] { return getWiFiStatusCommand(this->registry); }; + return [this] + { return getWiFiStatusCommand(this->registry); }; case CommandType::CONNECT_WIFI: - return [this] { return connectWiFiCommand(this->registry); }; + return [this] + { return connectWiFiCommand(this->registry); }; case CommandType::SWITCH_MODE: - return [this, json] { return switchModeCommand(this->registry, json); }; + return [this, json] + { return switchModeCommand(this->registry, json); }; case CommandType::GET_DEVICE_MODE: - return [this] { return getDeviceModeCommand(this->registry); }; + return [this] + { return getDeviceModeCommand(this->registry); }; + case CommandType::SET_LED_DUTY_CYCLE: + return [this, json] + { return updateLEDDutyCycleCommand(this->registry, json); }; default: return nullptr; } diff --git a/components/CommandManager/CommandManager/CommandManager.hpp b/components/CommandManager/CommandManager/CommandManager.hpp index 02231e3..5db67d0 100644 --- a/components/CommandManager/CommandManager/CommandManager.hpp +++ b/components/CommandManager/CommandManager/CommandManager.hpp @@ -44,6 +44,7 @@ enum class CommandType CONNECT_WIFI, SWITCH_MODE, GET_DEVICE_MODE, + SET_LED_DUTY_CYCLE, }; class CommandManager diff --git a/components/CommandManager/CommandManager/commands/device_commands.cpp b/components/CommandManager/CommandManager/commands/device_commands.cpp index 2ffc4dd..0ccd9ca 100644 --- a/components/CommandManager/CommandManager/commands/device_commands.cpp +++ b/components/CommandManager/CommandManager/commands/device_commands.cpp @@ -25,6 +25,8 @@ CommandResult setDeviceModeCommand(std::shared_ptr registry, const auto projectConfig = registry->resolve(DependencyType::project_config); projectConfig->setDeviceMode(static_cast(mode)); + cJSON_Delete(parsedJson); + return CommandResult::getSuccessResult("Device mode set"); } @@ -64,10 +66,41 @@ CommandResult updateOTACredentialsCommand(std::shared_ptr re } } - projectConfig->setDeviceConfig(OTALogin, OTAPassword, OTAPort); + cJSON_Delete(parsedJson); + + projectConfig->setOTAConfig(OTALogin, OTAPassword, OTAPort); return CommandResult::getSuccessResult("OTA Config set"); } +CommandResult updateLEDDutyCycleCommand(std::shared_ptr registry, std::string_view jsonPayload) +{ + const auto parsedJson = cJSON_Parse(jsonPayload.data()); + if (parsedJson == nullptr) + { + return CommandResult::getErrorResult("Invalid payload"); + } + + const auto dutyCycleObject = cJSON_GetObjectItem(parsedJson, "dutyCycle"); + if (dutyCycleObject == nullptr) + { + return CommandResult::getErrorResult("Invalid payload - missing dutyCycle"); + } + + const auto dutyCycle = dutyCycleObject->valueint; + + if (dutyCycle < 0 || dutyCycle > 100) + { + return CommandResult::getErrorResult("Invalid payload - unsupported dutyCycle"); + } + + const auto projectConfig = registry->resolve(DependencyType::project_config); + projectConfig->setLEDDUtyCycleConfig(dutyCycle); + + cJSON_Delete(parsedJson); + + return CommandResult::getSuccessResult("LED duty cycle set"); +} + CommandResult restartDeviceCommand() { OpenIrisTasks::ScheduleRestart(2000); diff --git a/components/CommandManager/CommandManager/commands/device_commands.hpp b/components/CommandManager/CommandManager/commands/device_commands.hpp index 4eb1b3d..22cde8a 100644 --- a/components/CommandManager/CommandManager/commands/device_commands.hpp +++ b/components/CommandManager/CommandManager/commands/device_commands.hpp @@ -13,6 +13,8 @@ CommandResult setDeviceModeCommand(std::shared_ptr registry, CommandResult updateOTACredentialsCommand(std::shared_ptr registry, std::string_view jsonPayload); +CommandResult updateLEDDutyCycleCommand(std::shared_ptr registry, std::string_view jsonPayload); + CommandResult restartDeviceCommand(); CommandResult startStreamingCommand(); diff --git a/components/LEDManager/CMakeLists.txt b/components/LEDManager/CMakeLists.txt index b377b09..4466f41 100644 --- a/components/LEDManager/CMakeLists.txt +++ b/components/LEDManager/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "LEDManager/LEDManager.cpp" INCLUDE_DIRS "LEDManager" - REQUIRES StateManager driver esp_driver_ledc Helpers + REQUIRES StateManager driver esp_driver_ledc Helpers ProjectConfig ) \ No newline at end of file diff --git a/components/LEDManager/LEDManager/LEDManager.cpp b/components/LEDManager/LEDManager/LEDManager.cpp index 97ad6e0..19c7da4 100644 --- a/components/LEDManager/LEDManager/LEDManager.cpp +++ b/components/LEDManager/LEDManager/LEDManager.cpp @@ -48,10 +48,7 @@ ledStateMap_t LEDManager::ledStateMap = { { false, false, - { - {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}, - {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200} - }, + {{LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}, {LED_ON, 200}, {LED_OFF, 200}}, }, }, { @@ -65,32 +62,38 @@ ledStateMap_t LEDManager::ledStateMap = { }; LEDManager::LEDManager(gpio_num_t pin, gpio_num_t illumninator_led_pin, - QueueHandle_t ledStateQueue) : blink_led_pin(pin), - illumninator_led_pin(illumninator_led_pin), - ledStateQueue(ledStateQueue), - currentState(LEDStates_e::LedStateNone) { + QueueHandle_t ledStateQueue, std::shared_ptr deviceConfig) : blink_led_pin(pin), + illumninator_led_pin(illumninator_led_pin), + ledStateQueue(ledStateQueue), + currentState(LEDStates_e::LedStateNone), + deviceConfig(deviceConfig) +{ } -void LEDManager::setup() { - ESP_LOGD(LED_MANAGER_TAG, "Setting up status led."); +void LEDManager::setup() +{ + ESP_LOGI(LED_MANAGER_TAG, "Setting up status led."); gpio_reset_pin(blink_led_pin); /* Set the GPIO as a push/pull output */ gpio_set_direction(blink_led_pin, GPIO_MODE_OUTPUT); this->toggleLED(LED_OFF); #ifdef CONFIG_LED_EXTERNAL_CONTROL - ESP_LOGD(LED_MANAGER_TAG, "Setting up illuminator led."); + ESP_LOGI(LED_MANAGER_TAG, "Setting up illuminator led."); const int freq = CONFIG_LED_EXTERNAL_PWM_FREQ; const auto resolution = LEDC_TIMER_8_BIT; - const int dutyCycle = (CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE * 255) / 100; + const auto deviceConfig = this->deviceConfig->getDeviceConfig(); + + const uint32_t dutyCycle = (deviceConfig.led_external_pwm_duty_cycle * 255) / 100; + + ESP_LOGI(LED_MANAGER_TAG, "Setting dutyCycle to: %lu ", dutyCycle); ledc_timer_config_t ledc_timer = { .speed_mode = LEDC_LOW_SPEED_MODE, .duty_resolution = resolution, .timer_num = LEDC_TIMER_0, .freq_hz = freq, - .clk_cfg = LEDC_AUTO_CLK - }; + .clk_cfg = LEDC_AUTO_CLK}; ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); @@ -101,8 +104,7 @@ void LEDManager::setup() { .intr_type = LEDC_INTR_DISABLE, .timer_sel = LEDC_TIMER_0, .duty = dutyCycle, - .hpoint = 0 - }; + .hpoint = 0}; ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); #endif @@ -110,37 +112,46 @@ void LEDManager::setup() { ESP_LOGD(LED_MANAGER_TAG, "Done."); } -void LEDManager::handleLED() { - if (!this->finishedPattern) { +void LEDManager::handleLED() +{ + if (!this->finishedPattern) + { displayCurrentPattern(); return; } - if (xQueueReceive(this->ledStateQueue, &buffer, 10)) { + if (xQueueReceive(this->ledStateQueue, &buffer, 10)) + { this->updateState(buffer); - } else { + } + else + { // we've finished displaying the pattern, so let's check if it's repeatable and if so - reset it - if (ledStateMap[this->currentState].isRepeatable || ledStateMap[this->currentState].isError) { + if (ledStateMap[this->currentState].isRepeatable || ledStateMap[this->currentState].isError) + { this->currentPatternIndex = 0; this->finishedPattern = false; } } } -void LEDManager::displayCurrentPattern() { +void LEDManager::displayCurrentPattern() +{ auto [state, delayTime] = ledStateMap[this->currentState].patterns[this->currentPatternIndex]; this->toggleLED(state); this->timeToDelayFor = delayTime; if (this->currentPatternIndex < ledStateMap[this->currentState].patterns.size() - 1) this->currentPatternIndex++; - else { + else + { this->finishedPattern = true; this->toggleLED(LED_OFF); } } -void LEDManager::updateState(const LEDStates_e newState) { +void LEDManager::updateState(const LEDStates_e newState) +{ // we should change the displayed state // only if we finished displaying the current one - which is handled by the task // if the new state is not the same as the current one @@ -153,21 +164,25 @@ void LEDManager::updateState(const LEDStates_e newState) { if (newState == this->currentState) return; - if (ledStateMap.contains(newState)) { + if (ledStateMap.contains(newState)) + { this->currentState = newState; this->currentPatternIndex = 0; this->finishedPattern = false; } } -void LEDManager::toggleLED(const bool state) const { +void LEDManager::toggleLED(const bool state) const +{ gpio_set_level(blink_led_pin, state); } -void HandleLEDDisplayTask(void *pvParameter) { +void HandleLEDDisplayTask(void *pvParameter) +{ auto *ledManager = static_cast(pvParameter); - while (true) { + while (true) + { ledManager->handleLED(); vTaskDelay(ledManager->getTimeToDelayFor()); } diff --git a/components/LEDManager/LEDManager/LEDManager.hpp b/components/LEDManager/LEDManager/LEDManager.hpp index af92387..1f4fa67 100644 --- a/components/LEDManager/LEDManager/LEDManager.hpp +++ b/components/LEDManager/LEDManager/LEDManager.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include // it kinda looks like different boards have these states swapped @@ -41,7 +42,7 @@ typedef std::unordered_map class LEDManager { public: - LEDManager(gpio_num_t blink_led_pin, gpio_num_t illumninator_led_pin, QueueHandle_t ledStateQueue); + LEDManager(gpio_num_t blink_led_pin, gpio_num_t illumninator_led_pin, QueueHandle_t ledStateQueue, std::shared_ptr deviceConfig); void setup(); void handleLED(); @@ -60,6 +61,7 @@ private: LEDStates_e buffer; LEDStates_e currentState; + std::shared_ptr deviceConfig; size_t currentPatternIndex = 0; size_t timeToDelayFor = 100; diff --git a/components/ProjectConfig/ProjectConfig/Models.hpp b/components/ProjectConfig/ProjectConfig/Models.hpp index 85c9b81..4326344 100644 --- a/components/ProjectConfig/ProjectConfig/Models.hpp +++ b/components/ProjectConfig/ProjectConfig/Models.hpp @@ -21,35 +21,39 @@ struct BaseConfigModel Preferences *pref; }; -enum class StreamingMode { +enum class StreamingMode +{ AUTO, UVC, WIFI, }; -struct DeviceMode_t : BaseConfigModel { +struct DeviceMode_t : BaseConfigModel +{ StreamingMode mode; - explicit DeviceMode_t( Preferences *pref) : BaseConfigModel(pref), mode(StreamingMode::AUTO){} + explicit DeviceMode_t(Preferences *pref) : BaseConfigModel(pref), mode(StreamingMode::AUTO) {} - void load() { + void load() + { int stored_mode = this->pref->getInt("mode", 0); this->mode = static_cast(stored_mode); ESP_LOGI("DeviceMode", "Loaded device mode: %d", stored_mode); } - void save() const { + void save() const + { this->pref->putInt("mode", static_cast(this->mode)); ESP_LOGI("DeviceMode", "Saved device mode: %d", static_cast(this->mode)); } }; - struct DeviceConfig_t : BaseConfigModel { DeviceConfig_t(Preferences *pref) : BaseConfigModel(pref) {} std::string OTALogin; std::string OTAPassword; + int led_external_pwm_duty_cycle; int OTAPort; void load() @@ -57,20 +61,23 @@ struct DeviceConfig_t : BaseConfigModel this->OTALogin = this->pref->getString("OTALogin", "openiris"); this->OTAPassword = this->pref->getString("OTAPassword", "openiris"); this->OTAPort = this->pref->getInt("OTAPort", 3232); + this->led_external_pwm_duty_cycle = this->pref->getInt("led_ext_pwm", CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE); }; - void save() const { + void save() const + { this->pref->putString("OTALogin", this->OTALogin.c_str()); this->pref->putString("OTAPassword", this->OTAPassword.c_str()); this->pref->putInt("OTAPort", this->OTAPort); + this->pref->putInt("led_ext_pwm", this->led_external_pwm_duty_cycle); }; std::string toRepresentation() const { return Helpers::format_string( "\"device_config\": {\"OTALogin\": \"%s\", \"OTAPassword\": \"%s\", " - "\"OTAPort\": %u}", - this->OTALogin.c_str(), this->OTAPassword.c_str(), this->OTAPort); + "\"OTAPort\": %u, \"led_external_pwm_duty_cycle\": %u}", + this->OTALogin.c_str(), this->OTAPassword.c_str(), this->OTAPort, this->led_external_pwm_duty_cycle); }; }; @@ -94,7 +101,8 @@ struct MDNSConfig_t : BaseConfigModel this->hostname = this->pref->getString("hostname", default_hostname); }; - void save() const { + void save() const + { this->pref->putString("hostname", this->hostname.c_str()); }; @@ -125,7 +133,8 @@ struct CameraConfig_t : BaseConfigModel this->brightness = this->pref->getInt("brightness", 2); }; - void save() const { + void save() const + { this->pref->putInt("vflip", this->vflip); this->pref->putInt("href", this->href); this->pref->putInt("framesize", this->framesize); @@ -186,12 +195,13 @@ struct WiFiConfig_t : BaseConfigModel this->password = this->pref->getString(("password" + iter_str).c_str(), ""); this->channel = this->pref->getUInt(("channel" + iter_str).c_str()); this->power = this->pref->getUInt(("power" + iter_str).c_str()); - - ESP_LOGI("WiFiConfig", "Loaded network %d: name=%s, ssid=%s, channel=%d", + + ESP_LOGI("WiFiConfig", "Loaded network %d: name=%s, ssid=%s, channel=%d", index, this->name.c_str(), this->ssid.c_str(), this->channel); }; - void save() const { + void save() const + { char buffer[2]; auto const iter_str = std::string(Helpers::itoa(this->index, buffer, 10)); @@ -200,8 +210,8 @@ struct WiFiConfig_t : BaseConfigModel this->pref->putString(("password" + iter_str).c_str(), this->password.c_str()); this->pref->putUInt(("channel" + iter_str).c_str(), this->channel); this->pref->putUInt(("power" + iter_str).c_str(), this->power); - - ESP_LOGI("WiFiConfig", "Saved network %d: name=%s, ssid=%s, channel=%d", + + ESP_LOGI("WiFiConfig", "Saved network %d: name=%s, ssid=%s, channel=%d", this->index, this->name.c_str(), this->ssid.c_str(), this->channel); }; @@ -228,7 +238,8 @@ struct AP_WiFiConfig_t : BaseConfigModel this->password = this->pref->getString("apPassword", CONFIG_WIFI_AP_PASSWORD); }; - void save() const { + void save() const + { this->pref->putString("apSSID", this->ssid.c_str()); this->pref->putString("apPass", this->password.c_str()); this->pref->putUInt("apChannel", this->channel); @@ -254,7 +265,8 @@ struct WiFiTxPower_t : BaseConfigModel this->power = this->pref->getUInt("txpower", 52); }; - void save() const { + void save() const + { this->pref->putUInt("txpower", this->power); }; diff --git a/components/ProjectConfig/ProjectConfig/ProjectConfig.cpp b/components/ProjectConfig/ProjectConfig/ProjectConfig.cpp index ae7b189..ca38622 100644 --- a/components/ProjectConfig/ProjectConfig/ProjectConfig.cpp +++ b/components/ProjectConfig/ProjectConfig/ProjectConfig.cpp @@ -24,7 +24,8 @@ ProjectConfig::ProjectConfig(Preferences *pref) : pref(pref), ProjectConfig::~ProjectConfig() = default; -void ProjectConfig::save() const { +void ProjectConfig::save() const +{ ESP_LOGD(CONFIGURATION_TAG, "Saving project config"); this->config.device.save(); this->config.device_mode.save(); @@ -92,14 +93,22 @@ bool ProjectConfig::reset() //! DeviceConfig //* //********************************************************************************************************************** -void ProjectConfig::setDeviceConfig(const std::string &OTALogin, - const std::string &OTAPassword, - const int OTAPort) +void ProjectConfig::setOTAConfig(const std::string &OTALogin, + const std::string &OTAPassword, + const int OTAPort) { ESP_LOGD(CONFIGURATION_TAG, "Updating device config"); this->config.device.OTALogin.assign(OTALogin); this->config.device.OTAPassword.assign(OTAPassword); this->config.device.OTAPort = OTAPort; + this->config.device.save(); +} + +void ProjectConfig::setLEDDUtyCycleConfig(int led_external_pwm_duty_cycle) +{ + this->config.device.led_external_pwm_duty_cycle = led_external_pwm_duty_cycle; + ESP_LOGI(CONFIGURATION_TAG, "Setting duty cycle to %d", led_external_pwm_duty_cycle); + this->config.device.save(); } void ProjectConfig::setMDNSConfig(const std::string &hostname) @@ -120,6 +129,7 @@ void ProjectConfig::setCameraConfig(const uint8_t vflip, this->config.camera.framesize = framesize; this->config.camera.quality = quality; this->config.camera.brightness = brightness; + this->config.camera.save(); ESP_LOGD(CONFIGURATION_TAG, "Updating Camera config"); } @@ -133,8 +143,8 @@ void ProjectConfig::setWifiConfig(const std::string &networkName, const auto size = this->config.networks.size(); const auto it = std::ranges::find_if(this->config.networks, - [&](const WiFiConfig_t &network) - { return network.name == networkName; }); + [&](const WiFiConfig_t &network) + { return network.name == networkName; }); if (it != this->config.networks.end()) { @@ -191,8 +201,8 @@ void ProjectConfig::deleteWifiConfig(const std::string &networkName) } const auto it = std::ranges::find_if(this->config.networks, - [&](const WiFiConfig_t &network) - { return network.name == networkName; }); + [&](const WiFiConfig_t &network) + { return network.name == networkName; }); if (it != this->config.networks.end()) { @@ -205,6 +215,7 @@ void ProjectConfig::deleteWifiConfig(const std::string &networkName) void ProjectConfig::setWiFiTxPower(uint8_t power) { this->config.txpower.power = power; + this->config.txpower.save(); ESP_LOGD(CONFIGURATION_TAG, "Updating wifi tx power"); } @@ -215,12 +226,14 @@ void ProjectConfig::setAPWifiConfig(const std::string &ssid, this->config.ap_network.ssid.assign(ssid); this->config.ap_network.password.assign(password); this->config.ap_network.channel = channel; + this->config.ap_network.save(); ESP_LOGD(CONFIGURATION_TAG, "Updating access point config"); } -void ProjectConfig::setDeviceMode(const StreamingMode deviceMode) { +void ProjectConfig::setDeviceMode(const StreamingMode deviceMode) +{ this->config.device_mode.mode = deviceMode; - this->config.device_mode.save(); // Save immediately + this->config.device_mode.save(); // Save immediately } //********************************************************************************************************************** @@ -258,10 +271,12 @@ TrackerConfig_t &ProjectConfig::getTrackerConfig() return this->config; } -DeviceMode_t &ProjectConfig::getDeviceModeConfig() { +DeviceMode_t &ProjectConfig::getDeviceModeConfig() +{ return this->config.device_mode; } -StreamingMode ProjectConfig::getDeviceMode() { +StreamingMode ProjectConfig::getDeviceMode() +{ return this->config.device_mode.mode; } \ No newline at end of file diff --git a/components/ProjectConfig/ProjectConfig/ProjectConfig.hpp b/components/ProjectConfig/ProjectConfig/ProjectConfig.hpp index 045a8a6..07d04da 100644 --- a/components/ProjectConfig/ProjectConfig/ProjectConfig.hpp +++ b/components/ProjectConfig/ProjectConfig/ProjectConfig.hpp @@ -22,11 +22,6 @@ public: void load(); void save() const; - void wifiConfigSave(); - void cameraConfigSave(); - void deviceConfigSave(); - void mdnsConfigSave(); - void wifiTxPowerConfigSave(); bool reset(); DeviceConfig_t &getDeviceConfig(); @@ -38,9 +33,10 @@ public: WiFiTxPower_t &getWiFiTxPowerConfig(); TrackerConfig_t &getTrackerConfig(); - void setDeviceConfig(const std::string &OTALogin, - const std::string &OTAPassword, - int OTAPort); + void setOTAConfig(const std::string &OTALogin, + const std::string &OTAPassword, + int OTAPort); + void setLEDDUtyCycleConfig(int led_external_pwm_duty_cycle); void setMDNSConfig(const std::string &hostname); void setCameraConfig(uint8_t vflip, uint8_t framesize, diff --git a/main/openiris_main.cpp b/main/openiris_main.cpp index 8c908d6..1e66792 100644 --- a/main/openiris_main.cpp +++ b/main/openiris_main.cpp @@ -53,7 +53,7 @@ auto *restAPI = new RestAPI("http://0.0.0.0:81", commandManager); UVCStreamManager uvcStream; #endif -auto *ledManager = new LEDManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue); +auto *ledManager = new LEDManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue, deviceConfig); auto *serialManager = new SerialManager(commandManager, &timerHandle, deviceConfig); static void initNVSStorage() @@ -274,10 +274,10 @@ extern "C" void app_main(void) // setup CI and building for other boards // finish todos, overhaul stuff a bit + // esp_log_set_vprintf(&websocket_logger); Logo::printASCII(); initNVSStorage(); - - // esp_log_set_vprintf(&websocket_logger); + deviceConfig->load(); ledManager->setup(); xTaskCreate( @@ -297,7 +297,6 @@ extern "C" void app_main(void) 3, nullptr); - deviceConfig->load(); serialManager->setup(); static TaskHandle_t serialManagerHandle = nullptr; @@ -308,8 +307,7 @@ extern "C" void app_main(void) 1024 * 6, serialManager, 1, // we only rely on the serial manager during provisioning, we can run it slower - &serialManagerHandle - ); + &serialManagerHandle); wifiManager->Begin(); mdnsManager.start(); diff --git a/sdkconfig.board.project_babble b/sdkconfig.board.project_babble index 47b59a9..1ef150a 100644 --- a/sdkconfig.board.project_babble +++ b/sdkconfig.board.project_babble @@ -50,5 +50,5 @@ CONFIG_LED_EXTERNAL_CONTROL=y CONFIG_LED_EXTERNAL_PWM_FREQ=5000 CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=100 CONFIG_LED_EXTERNAL_GPIO=1 -CONFIG_CAMERA_USB_XCLK_FREQ=23000000 # NOT TESTED +CONFIG_CAMERA_USB_XCLK_FREQ=23000000 CONFIG_GENERAL_WIRED_MODE=y \ No newline at end of file diff --git a/tools/openiris_setup.py b/tools/openiris_setup.py index d797918..3b8ff30 100644 --- a/tools/openiris_setup.py +++ b/tools/openiris_setup.py @@ -410,6 +410,17 @@ class OpenIrisDevice: print(f"❌ Failed to parse mode response: {e}") return "unknown" + def set_led_duty_cycle(self, duty_cycle): + """Sets the PWN duty cycle of the LED""" + print(f"🌟 Setting LED duty cycle to {duty_cycle}%...") + response = self.send_command("set_led_duty_cycle", {"dutyCycle": duty_cycle}) + if "error" in response: + print(f"❌ Failed to set LED duty cycle: {response['error']}") + return False + + print("✅ LED duty cycle set successfully") + return True + def monitor_logs(self): """Monitor device logs until interrupted""" print("📋 Monitoring device logs (Press Ctrl+C to exit)...") @@ -736,6 +747,24 @@ def switch_device_mode(device: OpenIrisDevice, args = None): print("❌ Invalid mode selection") +def set_led_duty_cycle(device: OpenIrisDevice, args=None): + while True: + input_data = input("Enter LED external PWM duty cycle (0-100) or `back` to exit: \n") + if input_data.lower() == "back": + break + + try: + duty_cycle = int(input_data) + except ValueError: + print("❌ Invalid input. Please enter a number between 0 and 100.") + + if duty_cycle < 0 or duty_cycle > 100: + print("❌ Duty cycle must be between 0 and 100.") + else: + device.set_led_duty_cycle(duty_cycle) + break + + def monitor_logs(device: OpenIrisDevice, args = None): device.monitor_logs() @@ -750,7 +779,8 @@ COMMANDS_MAP = { "7": attempt_wifi_connection, "8": start_streaming, "9": switch_device_mode, - "10": monitor_logs, + "10": set_led_duty_cycle, + "11": monitor_logs, } @@ -848,9 +878,10 @@ def main(): print("7. 🔗 Connect to WiFi") print("8. 🚀 Start streaming mode") print("9. 🔄 Switch device mode (WiFi/UVC/Auto)") - print("10. 📋 Monitor logs") + print("10. 💡 Update PWM Duty Cycle") + print("11. 📋 Monitor logs") print("exit. 🚪 Exit") - choice = input("\nSelect option (1-10): ").strip() + choice = input("\nSelect option (1-11): ").strip() if choice == "exit": break