implement new light mode (off/day/night/simulation)

missing:
- fully connect it to the ui
- setup duration in light settings

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-09-29 23:15:06 +02:00
parent dc66484f5e
commit 08b0e04584
50 changed files with 14880 additions and 8787 deletions

View File

@@ -1,101 +0,0 @@
#include "common/ColorSettingsMenu.h"
#include "led_manager.h"
namespace ColorSettingsMenuItem
{
constexpr auto RED = 0;
constexpr auto GREEN = 1;
constexpr auto BLUE = 2;
} // namespace ColorSettingsMenuItem
ColorSettingsMenu::ColorSettingsMenu(menu_options_t *options, std::string suffix)
: Menu(options), m_suffix(std::move(suffix)), m_options(options)
{
std::vector<std::string> values;
for (size_t i = 0; i <= 254; i++)
{
values.emplace_back(std::to_string(i));
}
int red_value = 0;
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::RED + m_suffix;
red_value = m_options->persistenceManager->GetValue(key, red_value);
}
addSelection(ColorSettingsMenuItem::RED, "Rot", values, red_value);
int green_value = 0;
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::GREEN + m_suffix;
green_value = m_options->persistenceManager->GetValue(key, green_value);
}
addSelection(ColorSettingsMenuItem::GREEN, "Gruen", values, green_value);
int blue_value = 0;
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::BLUE + m_suffix;
blue_value = m_options->persistenceManager->GetValue(key, blue_value);
}
addSelection(ColorSettingsMenuItem::BLUE, "Blau", values, blue_value);
}
void ColorSettingsMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType button)
{
switch (menuItem.getId())
{
case ColorSettingsMenuItem::RED:
if (button == ButtonType::LEFT || button == ButtonType::RIGHT)
{
const auto item = switchValue(menuItem, button);
const auto value = getItem(item.getId()).getIndex();
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::RED + m_suffix;
m_options->persistenceManager->SetValue(key, value);
}
}
break;
case ColorSettingsMenuItem::GREEN:
if (button == ButtonType::LEFT || button == ButtonType::RIGHT)
{
const auto item = switchValue(menuItem, button);
const auto value = getItem(item.getId()).getIndex();
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::GREEN + m_suffix;
m_options->persistenceManager->SetValue(key, value);
}
}
break;
case ColorSettingsMenuItem::BLUE:
if (button == ButtonType::LEFT || button == ButtonType::RIGHT)
{
const auto item = switchValue(menuItem, button);
const auto value = getItem(item.getId()).getIndex();
if (m_options && m_options->persistenceManager)
{
std::string key = ColorSettingsMenuOptions::BLUE + m_suffix;
m_options->persistenceManager->SetValue(key, value);
}
}
break;
}
}
void ColorSettingsMenu::onExit()
{
if (m_options && m_options->persistenceManager)
{
m_options->persistenceManager->Save();
led_event_data_t payload = {.value = 42};
send_event(EVENT_LED_REFRESH, &payload);
}
}

View File

@@ -29,7 +29,7 @@ constexpr int BOTTOM_OFFSET = 10;
Menu::Menu(menu_options_t *options) : Widget(options->u8g2), m_options(options)
{
// Set up button callback using lambda to forward to member function
m_options->onButtonClicked = [this](const ButtonType button) { onButtonClicked(button); };
m_options->onButtonClicked = [this](const ButtonType button) { OnButtonClicked(button); };
}
Menu::~Menu()
@@ -126,7 +126,7 @@ MenuItem Menu::replaceItem(const int index, const MenuItem &item)
return item;
}
void Menu::render()
void Menu::Render()
{
// Initialize selection if not set
if (m_selected_item >= m_items.size() && !m_items.empty())
@@ -232,7 +232,7 @@ void Menu::renderWidget(const MenuItem *item, const uint8_t *font, const int x,
}
}
void Menu::onButtonClicked(const ButtonType button)
void Menu::OnButtonClicked(const ButtonType button)
{
// Map button input to navigation functions
switch (button)
@@ -362,7 +362,7 @@ void Menu::drawScrollBar() const
// Create scrollbar instance
ScrollBar scrollBar(m_options, u8g2->width - UIConstants::SCROLLBAR_WIDTH, 3, 1, u8g2->height - 6);
scrollBar.refresh(m_selected_item, m_items.size());
scrollBar.render();
scrollBar.Render();
}
void Menu::drawSelectionBox() const

View File

