add simulation to UI

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-09-30 21:53:40 +02:00
parent 9ae568c2f4
commit 0f7686d5a5
13 changed files with 113 additions and 131 deletions

View File

@@ -49,7 +49,7 @@
*/
class LightMenu final : public Menu
{
public:
public:
/**
* @brief Constructs the light control menu with the specified configuration
* @param options Pointer to menu options configuration structure
@@ -80,7 +80,7 @@ public:
*/
explicit LightMenu(menu_options_t *options);
private:
private:
/**
* @brief Handles button press events specific to light control menu items
* @param menuItem
@@ -116,7 +116,7 @@ private:
* @see Menu::onButtonPressed for the base implementation
* @see ButtonType for available button types
*/
void onButtonPressed(const MenuItem& menuItem, ButtonType button) override;
void onButtonPressed(const MenuItem &menuItem, ButtonType button) override;
/**
* @brief Pointer to menu options configuration structure

View File

@@ -1,4 +1,5 @@
#include "ui/ClockScreenSaver.h"
#include "hal_esp32/PersistenceManager.h"
#include "simulator.h"
#include <cstring>
#include <ctime>
@@ -37,22 +38,23 @@ void ClockScreenSaver::updateTextDimensions()
void ClockScreenSaver::getCurrentTimeString(char *buffer, size_t bufferSize) const
{
char *simulated_time = get_time();
if (simulated_time != nullptr)
if (m_options && m_options->persistenceManager->GetValue("light_active", false))
{
strncpy(buffer, simulated_time, bufferSize);
char *simulated_time = get_time();
if (simulated_time != nullptr)
{
strncpy(buffer, simulated_time, bufferSize);
return;
}
}
else
{
time_t rawtime;
struct tm *timeinfo;
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
time(&rawtime);
timeinfo = localtime(&rawtime);
// Format time as HH:MM:SS
strftime(buffer, bufferSize, "%H:%M:%S", timeinfo);
}
// Format time as HH:MM:SS
strftime(buffer, bufferSize, "%H:%M:%S", timeinfo);
}
void ClockScreenSaver::Update(const uint64_t dt)

View File

@@ -1,6 +1,7 @@
#include "ui/LightMenu.h"
#include "led_strip_ws2812.h"
#include "simulator.h"
/**
* @namespace LightMenuItem
@@ -54,19 +55,12 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
{
toggle(menuItem);
const auto value = getItem(menuItem.getId()).getValue() == "1";
if (value)
{
led_strip_update(LED_STATE_DAY, rgb_t{});
}
else
{
led_strip_update(LED_STATE_OFF, rgb_t{});
}
if (m_options && m_options->persistenceManager)
{
m_options->persistenceManager->SetValue(LightMenuOptions::LIGHT_ACTIVE, value);
}
start_simulation();
}
break;
}
@@ -83,7 +77,7 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
m_options->persistenceManager->Save();
}
led_strip_update(value == 0 ? LED_STATE_DAY : LED_STATE_NIGHT, rgb_t{});
start_simulation();
}
break;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include <sys/cdefs.h>
typedef struct
{
@@ -16,7 +17,9 @@ typedef struct
uint8_t v;
} hsv_t;
__BEGIN_DECLS
rgb_t interpolate_color_rgb(rgb_t start, rgb_t end, float factor);
rgb_t interpolate_color_hsv(rgb_t start, rgb_t end, float factor);
hsv_t rgb_to_hsv(rgb_t rgb);
rgb_t hsv_to_rgb(hsv_t hsv);
__END_DECLS

View File

@@ -88,6 +88,8 @@ esp_err_t led_strip_init(void)
return ESP_FAIL;
}
set_all_pixels((rgb_t){.red = 0, .green = 0, .blue = 0});
xTaskCreate(led_strip_task, "led_strip_task", 4096, NULL, tskIDLE_PRIORITY + 1, NULL);
ESP_LOGI(TAG, "LED strip initialized");

View File

@@ -1,63 +0,0 @@
#pragma once
#include "../IPersistenceManager.h"
#include <SDL3/SDL.h>
#include <unordered_map>
#include <variant>
class PersistenceManager final : public IPersistenceManager {
public:
using ValueType = std::variant<
bool,
int,
float,
double,
std::string
>;
private:
std::unordered_map<std::string, ValueType> m_data;
std::string m_filename;
public:
explicit PersistenceManager(std::string filename = "settings.dat");
~PersistenceManager() override;
[[nodiscard]] bool HasKey(const std::string& key) const override;
void RemoveKey(const std::string& key) override;
void Clear() override;
[[nodiscard]] size_t GetKeyCount() const override { return m_data.size(); }
bool Save() override;
bool Load() override;
bool SaveToFile(const std::string& filename);
bool LoadFromFile(const std::string& filename);
protected:
void SetValueImpl(const std::string& key, bool value) override;
void SetValueImpl(const std::string& key, int value) override;
void SetValueImpl(const std::string& key, float value) override;
void SetValueImpl(const std::string& key, double value) override;
void SetValueImpl(const std::string& key, const std::string& value) override;
[[nodiscard]] bool GetValueImpl(const std::string& key, bool defaultValue) const override;
[[nodiscard]] int GetValueImpl(const std::string& key, int defaultValue) const override;
[[nodiscard]] float GetValueImpl(const std::string& key, float defaultValue) const override;
[[nodiscard]] double GetValueImpl(const std::string& key, double defaultValue) const override;
[[nodiscard]] std::string GetValueImpl(const std::string& key, const std::string& defaultValue) const override;
private:
static bool WriteValueToStream(SDL_IOStream* stream, const ValueType& value) ;
static bool ReadValueFromStream(SDL_IOStream* stream, ValueType& value) ;
enum class TypeId : uint8_t {
BOOL = 0,
INT = 1,
FLOAT = 2,
DOUBLE = 3,
STRING = 4
};
static TypeId GetTypeId(const ValueType& value);
};

View File

@@ -1,8 +1,9 @@
idf_component_register(SRCS
"src/simulator.c"
"src/storage.c"
"src/simulator.cpp"
"src/storage.cpp"
INCLUDE_DIRS "include"
PRIV_REQUIRES
led-manager
persistence-manager
spiffs
)

View File

@@ -9,13 +9,12 @@ typedef struct
int cycle_duration_minutes;
} simulation_config_t;
__BEGIN_DECLS
char *get_time(void);
esp_err_t add_light_item(const char time[5], uint8_t red, uint8_t green, uint8_t blue, uint8_t white,
uint8_t brightness, uint8_t saturation);
void cleanup_light_items(void);
void start_simulate_day(void);
void start_simulate_night(void);
void start_simulation_task(void);
__END_DECLS
void stop_simulation_task(void);
void start_simulation(void);

View File

@@ -1,5 +1,4 @@
#pragma once
void initialize_storage();
void load_file(const char *filename);

View File

@@ -1,6 +1,7 @@
#include "simulator.h"
#include "color.h"
#include "hal_esp32/PersistenceManager.h"
#include "led_strip_ws2812.h"
#include "storage.h"
#include <esp_heap_caps.h>
@@ -332,11 +333,7 @@ void simulate_cycle(void *args)
void start_simulation_task(void)
{
if (simulation_task_handle != NULL)
{
vTaskDelete(simulation_task_handle);
simulation_task_handle = NULL;
}
stop_simulation_task();
simulation_config_t *config =
(simulation_config_t *)heap_caps_malloc(sizeof(simulation_config_t), MALLOC_CAP_SPIRAM);
@@ -355,3 +352,46 @@ void start_simulation_task(void)
heap_caps_free(config);
}
}
void stop_simulation_task(void)
{
if (simulation_task_handle != NULL)
{
vTaskDelete(simulation_task_handle);
simulation_task_handle = NULL;
}
};
void start_simulation(void)
{
stop_simulation_task();
auto persistence = PersistenceManager();
if (persistence.GetValue("light_active", false))
{
int mode = persistence.GetValue("light_mode", 0);
switch (mode)
{
case 0: // Simulation mode
start_simulation_task();
break;
case 1: // Day mode
start_simulate_day();
break;
case 2: // Night mode
start_simulate_night();
break;
default:
ESP_LOGW(TAG, "Unknown light mode: %d", mode);
break;
}
}
else
{
led_strip_update(LED_STATE_OFF, rgb_t{});
}
}

View File

@@ -3,20 +3,22 @@
#include "analytics.h"
#include "button_handling.h"
#include "common/InactivityTracker.h"
#include "driver/i2c.h"
#include "esp_diagnostics.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "hal/u8g2_esp32_hal.h"
#include "hal_esp32/PersistenceManager.h"
#include "i2c_checker.h"
#include "led_status.h"
#include "sdkconfig.h"
#include "u8g2.h"
#include "simulator.h"
#include "ui/ClockScreenSaver.h"
#include "ui/ScreenSaver.h"
#include "ui/SplashScreen.h"
#include "wifi_manager.h"
#include <driver/i2c.h>
#include <esp_diagnostics.h>
#include <esp_log.h>
#include <esp_task_wdt.h>
#include <esp_timer.h>
#include <sdkconfig.h>
#include <u8g2.h>
#define PIN_RST GPIO_NUM_NC
@@ -47,9 +49,13 @@ static void setup_screen(void)
ESP_DIAG_EVENT(TAG, "u8g2_InitDisplay");
u8g2_InitDisplay(&u8g2);
vTaskDelay(pdMS_TO_TICKS(10));
ESP_DIAG_EVENT(TAG, "u8g2_SetPowerSave");
u8g2_SetPowerSave(&u8g2, 0);
vTaskDelay(pdMS_TO_TICKS(10));
u8g2_ClearDisplay(&u8g2);
}
void setScreen(const std::shared_ptr<Widget> &screen)
@@ -158,6 +164,8 @@ static void handle_button(uint8_t button)
void app_task(void *args)
{
esp_task_wdt_add(NULL);
if (i2c_bus_scan_and_check() != ESP_OK)
{
led_behavior_t led0_behavior = {.mode = LED_MODE_BLINK,
@@ -180,10 +188,14 @@ void app_task(void *args)
analytics_init();
#endif
start_simulation();
auto oldTime = esp_timer_get_time();
while (true)
{
esp_task_wdt_reset();
u8g2_ClearBuffer(&u8g2);
if (m_widget != nullptr)

View File

@@ -3,7 +3,6 @@
#include "hal_esp32/PersistenceManager.h"
#include "led_status.h"
#include "led_strip_ws2812.h"
#include "simulator.h"
#include "wifi_manager.h"
#include <ble_manager.h>
#include <esp_event.h>
@@ -31,15 +30,9 @@ void app_main(void)
led_status_init(CONFIG_STATUS_WLED_PIN);
led_strip_init();
start_simulation_task();
xTaskCreatePinnedToCore(app_task, "app_task", 4096, NULL, tskIDLE_PRIORITY + 1, NULL, portNUM_PROCESSORS - 1);
xTaskCreatePinnedToCore(app_task, "app_task", 8192, NULL, tskIDLE_PRIORITY + 1, NULL, portNUM_PROCESSORS - 1);
// xTaskCreatePinnedToCore(ble_manager_task, "ble_manager", 4096, NULL, tskIDLE_PRIORITY + 1, NULL,
// portNUM_PROCESSORS - 1);
if (persistence.GetValue("light_active", false))
{
led_strip_update(LED_STATE_DAY, rgb_t{});
}
}
__END_DECLS