mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-19 06:23:44 +02:00
Added PWM live control and get_led_duty_cycle
This commit is contained in:
@@ -11,5 +11,5 @@ idf_component_register(
|
|||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"CommandManager"
|
"CommandManager"
|
||||||
"CommandManager/commands"
|
"CommandManager/commands"
|
||||||
REQUIRES ProjectConfig cJSON CameraManager OpenIrisTasks wifiManager Helpers
|
REQUIRES ProjectConfig cJSON CameraManager OpenIrisTasks wifiManager Helpers LEDManager
|
||||||
)
|
)
|
||||||
@@ -24,6 +24,7 @@ std::unordered_map<std::string, CommandType> commandTypeMap = {
|
|||||||
{"switch_mode", CommandType::SWITCH_MODE},
|
{"switch_mode", CommandType::SWITCH_MODE},
|
||||||
{"get_device_mode", CommandType::GET_DEVICE_MODE},
|
{"get_device_mode", CommandType::GET_DEVICE_MODE},
|
||||||
{"set_led_duty_cycle", CommandType::SET_LED_DUTY_CYCLE},
|
{"set_led_duty_cycle", CommandType::SET_LED_DUTY_CYCLE},
|
||||||
|
{"get_led_duty_cycle", CommandType::GET_LED_DUTY_CYCLE},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<CommandResult()> CommandManager::createCommand(const CommandType type, std::string_view json) const
|
std::function<CommandResult()> CommandManager::createCommand(const CommandType type, std::string_view json) const
|
||||||
@@ -93,6 +94,9 @@ std::function<CommandResult()> CommandManager::createCommand(const CommandType t
|
|||||||
case CommandType::SET_LED_DUTY_CYCLE:
|
case CommandType::SET_LED_DUTY_CYCLE:
|
||||||
return [this, json]
|
return [this, json]
|
||||||
{ return updateLEDDutyCycleCommand(this->registry, json); };
|
{ return updateLEDDutyCycleCommand(this->registry, json); };
|
||||||
|
case CommandType::GET_LED_DUTY_CYCLE:
|
||||||
|
return [this]
|
||||||
|
{ return getLEDDutyCycleCommand(this->registry); };
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ enum class CommandType
|
|||||||
SWITCH_MODE,
|
SWITCH_MODE,
|
||||||
GET_DEVICE_MODE,
|
GET_DEVICE_MODE,
|
||||||
SET_LED_DUTY_CYCLE,
|
SET_LED_DUTY_CYCLE,
|
||||||
|
GET_LED_DUTY_CYCLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandManager
|
class CommandManager
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ enum class DependencyType
|
|||||||
{
|
{
|
||||||
project_config,
|
project_config,
|
||||||
camera_manager,
|
camera_manager,
|
||||||
wifi_manager
|
wifi_manager,
|
||||||
|
led_manager
|
||||||
};
|
};
|
||||||
|
|
||||||
class DependencyRegistry
|
class DependencyRegistry
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "device_commands.hpp"
|
#include "device_commands.hpp"
|
||||||
|
#include "LEDManager.hpp"
|
||||||
|
|
||||||
// Implementation inspired by SummerSigh work, initial PR opened in openiris repo, adapted to this rewrite
|
// Implementation inspired by SummerSigh work, initial PR opened in openiris repo, adapted to this rewrite
|
||||||
CommandResult setDeviceModeCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload)
|
CommandResult setDeviceModeCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload)
|
||||||
@@ -96,6 +97,13 @@ CommandResult updateLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> regi
|
|||||||
const auto projectConfig = registry->resolve<ProjectConfig>(DependencyType::project_config);
|
const auto projectConfig = registry->resolve<ProjectConfig>(DependencyType::project_config);
|
||||||
projectConfig->setLEDDUtyCycleConfig(dutyCycle);
|
projectConfig->setLEDDUtyCycleConfig(dutyCycle);
|
||||||
|
|
||||||
|
// Try to apply the change live via LEDManager if available
|
||||||
|
auto ledMgr = registry->resolve<LEDManager>(DependencyType::led_manager);
|
||||||
|
if (ledMgr)
|
||||||
|
{
|
||||||
|
ledMgr->setExternalLEDDutyCycle(static_cast<uint8_t>(dutyCycle));
|
||||||
|
}
|
||||||
|
|
||||||
cJSON_Delete(parsedJson);
|
cJSON_Delete(parsedJson);
|
||||||
|
|
||||||
return CommandResult::getSuccessResult("LED duty cycle set");
|
return CommandResult::getSuccessResult("LED duty cycle set");
|
||||||
@@ -107,6 +115,15 @@ CommandResult restartDeviceCommand()
|
|||||||
return CommandResult::getSuccessResult("Device restarted");
|
return CommandResult::getSuccessResult("Device restarted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandResult getLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry)
|
||||||
|
{
|
||||||
|
const auto projectConfig = registry->resolve<ProjectConfig>(DependencyType::project_config);
|
||||||
|
const auto deviceCfg = projectConfig->getDeviceConfig();
|
||||||
|
int duty = deviceCfg.led_external_pwm_duty_cycle;
|
||||||
|
auto result = std::format("{{ \"led_external_pwm_duty_cycle\": {} }}", duty);
|
||||||
|
return CommandResult::getSuccessResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
CommandResult startStreamingCommand()
|
CommandResult startStreamingCommand()
|
||||||
{
|
{
|
||||||
activateStreaming(false); // Don't disable setup interfaces by default
|
activateStreaming(false); // Don't disable setup interfaces by default
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ CommandResult setDeviceModeCommand(std::shared_ptr<DependencyRegistry> registry,
|
|||||||
CommandResult updateOTACredentialsCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
|
CommandResult updateOTACredentialsCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
|
||||||
|
|
||||||
CommandResult updateLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
|
CommandResult updateLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry, std::string_view jsonPayload);
|
||||||
|
CommandResult getLEDDutyCycleCommand(std::shared_ptr<DependencyRegistry> registry);
|
||||||
|
|
||||||
CommandResult restartDeviceCommand();
|
CommandResult restartDeviceCommand();
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,29 @@ void LEDManager::toggleLED(const bool state) const
|
|||||||
gpio_set_level(blink_led_pin, state);
|
gpio_set_level(blink_led_pin, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LEDManager::setExternalLEDDutyCycle(uint8_t dutyPercent)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LED_EXTERNAL_CONTROL
|
||||||
|
dutyPercent = std::min<uint8_t>(100, dutyPercent);
|
||||||
|
const uint32_t dutyCycle = (static_cast<uint32_t>(dutyPercent) * 255) / 100;
|
||||||
|
ESP_LOGI(LED_MANAGER_TAG, "Updating external LED duty to %u%% (raw %lu)", dutyPercent, dutyCycle);
|
||||||
|
|
||||||
|
// Persist into config immediately so it survives reboot
|
||||||
|
if (this->deviceConfig)
|
||||||
|
{
|
||||||
|
this->deviceConfig->setLEDDUtyCycleConfig(dutyPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply to LEDC hardware live
|
||||||
|
// We configured channel 0 in setup with LEDC_LOW_SPEED_MODE
|
||||||
|
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, dutyCycle));
|
||||||
|
ESP_ERROR_CHECK_WITHOUT_ABORT(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
|
||||||
|
#else
|
||||||
|
(void)dutyPercent; // unused
|
||||||
|
ESP_LOGW(LED_MANAGER_TAG, "CONFIG_LED_EXTERNAL_CONTROL not enabled; ignoring duty update");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void HandleLEDDisplayTask(void *pvParameter)
|
void HandleLEDDisplayTask(void *pvParameter)
|
||||||
{
|
{
|
||||||
auto *ledManager = static_cast<LEDManager *>(pvParameter);
|
auto *ledManager = static_cast<LEDManager *>(pvParameter);
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ public:
|
|||||||
void handleLED();
|
void handleLED();
|
||||||
size_t getTimeToDelayFor() const { return timeToDelayFor; }
|
size_t getTimeToDelayFor() const { return timeToDelayFor; }
|
||||||
|
|
||||||
|
// Apply new external LED PWM duty cycle immediately (0-100)
|
||||||
|
void setExternalLEDDutyCycle(uint8_t dutyPercent);
|
||||||
|
uint8_t getExternalLEDDutyCycle() const { return deviceConfig ? deviceConfig->getDeviceConfig().led_external_pwm_duty_cycle : 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void toggleLED(bool state) const;
|
void toggleLED(bool state) const;
|
||||||
void displayCurrentPattern();
|
void displayCurrentPattern();
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ extern "C" void app_main(void)
|
|||||||
dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig);
|
dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig);
|
||||||
dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler);
|
dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler);
|
||||||
dependencyRegistry->registerService<WiFiManager>(DependencyType::wifi_manager, wifiManager);
|
dependencyRegistry->registerService<WiFiManager>(DependencyType::wifi_manager, wifiManager);
|
||||||
|
dependencyRegistry->registerService<LEDManager>(DependencyType::led_manager, std::shared_ptr<LEDManager>(ledManager, [](LEDManager*){}));
|
||||||
// uvc plan
|
// uvc plan
|
||||||
// cleanup the logs - done
|
// cleanup the logs - done
|
||||||
// prepare the camera to be initialized with UVC - done?
|
// prepare the camera to be initialized with UVC - done?
|
||||||
|
|||||||
@@ -421,6 +421,24 @@ class OpenIrisDevice:
|
|||||||
print("✅ LED duty cycle set successfully")
|
print("✅ LED duty cycle set successfully")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_led_duty_cycle(self) -> Optional[int]:
|
||||||
|
"""Get the current LED PWM duty cycle from the device"""
|
||||||
|
response = self.send_command("get_led_duty_cycle")
|
||||||
|
if "error" in response:
|
||||||
|
print(f"❌ Failed to get LED duty cycle: {response['error']}")
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
results = response.get("results", [])
|
||||||
|
if results:
|
||||||
|
result_data = json.loads(results[0])
|
||||||
|
payload = result_data["result"]
|
||||||
|
if isinstance(payload, str):
|
||||||
|
payload = json.loads(payload)
|
||||||
|
return int(payload.get("led_external_pwm_duty_cycle"))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to parse LED duty cycle: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def monitor_logs(self):
|
def monitor_logs(self):
|
||||||
"""Monitor device logs until interrupted"""
|
"""Monitor device logs until interrupted"""
|
||||||
print("📋 Monitoring device logs (Press Ctrl+C to exit)...")
|
print("📋 Monitoring device logs (Press Ctrl+C to exit)...")
|
||||||
@@ -761,14 +779,20 @@ def set_led_duty_cycle(device: OpenIrisDevice, args=None):
|
|||||||
if duty_cycle < 0 or duty_cycle > 100:
|
if duty_cycle < 0 or duty_cycle > 100:
|
||||||
print("❌ Duty cycle must be between 0 and 100.")
|
print("❌ Duty cycle must be between 0 and 100.")
|
||||||
else:
|
else:
|
||||||
|
# Apply immediately; stay in loop for further tweaks
|
||||||
device.set_led_duty_cycle(duty_cycle)
|
device.set_led_duty_cycle(duty_cycle)
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def monitor_logs(device: OpenIrisDevice, args = None):
|
def monitor_logs(device: OpenIrisDevice, args = None):
|
||||||
device.monitor_logs()
|
device.monitor_logs()
|
||||||
|
|
||||||
|
|
||||||
|
def get_led_duty_cycle(device: OpenIrisDevice, args=None):
|
||||||
|
duty = device.get_led_duty_cycle()
|
||||||
|
if duty is not None:
|
||||||
|
print(f"💡 Current LED duty cycle: {duty}%")
|
||||||
|
|
||||||
|
|
||||||
COMMANDS_MAP = {
|
COMMANDS_MAP = {
|
||||||
"1": scan_networks,
|
"1": scan_networks,
|
||||||
"2": display_networks,
|
"2": display_networks,
|
||||||
@@ -780,7 +804,8 @@ COMMANDS_MAP = {
|
|||||||
"8": start_streaming,
|
"8": start_streaming,
|
||||||
"9": switch_device_mode,
|
"9": switch_device_mode,
|
||||||
"10": set_led_duty_cycle,
|
"10": set_led_duty_cycle,
|
||||||
"11": monitor_logs,
|
"11": get_led_duty_cycle,
|
||||||
|
"12": monitor_logs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -879,9 +904,10 @@ def main():
|
|||||||
print("8. 🚀 Start streaming mode")
|
print("8. 🚀 Start streaming mode")
|
||||||
print("9. 🔄 Switch device mode (WiFi/UVC/Auto)")
|
print("9. 🔄 Switch device mode (WiFi/UVC/Auto)")
|
||||||
print("10. 💡 Update PWM Duty Cycle")
|
print("10. 💡 Update PWM Duty Cycle")
|
||||||
print("11. 📋 Monitor logs")
|
print("11. 💡Get PWM Duty Cycle")
|
||||||
|
print("12. 📖 Monitor logs")
|
||||||
print("exit. 🚪 Exit")
|
print("exit. 🚪 Exit")
|
||||||
choice = input("\nSelect option (1-11): ").strip()
|
choice = input("\nSelect option (1-12): ").strip()
|
||||||
|
|
||||||
if choice == "exit":
|
if choice == "exit":
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user