@@ -7,7 +7,7 @@ ScrollBar::ScrollBar(const menu_options_t *options, const size_t x, const size_t
{
}
void ScrollBar::render()
void ScrollBar::Render()
{
if (m_max <= 1)
{

View File

@@ -20,14 +20,14 @@ void Widget::onExit()
{
}
void Widget::update(uint64_t dt)
void Widget::Update(uint64_t dt)
{
}
void Widget::render()
void Widget::Render()
{
}
void Widget::onButtonClicked(ButtonType button)
void Widget::OnButtonClicked(ButtonType button)
{
}

View File

@@ -1,4 +1,5 @@
#include "ui/ClockScreenSaver.h"
#include "simulator.h"
#include <cstring>
#include <ctime>
@@ -36,17 +37,25 @@ void ClockScreenSaver::updateTextDimensions()
void ClockScreenSaver::getCurrentTimeString(char *buffer, size_t bufferSize) const
{
time_t rawtime;
struct tm *timeinfo;
char *simulated_time = get_time();
if (simulated_time != nullptr)
{
strncpy(buffer, simulated_time, bufferSize);
}
else
{
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)
void ClockScreenSaver::Update(const uint64_t dt)
{
m_moveTimer += dt;
@@ -94,7 +103,7 @@ void ClockScreenSaver::checkBoundaryCollision()
}
}
void ClockScreenSaver::render()
void ClockScreenSaver::Render()
{
// Clear screen with a black background
u8g2_SetDrawColor(u8g2, 0);
@@ -112,7 +121,7 @@ void ClockScreenSaver::render()
u8g2_DrawStr(u8g2, m_posX, m_posY, timeBuffer);
}
void ClockScreenSaver::onButtonClicked(ButtonType button)
void ClockScreenSaver::OnButtonClicked(ButtonType button)
{
// Exit screensaver on any button press
if (m_options && m_options->popScreen)

View File

@@ -1,5 +0,0 @@
#include "ui/DayColorSettingsMenu.h"
DayColorSettingsMenu::DayColorSettingsMenu(menu_options_t *options) : ColorSettingsMenu(options, "day")
{
}

View File

@@ -1,7 +1,6 @@
#include "ui/LightMenu.h"
#include "led_manager.h"
#include "ui/LightSettingsMenu.h"
#include "led_strip_ws2812.h"
/**
* @namespace LightMenuItem
@@ -9,9 +8,8 @@
*/
namespace LightMenuItem
{
constexpr auto ACTIVATE = 0; ///< ID for the light activation toggle
constexpr auto MODE = 1; ///< ID for the light mode selection
constexpr auto LED_SETTINGS = 2; ///< ID for the LED settings menu item
constexpr auto ACTIVATE = 0; ///< ID for the light activation toggle
constexpr auto MODE = 1; ///< ID for the light mode selection
} // namespace LightMenuItem
namespace LightMenuOptions
@@ -30,19 +28,17 @@ LightMenu::LightMenu(menu_options_t *options) : Menu(options), m_options(options
}
addToggle(LightMenuItem::ACTIVATE, "Einschalten", active);
// Create mode selection options (Day/Night modes)
std::vector<std::string> values;
values.emplace_back("Tag"); // Day mode
values.emplace_back("Nacht"); // Night mode
// Create mode selection options (Simulation/Day/Night modes)
std::vector<std::string> items;
items.emplace_back("Simulation"); // Simulation mode
items.emplace_back("Tag"); // Day mode
items.emplace_back("Nacht"); // Night mode
int mode_value = 0;
if (m_options && m_options->persistenceManager)
{
mode_value = m_options->persistenceManager->GetValue(LightMenuOptions::LIGHT_MODE, mode_value);
}
addSelection(LightMenuItem::MODE, "Modus", values, mode_value);
// Add menu item for accessing LED settings submenu
addText(LightMenuItem::LED_SETTINGS, "Einstellungen");
addSelection(LightMenuItem::MODE, "Modus", items, mode_value);
}
void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType button)
@@ -58,14 +54,13 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
{
toggle(menuItem);
const auto value = getItem(menuItem.getId()).getValue() == "1";
led_event_data_t payload = {.value = 42};
if (value)
{
send_event(EVENT_LED_ON, &payload);
led_strip_update(LED_STATE_DAY, rgb_t{});
}
else
{
send_event(EVENT_LED_OFF, &payload);
led_strip_update(LED_STATE_OFF, rgb_t{});
}
if (m_options && m_options->persistenceManager)
@@ -88,17 +83,7 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
m_options->persistenceManager->Save();
}
led_event_data_t payload = {.value = value};
send_event(EVENT_LED_DAY + value, &payload);
}
break;
}
case LightMenuItem::LED_SETTINGS: {
// Open the LED settings submenu when SELECT is pressed
if (button == ButtonType::SELECT)
{
widget = std::make_shared<LightSettingsMenu>(m_options);
led_strip_update(value == 0 ? LED_STATE_DAY : LED_STATE_NIGHT, rgb_t{});
}
break;
}
@@ -113,4 +98,4 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
{
m_options->pushScreen(widget);
}
}
}

View File

@@ -1,102 +0,0 @@
#include "ui/LightSettingsMenu.h"
#include "common/Common.h"
#include "ui/DayColorSettingsMenu.h"
#include "ui/NightColorSettingsMenu.h"
/**
* @namespace LightSettingsMenuItem
* @brief Constants for light settings menu item identifiers
*/
namespace LightSettingsMenuItem
{
constexpr uint8_t RGB_SETTING_DAY = 0;
constexpr uint8_t RGB_SETTING_NIGHT = 1;
constexpr uint8_t SECTION_COUNTER = 2;
} // namespace LightSettingsMenuItem
std::string LightSettingsMenu::CreateKey(const int index)
{
constexpr int key_length = 20;
char key[key_length] = "";
snprintf(key, key_length, "section_%d", index);
return key;
}
LightSettingsMenu::LightSettingsMenu(menu_options_t *options) : Menu(options), m_options(options)
{
addText(LightSettingsMenuItem::RGB_SETTING_DAY, "Tag (Farbe)");
addText(LightSettingsMenuItem::RGB_SETTING_NIGHT, "Nacht (Farbe)");
/*
// Create values vector for section counts (1-99)
std::vector<std::string> values;
for (size_t i = 1; i <= 99; i++)
{
values.emplace_back(std::to_string(i));
}
// Add section counter selection (allows choosing number of sections)
auto value = 7;
if (m_options && m_options->persistenceManager)
{
value = m_options->persistenceManager->GetValue(CreateKey(0), value);
}
addSelection(LightSettingsMenuItem::SECTION_COUNTER, "Sektionen", values, value);
setItemSize(std::stoull(getItem(LightSettingsMenuItem::SECTION_COUNTER).getValue()),
LightSettingsMenuItem::SECTION_COUNTER);
*/
}
void LightSettingsMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType button)
{
std::shared_ptr<Widget> widget;
switch (button)
{
case ButtonType::SELECT:
switch (menuItem.getId())
{
case LightSettingsMenuItem::RGB_SETTING_DAY:
widget = std::make_shared<DayColorSettingsMenu>(m_options);
break;
case LightSettingsMenuItem::RGB_SETTING_NIGHT:
widget = std::make_shared<NightColorSettingsMenu>(m_options);
break;
default:
break;
}
if (m_options && m_options->pushScreen)
{
m_options->pushScreen(widget);
}
break;
case ButtonType::RIGHT:
case ButtonType::LEFT:
// Handle value switching for the current menu item
switchValue(menuItem, button);
// Update the section list size based on the section counter value
if (menuItem.getId() == LightSettingsMenuItem::SECTION_COUNTER)
{
setItemSize(std::stoull(getItem(LightSettingsMenuItem::SECTION_COUNTER).getValue()),
LightSettingsMenuItem::SECTION_COUNTER);
}
// Persist the changed section values if persistence is available
if (m_options && m_options->persistenceManager)
{
const auto value = getItem(menuItem.getId()).getIndex();
m_options->persistenceManager->SetValue(CreateKey(menuItem.getId()), value);
}
break;
default:
break;
}
}

View File

@@ -1,5 +0,0 @@
#include "ui/NightColorSettingsMenu.h"
NightColorSettingsMenu::NightColorSettingsMenu(menu_options_t *options) : ColorSettingsMenu(options, "night")
{
}

View File

@@ -20,7 +20,7 @@ void ScreenSaver::initVehicles()
}
}
void ScreenSaver::update(const uint64_t dt)
void ScreenSaver::Update(const uint64_t dt)
{
m_animationCounter += dt;
m_lastSpawnTime += dt;
@@ -214,7 +214,7 @@ ScreenSaver::Direction ScreenSaver::getRandomDirection()
return (random() % 2 == 0) ? Direction::LEFT : Direction::RIGHT;
}
void ScreenSaver::render()
void ScreenSaver::Render()
{
// Clear screen with a black background
u8g2_SetDrawColor(u8g2, 0);
@@ -320,7 +320,7 @@ const unsigned char *ScreenSaver::getVehicleBitmap(const VehicleType type, const
}
}
void ScreenSaver::onButtonClicked(ButtonType button)
void ScreenSaver::OnButtonClicked(ButtonType button)
{
if (m_options && m_options->popScreen)
{

View File

@@ -8,7 +8,7 @@ SplashScreen::SplashScreen(menu_options_t *options) : Widget(options->u8g2), m_o
{
}
void SplashScreen::update(const uint64_t dt)
void SplashScreen::Update(const uint64_t dt)
{
splashTime += dt;
if (splashTime > 100)
@@ -20,7 +20,7 @@ void SplashScreen::update(const uint64_t dt)
}
}
void SplashScreen::render()
void SplashScreen::Render()
{
u8g2_SetFont(u8g2, u8g2_font_DigitalDisco_tr);
u8g2_DrawStr(u8g2, 28, u8g2->height / 2 - 10, "HO Anlage");