Merge remote-tracking branch 'upstream/abstraction' into UIRefactor

This commit is contained in:
MatthewColvin 2023-09-17 19:45:03 -05:00
commit f5b7b7bc5f
8 changed files with 435 additions and 293 deletions

View file

@ -25,6 +25,15 @@ public:
virtual std::shared_ptr<DisplayAbstract> display() = 0; virtual std::shared_ptr<DisplayAbstract> display() = 0;
virtual std::shared_ptr<wifiHandlerInterface> wifi() = 0; virtual std::shared_ptr<wifiHandlerInterface> wifi() = 0;
virtual char getCurrentDevice() = 0;
virtual void setCurrentDevice(char currentDevice) = 0;
virtual bool getWakeupByIMUEnabled() = 0;
virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) = 0;
virtual uint16_t getSleepTimeout() = 0;
virtual void setSleepTimeout(uint16_t sleepTimeout) = 0;
protected: protected:
}; };

View file

@ -50,9 +50,7 @@ void HardwareRevX::initIO() {
gpio_deep_sleep_hold_dis(); gpio_deep_sleep_hold_dis();
} }
HardwareRevX::HardwareRevX(): HardwareRevX::HardwareRevX() : HardwareAbstract() {}
HardwareAbstract(){
}
HardwareRevX::WakeReason getWakeReason() { HardwareRevX::WakeReason getWakeReason() {
// Find out wakeup cause // Find out wakeup cause
@ -74,11 +72,13 @@ void HardwareRevX::init() {
Serial.begin(115200); Serial.begin(115200);
mDisplay = Display::getInstance(); mDisplay = Display::getInstance();
mBattery = std::make_shared<Battery>(ADC_BAT,CRG_STAT); mBattery = std::make_shared<Battery>(ADC_BAT, CRG_STAT);
mWifiHandler = wifiHandler::getInstance(); mWifiHandler = wifiHandler::getInstance();
restorePreferences(); restorePreferences();
mDisplay->onTouch([this]([[maybe_unused]] auto touchPoint){ standbyTimer = SLEEP_TIMEOUT;}); mDisplay->onTouch([this]([[maybe_unused]] auto touchPoint) {
standbyTimer = this->getSleepTimeout();
});
setupIMU(); setupIMU();
setupIR(); setupIR();
@ -86,37 +86,31 @@ void HardwareRevX::init() {
debugPrint("Finished Hardware Setup in %d", millis()); debugPrint("Finished Hardware Setup in %d", millis());
} }
void HardwareRevX::debugPrint(const char* fmt, ...) void HardwareRevX::debugPrint(const char *fmt, ...) {
{
char result[100]; char result[100];
va_list arguments; va_list arguments;
va_start(arguments, fmt); va_start(arguments, fmt);
vsnprintf(result, 100, fmt, arguments); vsnprintf(result, 100, fmt, arguments);
va_end (arguments); va_end(arguments);
Serial.print(result); Serial.print(result);
} }
std::shared_ptr<HardwareRevX> HardwareRevX::getInstance(){ std::shared_ptr<HardwareRevX> HardwareRevX::getInstance() {
if (!mInstance) { if (!mInstance) {
mInstance = std::shared_ptr<HardwareRevX>(new HardwareRevX()); mInstance = std::shared_ptr<HardwareRevX>(new HardwareRevX());
} }
return mInstance; return mInstance;
} }
std::shared_ptr<wifiHandlerInterface> HardwareRevX::wifi() std::shared_ptr<wifiHandlerInterface> HardwareRevX::wifi() {
{
return mWifiHandler; return mWifiHandler;
} }
std::shared_ptr<BatteryInterface> HardwareRevX::battery(){ std::shared_ptr<BatteryInterface> HardwareRevX::battery() { return mBattery; }
return mBattery;
}
std::shared_ptr<DisplayAbstract> HardwareRevX::display(){ std::shared_ptr<DisplayAbstract> HardwareRevX::display() { return mDisplay; }
return mDisplay;
}
void HardwareRevX::activityDetection() { void HardwareRevX::activityDetection() {
static int accXold; static int accXold;
@ -134,7 +128,7 @@ void HardwareRevX::activityDetection() {
standbyTimer = 0; standbyTimer = 0;
// If the motion exceeds the threshold, the standbyTimer is reset // If the motion exceeds the threshold, the standbyTimer is reset
if (motion > MOTION_THRESHOLD) if (motion > MOTION_THRESHOLD)
standbyTimer = SLEEP_TIMEOUT; standbyTimer = sleepTimeout;
// Store the current acceleration and time // Store the current acceleration and time
accXold = accX; accXold = accX;
@ -142,11 +136,31 @@ void HardwareRevX::activityDetection() {
accZold = accZ; accZold = accZ;
} }
char HardwareRevX::getCurrentDevice() { return currentDevice; }
void HardwareRevX::setCurrentDevice(char currentDevice) {
this->currentDevice = currentDevice;
}
bool HardwareRevX::getWakeupByIMUEnabled() { return wakeupByIMUEnabled; }
void HardwareRevX::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) {
this->wakeupByIMUEnabled = wakeupByIMUEnabled;
}
uint16_t HardwareRevX::getSleepTimeout() { return sleepTimeout; }
void HardwareRevX::setSleepTimeout(uint16_t sleepTimeout) {
this->sleepTimeout = sleepTimeout;
standbyTimer = sleepTimeout;
}
void HardwareRevX::enterSleep() { void HardwareRevX::enterSleep() {
// Save settings to internal flash memory // Save settings to internal flash memory
preferences.putBool("wkpByIMU", wakeupByIMUEnabled); preferences.putBool("wkpByIMU", wakeupByIMUEnabled);
preferences.putUChar("blBrightness", mDisplay->getBrightness()); preferences.putUChar("blBrightness", mDisplay->getBrightness());
preferences.putUChar("currentDevice", currentDevice); preferences.putUChar("currentDevice", currentDevice);
preferences.putUInt("sleepTimeout", sleepTimeout);
if (!preferences.getBool("alreadySetUp")) if (!preferences.getBool("alreadySetUp"))
preferences.putBool("alreadySetUp", true); preferences.putBool("alreadySetUp", true);
preferences.end(); preferences.end();
@ -259,6 +273,11 @@ void HardwareRevX::restorePreferences() {
wakeupByIMUEnabled = preferences.getBool("wkpByIMU"); wakeupByIMUEnabled = preferences.getBool("wkpByIMU");
backlight_brightness = preferences.getUChar("blBrightness"); backlight_brightness = preferences.getUChar("blBrightness");
currentDevice = preferences.getUChar("currentDevice"); currentDevice = preferences.getUChar("currentDevice");
sleepTimeout = preferences.getUInt("sleepTimeout");
// setting the default to prevent a 0ms sleep timeout
if (sleepTimeout == 0) {
sleepTimeout = SLEEP_TIMEOUT;
}
} }
mDisplay->setBrightness(backlight_brightness); mDisplay->setBrightness(backlight_brightness);
} }
@ -312,7 +331,7 @@ void HardwareRevX::loopHandler() {
if (customKeypad.key[i].kstate == PRESSED || if (customKeypad.key[i].kstate == PRESSED ||
customKeypad.key[i].kstate == HOLD) { customKeypad.key[i].kstate == HOLD) {
standbyTimer = standbyTimer =
SLEEP_TIMEOUT; // Reset the sleep timer when a button is pressed sleepTimeout; // Reset the sleep timer when a button is pressed
int keyCode = customKeypad.key[i].kcode; int keyCode = customKeypad.key[i].kcode;
Serial.println(customKeypad.key[i].kchar); Serial.println(customKeypad.key[i].kchar);
// Send IR codes depending on the current device (tabview page) // Send IR codes depending on the current device (tabview page)

View file

@ -2,8 +2,9 @@
#include "SparkFunLIS3DH.h" #include "SparkFunLIS3DH.h"
#include "HardwareAbstract.hpp" #include "HardwareAbstract.hpp"
#include "lvgl.h"
#include "battery.hpp" #include "battery.hpp"
#include "lvgl.h"
#include "wifihandler.hpp"
#include <IRrecv.h> #include <IRrecv.h>
#include <IRremoteESP8266.h> #include <IRremoteESP8266.h>
#include <IRsend.h> #include <IRsend.h>
@ -13,14 +14,11 @@
#include <PubSubClient.h> #include <PubSubClient.h>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "wifihandler.hpp"
#include "omoteconfig.h"
#include "BatteryInterface.h" #include "BatteryInterface.h"
#include "wifiHandlerInterface.h"
#include "display.hpp" #include "display.hpp"
#include "omoteconfig.h"
#include "wifiHandlerInterface.h"
class HardwareRevX : public HardwareAbstract { class HardwareRevX : public HardwareAbstract {
public: public:
@ -31,15 +29,25 @@ public:
// HardwareAbstract // HardwareAbstract
virtual void init() override; virtual void init() override;
virtual void debugPrint(const char* fmt, ...) override; virtual void debugPrint(const char *fmt, ...) override;
virtual std::shared_ptr<BatteryInterface> battery() override; virtual std::shared_ptr<BatteryInterface> battery() override;
virtual std::shared_ptr<DisplayAbstract> display() override; virtual std::shared_ptr<DisplayAbstract> display() override;
virtual std::shared_ptr<wifiHandlerInterface> wifi() override; virtual std::shared_ptr<wifiHandlerInterface> wifi() override;
virtual char getCurrentDevice() override;
virtual void setCurrentDevice(char currentDevice) override;
virtual bool getWakeupByIMUEnabled() override;
virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override;
virtual uint16_t getSleepTimeout() override;
virtual void setSleepTimeout(uint16_t sleepTimeout) override;
/// @brief To be ran in loop out in main /// @brief To be ran in loop out in main
// TODO move to a freertos task // TODO move to a freertos task
void loopHandler(); void loopHandler();
protected: protected:
// Init Functions to setup hardware // Init Functions to setup hardware
void initIO(); void initIO();
@ -64,6 +72,7 @@ private:
// IMU Motion Detection // IMU Motion Detection
LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19. LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
int standbyTimer = SLEEP_TIMEOUT; int standbyTimer = SLEEP_TIMEOUT;
int sleepTimeout = SLEEP_TIMEOUT;
int motion = 0; int motion = 0;
WakeReason wakeup_reason; WakeReason wakeup_reason;
@ -76,7 +85,6 @@ private:
IRsend IrSender = IRsend(IR_LED, true); IRsend IrSender = IRsend(IR_LED, true);
IRrecv IrReceiver = IRrecv(IR_RX); IRrecv IrReceiver = IRrecv(IR_RX);
// Keypad declarations // Keypad declarations
static const byte ROWS = 5; // four rows static const byte ROWS = 5; // four rows
static const byte COLS = 5; // four columns static const byte COLS = 5; // four columns

View file

@ -3,27 +3,27 @@
#include "SDLDisplay.hpp" #include "SDLDisplay.hpp"
#include <sstream> #include <sstream>
HardwareSimulator::HardwareSimulator(): HardwareAbstract(), HardwareSimulator::HardwareSimulator()
mTickThread([](){ : HardwareAbstract(), mTickThread([]() {
while(true){ while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(2)); std::this_thread::sleep_for(std::chrono::milliseconds(2));
lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/ lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/
}}), }
}),
mBattery(std::make_shared<BatterySimulator>()), mBattery(std::make_shared<BatterySimulator>()),
mDisplay(SDLDisplay::getInstance()), mDisplay(SDLDisplay::getInstance()),
mWifiHandler(std::make_shared<wifiHandlerSim>()) mWifiHandler(std::make_shared<wifiHandlerSim>()) {
{
mHardwareStatusTitleUpdate = std::thread([this] { mHardwareStatusTitleUpdate = std::thread([this] {
int dataToShow = 0; int dataToShow = 0;
while (true) while (true) {
{
std::stringstream title; std::stringstream title;
switch (dataToShow){ switch (dataToShow) {
case 0: case 0:
title << "Batt:" << mBattery->getPercentage() << "%" << std::endl; title << "Batt:" << mBattery->getPercentage() << "%" << std::endl;
break; break;
case 1: case 1:
title << "BKLght: " << static_cast<int>(mDisplay->getBrightness()) << std::endl; title << "BKLght: " << static_cast<int>(mDisplay->getBrightness())
<< std::endl;
dataToShow = -1; dataToShow = -1;
break; break;
default: default:
@ -37,12 +37,24 @@ HardwareSimulator::HardwareSimulator(): HardwareAbstract(),
}); });
} }
std::shared_ptr<BatteryInterface> HardwareSimulator::battery(){ std::shared_ptr<BatteryInterface> HardwareSimulator::battery() {
return mBattery; return mBattery;
} }
std::shared_ptr<DisplayAbstract> HardwareSimulator::display(){ std::shared_ptr<DisplayAbstract> HardwareSimulator::display() {
return mDisplay; return mDisplay;
} }
std::shared_ptr<wifiHandlerInterface> HardwareSimulator::wifi(){ std::shared_ptr<wifiHandlerInterface> HardwareSimulator::wifi() {
return mWifiHandler; return mWifiHandler;
} }
char HardwareSimulator::getCurrentDevice() { return 0; }
void HardwareSimulator::setCurrentDevice(char currentDevice) {}
bool HardwareSimulator::getWakeupByIMUEnabled() { return true; }
void HardwareSimulator::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) {}
uint16_t HardwareSimulator::getSleepTimeout() { return 20000; }
void HardwareSimulator::setSleepTimeout(uint16_t sleepTimeout) {}

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "HardwareAbstract.hpp" #include "HardwareAbstract.hpp"
#include "batterySimulator.hpp"
#include "SDLDisplay.hpp" #include "SDLDisplay.hpp"
#include "batterySimulator.hpp"
#include "wifiHandlerSim.hpp" #include "wifiHandlerSim.hpp"
#include <thread> #include <thread>
@ -11,9 +11,9 @@ class HardwareSimulator : public HardwareAbstract {
public: public:
HardwareSimulator(); HardwareSimulator();
virtual void init() override {}; virtual void init() override{};
virtual void debugPrint(const char* fmt, ...) override { virtual void debugPrint(const char *fmt, ...) override {
va_list arguments; va_list arguments;
va_start(arguments, fmt); va_start(arguments, fmt);
vprintf(fmt, arguments); vprintf(fmt, arguments);
@ -24,6 +24,15 @@ public:
virtual std::shared_ptr<DisplayAbstract> display() override; virtual std::shared_ptr<DisplayAbstract> display() override;
virtual std::shared_ptr<wifiHandlerInterface> wifi() override; virtual std::shared_ptr<wifiHandlerInterface> wifi() override;
virtual char getCurrentDevice() override;
virtual void setCurrentDevice(char currentDevice) override;
virtual bool getWakeupByIMUEnabled() override;
virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override;
virtual uint16_t getSleepTimeout() override;
virtual void setSleepTimeout(uint16_t sleepTimeout) override;
private: private:
std::thread mTickThread; std::thread mTickThread;
std::thread mHardwareStatusTitleUpdate; std::thread mHardwareStatusTitleUpdate;

View file

@ -11,7 +11,8 @@ std::shared_ptr<OmoteUI> OmoteUI::mInstance = nullptr;
// #if defined(IS_SIMULATOR) && (IS_SIMULATOR == true) // #if defined(IS_SIMULATOR) && (IS_SIMULATOR == true)
// #endif // #endif
OmoteUI::OmoteUI(std::shared_ptr<HardwareAbstract> aHardware) : UIBase(aHardware){} OmoteUI::OmoteUI(std::shared_ptr<HardwareAbstract> aHardware)
: UIBase(aHardware) {}
// Set the page indicator scroll position relative to the tabview scroll // Set the page indicator scroll position relative to the tabview scroll
// position // position
@ -26,6 +27,7 @@ void OmoteUI::store_scroll_value_event_cb(lv_event_t *e) {
// Update current device when the tabview page is changes // Update current device when the tabview page is changes
void OmoteUI::tabview_device_event_cb(lv_event_t *e) { void OmoteUI::tabview_device_event_cb(lv_event_t *e) {
currentDevice = lv_tabview_get_tab_act(lv_event_get_target(e)); currentDevice = lv_tabview_get_tab_act(lv_event_get_target(e));
this->mHardware->setCurrentDevice(currentDevice);
} }
// Slider Event handler // Slider Event handler
@ -38,13 +40,21 @@ void OmoteUI::bl_slider_event_cb(lv_event_t *e) {
// Apple Key Event handler // Apple Key Event handler
void OmoteUI::appleKey_event_cb(lv_event_t *e) { void OmoteUI::appleKey_event_cb(lv_event_t *e) {
// Send IR command based on the event user data // Send IR command based on the event user data
//mHardware->debugPrint(std::to_string(50 + (int)e->user_data)); // mHardware->debugPrint(std::to_string(50 + (int)e->user_data));
} }
// Wakeup by IMU Switch Event handler // Wakeup by IMU Switch Event handler
void OmoteUI::WakeEnableSetting_event_cb(lv_event_t *e) { void OmoteUI::WakeEnableSetting_event_cb(lv_event_t *e) {
wakeupByIMUEnabled = this->mHardware->setWakeupByIMUEnabled(
lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED));
}
// Wakeup timeout dropdown Event handler
void OmoteUI::wakeTimeoutSetting_event_cb(lv_event_t *e) {
lv_obj_t *drop = lv_event_get_target(e);
int sleepTimeout = sleepTimeoutMap[lv_dropdown_get_selected(drop)];
mHardware->setSleepTimeout(sleepTimeout);
} }
// Smart Home Toggle Event handler // Smart Home Toggle Event handler
@ -91,14 +101,14 @@ void OmoteUI::virtualKeypad_event_cb(lv_event_t *e) {
// mHardware->debugPrint(buffer); // mHardware->debugPrint(buffer);
} }
void OmoteUI::loopHandler(){ void OmoteUI::loopHandler() {
lv_timer_handler(); lv_timer_handler();
lv_task_handler(); lv_task_handler();
} }
void OmoteUI::create_status_bar(){ void OmoteUI::create_status_bar() {
// Create a status bar // Create a status bar
lv_obj_t* statusbar = lv_btn_create(lv_scr_act()); lv_obj_t *statusbar = lv_btn_create(lv_scr_act());
lv_obj_set_size(statusbar, 240, 20); lv_obj_set_size(statusbar, 240, 20);
lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN); lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN);
@ -108,32 +118,41 @@ void OmoteUI::create_status_bar(){
this->WifiLabel = lv_label_create(statusbar); this->WifiLabel = lv_label_create(statusbar);
lv_label_set_text(this->WifiLabel, ""); lv_label_set_text(this->WifiLabel, "");
lv_obj_align(this->WifiLabel, LV_ALIGN_LEFT_MID, -8, 0); lv_obj_align(this->WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN); lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12,
LV_PART_MAIN);
this->objBattPercentage = lv_label_create(statusbar); this->objBattPercentage = lv_label_create(statusbar);
lv_label_set_text(this->objBattPercentage, ""); lv_label_set_text(this->objBattPercentage, "");
lv_obj_align(this->objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0); lv_obj_align(this->objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN); lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12,
LV_PART_MAIN);
this->objBattIcon = lv_label_create(statusbar); this->objBattIcon = lv_label_create(statusbar);
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY); lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
lv_obj_align(this->objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0); lv_obj_align(this->objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN); lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16,
LV_PART_MAIN);
batteryPoller = std::make_unique<poller>([&batteryIcon = objBattIcon, battery = mHardware->battery()](){ batteryPoller = std::make_unique<poller>(
[&batteryIcon = objBattIcon, battery = mHardware->battery()]() {
auto percent = battery->getPercentage(); auto percent = battery->getPercentage();
if(percent > 95) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL); if (percent > 95)
else if(percent > 75) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3); lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL);
else if(percent > 50) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2); else if (percent > 75)
else if(percent > 25) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1); lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3);
else lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY); else if (percent > 50)
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2);
else if (percent > 25)
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1);
else
lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY);
}); });
} }
void OmoteUI::setup_settings(lv_obj_t* parent) void OmoteUI::setup_settings(lv_obj_t *parent) {
{
// Add content to the settings tab // Add content to the settings tab
// With a flex layout, setting groups/boxes will position themselves automatically // With a flex layout, setting groups/boxes will position themselves
// automatically
lv_obj_set_layout(parent, LV_LAYOUT_FLEX); lv_obj_set_layout(parent, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE); lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE);
@ -143,19 +162,19 @@ void OmoteUI::setup_settings(lv_obj_t* parent)
/* Create main page for settings this->settingsMenu*/ /* Create main page for settings this->settingsMenu*/
this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL); this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL);
lv_obj_t* cont = lv_menu_cont_create(this->settingsMainPage); lv_obj_t *cont = lv_menu_cont_create(this->settingsMainPage);
lv_obj_set_layout(cont, LV_LAYOUT_FLEX); lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE); lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
//lv_obj_set_width(cont, lv_obj_get_width(parent)); // lv_obj_set_width(cont, lv_obj_get_width(parent));
this->display_settings(cont); this->display_settings(cont);
this->create_wifi_settings(this->settingsMenu, cont); this->create_wifi_settings(this->settingsMenu, cont);
// Another setting for the battery // Another setting for the battery
lv_obj_t* menuLabel = lv_label_create(cont); lv_obj_t *menuLabel = lv_label_create(cont);
lv_label_set_text(menuLabel, "Battery"); lv_label_set_text(menuLabel, "Battery");
lv_obj_t* menuBox = lv_obj_create(cont); lv_obj_t *menuBox = lv_obj_create(cont);
lv_obj_set_size(menuBox, lv_pct(100), 125); lv_obj_set_size(menuBox, lv_pct(100), 125);
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
@ -163,12 +182,11 @@ void OmoteUI::setup_settings(lv_obj_t* parent)
lv_menu_set_page(this->settingsMenu, this->settingsMainPage); lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
} }
void OmoteUI::ta_kb_event_cb(lv_event_t* e) void OmoteUI::ta_kb_event_cb(lv_event_t *e) {
{
lv_event_code_t code = lv_event_get_code(e); lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e); lv_obj_t *ta = lv_event_get_target(e);
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e); lv_obj_t *kb = (lv_obj_t *)lv_event_get_user_data(e);
switch(code){ switch (code) {
case LV_EVENT_FOCUSED: case LV_EVENT_FOCUSED:
lv_keyboard_set_textarea(kb, ta); lv_keyboard_set_textarea(kb, ta);
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
@ -183,59 +201,62 @@ void OmoteUI::ta_kb_event_cb(lv_event_t* e)
} }
} }
void OmoteUI::create_keyboard() void OmoteUI::create_keyboard() {
{
this->kb = lv_keyboard_create(lv_scr_act()); this->kb = lv_keyboard_create(lv_scr_act());
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_y(this->kb, 0); lv_obj_set_y(this->kb, 0);
} }
void OmoteUI::hide_keyboard() void OmoteUI::hide_keyboard() { lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); }
{
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
}
void OmoteUI::reset_settings_menu() void OmoteUI::reset_settings_menu() {
{
lv_menu_set_page(this->settingsMenu, this->settingsMainPage); lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
} }
void OmoteUI::attach_keyboard(lv_obj_t* textarea) void OmoteUI::attach_keyboard(lv_obj_t *textarea) {
{ if (this->kb == NULL) {
if (this->kb == NULL)
{
this->create_keyboard(); this->create_keyboard();
} }
lv_keyboard_set_textarea(this->kb, textarea); lv_keyboard_set_textarea(this->kb, textarea);
lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_FOCUSED, this->kb); lv_obj_add_event_cb(
lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_DEFOCUSED, this->kb); textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); },
LV_EVENT_FOCUSED, this->kb);
lv_obj_add_event_cb(
textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); },
LV_EVENT_DEFOCUSED, this->kb);
} }
void OmoteUI::layout_UI() { void OmoteUI::layout_UI() {
// Set the background color // Set the background color
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
this->create_keyboard(); this->create_keyboard();
// Setup a scrollable tabview for devices and settings // Setup a scrollable tabview for devices and settings
lv_obj_t* tabview; lv_obj_t *tabview;
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0 tabview =
lv_tabview_create(lv_scr_act(), LV_DIR_TOP,
0); // Hide tab labels by setting their height to 0
lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN);
lv_obj_set_size(tabview, SCREEN_WIDTH, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20) lv_obj_set_size(tabview, SCREEN_WIDTH,
270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20); lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20);
// Add 4 tabs (names are irrelevant since the labels are hidden) // Add 4 tabs (names are irrelevant since the labels are hidden)
lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings"); lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Settings");
lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat"); lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Technisat");
lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV"); lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Apple TV");
lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home"); lv_obj_t *tab4 = lv_tabview_add_tab(tabview, "Smart Home");
// Configure number button grid // Configure number button grid
static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1),
static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit LV_GRID_TEMPLATE_LAST}; // equal x distribution
static lv_coord_t row_dsc[] = {
52, 52, 52, 52, LV_GRID_TEMPLATE_LAST}; // manual y distribution to
// compress the grid a bit
// Create a container with grid for tab2 // Create a container with grid for tab2
lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN); lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN);
lv_obj_t* cont = lv_obj_create(tab2); lv_obj_t *cont = lv_obj_create(tab2);
lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN); lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN); lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
@ -246,48 +267,57 @@ void OmoteUI::layout_UI() {
lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0); lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN); lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
lv_obj_t* buttonLabel; lv_obj_t *buttonLabel;
lv_obj_t* obj; lv_obj_t *obj;
// Iterate through grid buttons configure them // Iterate through grid buttons configure them
for (int i = 0; i < 12; i++) { for (int i = 0; i < 12; i++) {
uint8_t col = i % 3; uint8_t col = i % 3;
uint8_t row = i / 3; uint8_t row = i / 3;
// Create the button object // Create the button object
if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button if ((row == 3) && ((col == 0) || (col == 2)))
continue; // Do not create a complete fourth row, only a 0 button
obj = lv_btn_create(cont); obj = lv_btn_create(cont);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1); lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
lv_obj_set_style_bg_color(obj, this->color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(obj, this->color_primary, LV_PART_MAIN);
lv_obj_set_style_radius(obj, 14, LV_PART_MAIN); lv_obj_set_style_radius(obj, 14, LV_PART_MAIN);
lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN); lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes
// a event in its container
// Create Labels for each button // Create Labels for each button
buttonLabel = lv_label_create(obj); buttonLabel = lv_label_create(obj);
if(i < 9){ if (i < 9) {
lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row); lv_label_set_text_fmt(buttonLabel, std::to_string(i + 1).c_str(), col,
lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event row);
} lv_obj_set_user_data(obj,
else{ (void *)i); // Add user data so we can identify which
// button caused the container event
} else {
lv_label_set_text_fmt(buttonLabel, "0", col, row); lv_label_set_text_fmt(buttonLabel, "0", col, row);
lv_obj_set_user_data(obj, (void*)9); lv_obj_set_user_data(obj, (void *)9);
} }
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN); lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24,
LV_PART_MAIN);
lv_obj_center(buttonLabel); lv_obj_center(buttonLabel);
} }
// Create a shared event for all button inside container // Create a shared event for all button inside container
lv_obj_add_event_cb(cont, [] (lv_event_t* e) {mInstance->virtualKeypad_event_cb(e);}, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(
cont, [](lv_event_t *e) { mInstance->virtualKeypad_event_cb(e); },
LV_EVENT_CLICKED, NULL);
// Add content to the Apple TV tab (3) // Add content to the Apple TV tab (3)
// Add a nice apple tv logo // Add a nice apple tv logo
lv_obj_t* appleImg = imgs.addAppleTVIcon(tab3); lv_obj_t *appleImg = imgs.addAppleTVIcon(tab3);
// create two buttons and add their icons accordingly // create two buttons and add their icons accordingly
lv_obj_t* button = lv_btn_create(tab3); lv_obj_t *button = lv_btn_create(tab3);
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0); lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0);
lv_obj_set_size(button, 60, 60); lv_obj_set_size(button, 60, 60);
lv_obj_set_style_radius(button, 30, LV_PART_MAIN); lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)1); lv_obj_add_event_cb(
button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); },
LV_EVENT_CLICKED, (void *)1);
appleImg = imgs.addAppleDisplayImage(button); appleImg = imgs.addAppleDisplayImage(button);
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0); lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
@ -300,7 +330,9 @@ void OmoteUI::layout_UI() {
lv_obj_set_size(button, 60, 60); lv_obj_set_size(button, 60, 60);
lv_obj_set_style_radius(button, 30, LV_PART_MAIN); lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)2); lv_obj_add_event_cb(
button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); },
LV_EVENT_CLICKED, (void *)2);
appleImg = imgs.addAppleDisplayImage(button); appleImg = imgs.addAppleDisplayImage(button);
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0); lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
@ -316,39 +348,49 @@ void OmoteUI::layout_UI() {
lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE); lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE);
// Add a label, then a box for the light controls // Add a label, then a box for the light controls
lv_obj_t* menuLabel = lv_label_create(tab4); lv_obj_t *menuLabel = lv_label_create(tab4);
lv_label_set_text(menuLabel, "Living Room"); lv_label_set_text(menuLabel, "Living Room");
lv_obj_t* menuBox = lv_obj_create(tab4); lv_obj_t *menuBox = lv_obj_create(tab4);
lv_obj_set_size(menuBox, lv_pct(100), 79); lv_obj_set_size(menuBox, lv_pct(100), 79);
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
lv_obj_t* bulbIcon = imgs.addLightBulbIcon(menuBox); lv_obj_t *bulbIcon = imgs.addLightBulbIcon(menuBox);
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
menuLabel = lv_label_create(menuBox); menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Floor Lamp"); lv_label_set_text(menuLabel, "Floor Lamp");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
lv_obj_t* lightToggleA = lv_switch_create(menuBox); lv_obj_t *lightToggleA = lv_switch_create(menuBox);
lv_obj_set_size(lightToggleA, 40, 22); lv_obj_set_size(lightToggleA, 40, 22);
lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0); lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN); lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR); lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR);
lv_obj_add_event_cb(lightToggleA, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1); lv_obj_add_event_cb(
lightToggleA,
[](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)1);
lv_obj_t *slider = lv_slider_create(menuBox); lv_obj_t *slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 0, 100); lv_slider_set_range(slider, 0, 100);
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30),
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_color(
slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180),
LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_slider_set_value(slider, 255, LV_ANIM_OFF); lv_slider_set_value(slider, 255, LV_ANIM_OFF);
lv_obj_set_size(slider, lv_pct(90), 10); lv_obj_set_size(slider, lv_pct(90), 10);
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1); lv_obj_add_event_cb(
slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)1);
// Add another this->settingsMenu box for a second appliance // Add another this->settingsMenu box for a second appliance
menuBox = lv_obj_create(tab4); menuBox = lv_obj_create(tab4);
@ -362,26 +404,35 @@ void OmoteUI::layout_UI() {
menuLabel = lv_label_create(menuBox); menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Ceiling Light"); lv_label_set_text(menuLabel, "Ceiling Light");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
lv_obj_t* lightToggleB = lv_switch_create(menuBox); lv_obj_t *lightToggleB = lv_switch_create(menuBox);
lv_obj_set_size(lightToggleB, 40, 22); lv_obj_set_size(lightToggleB, 40, 22);
lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0); lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN); lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR); lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR);
lv_obj_add_event_cb(lightToggleB, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2); lv_obj_add_event_cb(
lightToggleB,
[](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)2);
slider = lv_slider_create(menuBox); slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 0, 100); lv_slider_set_range(slider, 0, 100);
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30),
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_color(
slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180),
LV_PART_INDICATOR);
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_slider_set_value(slider, 255, LV_ANIM_OFF); lv_slider_set_value(slider, 255, LV_ANIM_OFF);
lv_obj_set_size(slider, lv_pct(90), 10); lv_obj_set_size(slider, lv_pct(90), 10);
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2); lv_obj_add_event_cb(
slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)2);
// Add another room (empty for now) // Add another room (empty for now)
menuLabel = lv_label_create(tab4); menuLabel = lv_label_create(tab4);
@ -392,20 +443,20 @@ void OmoteUI::layout_UI() {
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
// Set current page according to the current Device // Set current page according to the current Device
lv_tabview_set_act(tabview, 0, LV_ANIM_OFF); currentDevice = this->mHardware->getCurrentDevice();
lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF);
// Create a page indicator // Create a page indicator
panel = lv_obj_create(lv_scr_act()); panel = lv_obj_create(lv_scr_act());
lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable lv_obj_clear_flag(
panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
lv_obj_set_size(panel, SCREEN_WIDTH, 30); lv_obj_set_size(panel, SCREEN_WIDTH, 30);
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0); lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF); lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
// This small hidden button enables the page indicator to scroll further // This small hidden button enables the page indicator to scroll further
lv_obj_t* btn = lv_btn_create(panel); lv_obj_t *btn = lv_btn_create(panel);
lv_obj_set_size(btn, 50, lv_pct(100)); lv_obj_set_size(btn, 50, lv_pct(100));
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
@ -413,7 +464,7 @@ void OmoteUI::layout_UI() {
btn = lv_btn_create(panel); btn = lv_btn_create(panel);
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(btn, 150, lv_pct(100)); lv_obj_set_size(btn, 150, lv_pct(100));
lv_obj_t* label = lv_label_create(btn); lv_obj_t *label = lv_label_create(btn);
lv_label_set_text_fmt(label, "Settings"); lv_label_set_text_fmt(label, "Settings");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
@ -452,8 +503,13 @@ void OmoteUI::layout_UI() {
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
// Make the indicator scroll together with the tabs by creating a scroll event // Make the indicator scroll together with the tabs by creating a scroll event
lv_obj_add_event_cb(lv_tabview_get_content(tabview), [] (lv_event_t* e) {mInstance->store_scroll_value_event_cb(e);}, LV_EVENT_SCROLL, NULL); lv_obj_add_event_cb(
lv_obj_add_event_cb(tabview, [] (lv_event_t* e) {mInstance->tabview_device_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL); lv_tabview_get_content(tabview),
[](lv_event_t *e) { mInstance->store_scroll_value_event_cb(e); },
LV_EVENT_SCROLL, NULL);
lv_obj_add_event_cb(
tabview, [](lv_event_t *e) { mInstance->tabview_device_event_cb(e); },
LV_EVENT_VALUE_CHANGED, NULL);
// Initialize scroll position for the indicator // Initialize scroll position for the indicator
lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL); lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL);
@ -466,10 +522,10 @@ void OmoteUI::layout_UI() {
lv_obj_add_style(panel, &style_btn, 0); lv_obj_add_style(panel, &style_btn, 0);
// Make the indicator fade out at the sides using gradient bitmaps // Make the indicator fade out at the sides using gradient bitmaps
lv_obj_t* img1 = imgs.addLeftGradiant(lv_scr_act()); lv_obj_t *img1 = imgs.addLeftGradiant(lv_scr_act());
lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0); lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0);
lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
lv_obj_t* img2 = imgs.addRightGradiant(lv_scr_act()); lv_obj_t *img2 = imgs.addRightGradiant(lv_scr_act());
lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0); lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
lv_obj_set_size(img2, 30, 30); lv_obj_set_size(img2, 30, 30);

View file

@ -2,16 +2,16 @@
// 2023 Matthew Colvin // 2023 Matthew Colvin
#pragma once #pragma once
#include "UIBase.hpp"
#include "Images.hpp" #include "Images.hpp"
#include "UIBase.hpp"
#include "lvgl.h" #include "lvgl.h"
#include "poller.hpp"
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include "poller.hpp"
namespace UI::Basic{ namespace UI::Basic {
/// @brief Singleton to allow UI code to live separately from the Initialization /// @brief Singleton to allow UI code to live separately from the Initialization
/// of resources. /// of resources.
class OmoteUI : public UIBase { class OmoteUI : public UIBase {
@ -34,6 +34,8 @@ public:
void store_scroll_value_event_cb(lv_event_t *e); void store_scroll_value_event_cb(lv_event_t *e);
// Update current device when the tabview page is changes // Update current device when the tabview page is changes
void tabview_device_event_cb(lv_event_t *e); void tabview_device_event_cb(lv_event_t *e);
// Update wake timeout handler
void wakeTimeoutSetting_event_cb(lv_event_t *e);
// Slider Event handler // Slider Event handler
void bl_slider_event_cb(lv_event_t *e); void bl_slider_event_cb(lv_event_t *e);
// Apple Key Event handler // Apple Key Event handler
@ -46,28 +48,30 @@ public:
void smartHomeSlider_event_cb(lv_event_t *e); void smartHomeSlider_event_cb(lv_event_t *e);
// Virtual Keypad Event handler // Virtual Keypad Event handler
void virtualKeypad_event_cb(lv_event_t *e); void virtualKeypad_event_cb(lv_event_t *e);
void wifi_settings_cb(lv_event_t* event); void wifi_settings_cb(lv_event_t *event);
void connect_btn_cb(lv_event_t* event); void connect_btn_cb(lv_event_t *event);
void password_field_event_cb(lv_event_t* e); void password_field_event_cb(lv_event_t *e);
// Use LVGL to layout the ui and register the callbacks // Use LVGL to layout the ui and register the callbacks
void layout_UI(); void layout_UI();
void ta_kb_event_cb(lv_event_t* e); void ta_kb_event_cb(lv_event_t *e);
void wifi_scan_done(std::shared_ptr<std::vector<WifiInfo>> info); void wifi_scan_done(std::shared_ptr<std::vector<WifiInfo>> info);
void loopHandler(); void loopHandler();
/** /**
* @brief Function to hide the keyboard. If the keyboard is attached to a text area, it will be hidden when the * @brief Function to hide the keyboard. If the keyboard is attached to a text
* text area is defocused. This function can be used if the keyboard need to be hidden due to some script event. * area, it will be hidden when the text area is defocused. This function can
* be used if the keyboard need to be hidden due to some script event.
* *
*/ */
void hide_keyboard(); void hide_keyboard();
/** /**
* @brief Function to show the keyboard. If a text area needs the keybaord, it should be attached to the text area * @brief Function to show the keyboard. If a text area needs the keybaord, it
* using the approbiate function. The keyboard will then show up when the text area is focused. This function is * should be attached to the text area using the approbiate function. The
* keyboard will then show up when the text area is focused. This function is
* needed if the keyboard should be shown due to some script or other trigger. * needed if the keyboard should be shown due to some script or other trigger.
* *
*/ */
@ -78,51 +82,54 @@ private:
std::unique_ptr<poller> batteryPoller; std::unique_ptr<poller> batteryPoller;
int sleepTimeoutMap[5] = {10000,30000,60000,180000,600000};
void reset_settings_menu(); void reset_settings_menu();
void attach_keyboard(lv_obj_t* textarea); void attach_keyboard(lv_obj_t *textarea);
std::shared_ptr<std::vector<WifiInfo>> found_wifi_networks; std::shared_ptr<std::vector<WifiInfo>> found_wifi_networks;
/** /**
* @brief Keyboard object used whenever a keyboard is needed. * @brief Keyboard object used whenever a keyboard is needed.
* *
*/ */
lv_obj_t* kb; lv_obj_t *kb;
/** /**
* @brief Function to create the keyboard object which can then be attached to different text areas. * @brief Function to create the keyboard object which can then be attached to
* different text areas.
* *
*/ */
void create_keyboard(); void create_keyboard();
/** /**
* @brief Set the up settings object * @brief Set the up settings object
* *
* @param parent * @param parent
*/ */
void setup_settings(lv_obj_t* parent); void setup_settings(lv_obj_t *parent);
/** /**
* @brief LVGL Menu for settings pages as needed. * @brief LVGL Menu for settings pages as needed.
* *
*/ */
lv_obj_t* settingsMenu; lv_obj_t *settingsMenu;
/** /**
* @brief Main page of the settings menu * @brief Main page of the settings menu
* *
*/ */
lv_obj_t* settingsMainPage; lv_obj_t *settingsMainPage;
/** /**
* @brief Battery percentage label * @brief Battery percentage label
* *
*/ */
lv_obj_t* objBattPercentage; lv_obj_t *objBattPercentage;
/** /**
* @brief Battery icon object in the status bar * @brief Battery icon object in the status bar
* *
*/ */
lv_obj_t* objBattIcon; lv_obj_t *objBattIcon;
void create_status_bar(); void create_status_bar();
@ -130,44 +137,44 @@ void create_keyboard();
Images imgs = Images(); Images imgs = Images();
uint_fast8_t currentDevice = 4; uint_fast8_t currentDevice = 4;
lv_color_t color_primary = lv_color_hex(0x303030); // gray lv_color_t color_primary = lv_color_hex(0x303030); // gray
bool wakeupByIMUEnabled = true;
inline static const uint_fast8_t virtualKeyMapTechnisat[10] = { inline static const uint_fast8_t virtualKeyMapTechnisat[10] = {
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0}; 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0};
/************************************** WIFI Settings Menu *******************************************************/ /************************************** WIFI Settings Menu
* *******************************************************/
/** /**
* @brief Container within the wifi selection page * @brief Container within the wifi selection page
*/ */
lv_obj_t* wifi_setting_cont; lv_obj_t *wifi_setting_cont;
/** /**
* @brief Wifi settings entry point on the settings tab * @brief Wifi settings entry point on the settings tab
* *
*/ */
lv_obj_t* wifiOverview; lv_obj_t *wifiOverview;
/** /**
* @brief Label in the wifi password page. This label is updated with the selected SSID when the credentials for * @brief Label in the wifi password page. This label is updated with the
* a wifi network is entered. * selected SSID when the credentials for a wifi network is entered.
* *
*/ */
lv_obj_t* wifi_password_label; lv_obj_t *wifi_password_label;
/** /**
* @brief Menu Subpage for the wifi password * @brief Menu Subpage for the wifi password
*/ */
lv_obj_t* wifi_password_page; lv_obj_t *wifi_password_page;
/** /**
* @brief Menu Subpage for wifi selection * @brief Menu Subpage for wifi selection
*/ */
lv_obj_t* wifi_selection_page; lv_obj_t *wifi_selection_page;
/** /**
* @brief Wifi Label shown in the top status bar * @brief Wifi Label shown in the top status bar
*/ */
lv_obj_t* WifiLabel; lv_obj_t *WifiLabel;
/** /**
* @brief Number of wifi subpage needed to display the found wifi networks * @brief Number of wifi subpage needed to display the found wifi networks
@ -181,14 +188,14 @@ void create_keyboard();
*/ */
unsigned int no_wifi_networks; unsigned int no_wifi_networks;
void wifi_status(std::shared_ptr<wifiStatus> status); void wifi_status(std::shared_ptr<wifiStatus> status);
/** /**
* @brief callback function to get next wifi subpage. This callback can be used to get the next or previous page * @brief callback function to get next wifi subpage. This callback can be
* used to get the next or previous page
* *
* @param e lvgl event object * @param e lvgl event object
*/ */
void next_wifi_selection_subpage(lv_event_t* e); void next_wifi_selection_subpage(lv_event_t *e);
/** /**
* @brief Create a wifi selection sub page object * @brief Create a wifi selection sub page object
@ -196,7 +203,7 @@ void create_keyboard();
* @param menu LVGL Menu where the sub page should be added to * @param menu LVGL Menu where the sub page should be added to
* @return lv_obj_t* Menu sub page object pointer * @return lv_obj_t* Menu sub page object pointer
*/ */
lv_obj_t* create_wifi_selection_page(lv_obj_t* menu); lv_obj_t *create_wifi_selection_page(lv_obj_t *menu);
/** /**
* @brief Method to create the wifi password sub page * @brief Method to create the wifi password sub page
@ -204,23 +211,26 @@ void create_keyboard();
* @param menu Menu where the sub page should be created * @param menu Menu where the sub page should be created
* @return lv_obj_t* menu sub page object pointer * @return lv_obj_t* menu sub page object pointer
*/ */
lv_obj_t* create_wifi_password_page(lv_obj_t* menu); lv_obj_t *create_wifi_password_page(lv_obj_t *menu);
/** /**
* @brief Method to create the wifi settings on the main page * @brief Method to create the wifi settings on the main page
* *
* @param parent lv object parent where the main settings page should be added to * @param parent lv object parent where the main settings page should be
* added to
*/ */
void create_wifi_main_page(lv_obj_t* parent); void create_wifi_main_page(lv_obj_t *parent);
/** /**
* @brief Method to create wifi settings. This method will call the create_wifi_selection_page, * @brief Method to create wifi settings. This method will call the
* the create_wifi_password_page, and the create_wifi_main_page * create_wifi_selection_page, the create_wifi_password_page, and the
* create_wifi_main_page
* *
* @param menu Settings menu where the sub pages should be added to * @param menu Settings menu where the sub pages should be added to
* @param parent lv object parent where the main settings page should be added to * @param parent lv object parent where the main settings page should be
* added to
*/ */
void create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent); void create_wifi_settings(lv_obj_t *menu, lv_obj_t *parent);
/** /**
* @brief Function to update the wifi selection sub page * @brief Function to update the wifi selection sub page
@ -234,7 +244,7 @@ void create_keyboard();
* *
* @param parent LVGL object acting as a parent for the display settings page * @param parent LVGL object acting as a parent for the display settings page
*/ */
void display_settings(lv_obj_t* parent); void display_settings(lv_obj_t *parent);
}; };
} } // namespace UI::Basic

View file

@ -2,58 +2,77 @@
using namespace UI::Basic; using namespace UI::Basic;
void OmoteUI::display_settings(lv_obj_t *parent) {
void OmoteUI::display_settings(lv_obj_t* parent) lv_obj_t *menuLabel = lv_label_create(parent);
{
lv_obj_t* menuLabel = lv_label_create(parent);
lv_label_set_text(menuLabel, "Display"); lv_label_set_text(menuLabel, "Display");
lv_obj_t* menuBox = lv_obj_create(parent); lv_obj_t *menuBox = lv_obj_create(parent);
lv_obj_set_size(menuBox, lv_pct(100), 109); lv_obj_set_size(menuBox, lv_pct(100), 109);
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
lv_obj_t* brightnessIcon = imgs.addLowBrightnessIcon(menuBox); lv_obj_t *brightnessIcon = imgs.addLowBrightnessIcon(menuBox);
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_t* slider = lv_slider_create(menuBox); lv_obj_t *slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 0, 255); lv_slider_set_range(slider, 0, 255);
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN); lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50),
lv_slider_set_value(slider, mHardware->display()->getBrightness() , LV_ANIM_OFF); LV_PART_MAIN);
lv_slider_set_value(slider, mHardware->display()->getBrightness(),
LV_ANIM_OFF);
lv_obj_set_size(slider, lv_pct(66), 10); lv_obj_set_size(slider, lv_pct(66), 10);
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
brightnessIcon = imgs.addHighBrightnessIcon(menuBox); brightnessIcon = imgs.addHighBrightnessIcon(menuBox);
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1); lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1);
lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->bl_slider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, nullptr); lv_obj_add_event_cb(
slider, [](lv_event_t *e) { mInstance->bl_slider_event_cb(e); },
LV_EVENT_VALUE_CHANGED, nullptr);
menuLabel = lv_label_create(menuBox); menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Lift to Wake"); lv_label_set_text(menuLabel, "Lift to Wake");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
lv_obj_t* wakeToggle = lv_switch_create(menuBox); lv_obj_t *wakeToggle = lv_switch_create(menuBox);
lv_obj_set_size(wakeToggle, 40, 22); lv_obj_set_size(wakeToggle, 40, 22);
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29); lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN); lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN);
lv_obj_add_event_cb(wakeToggle, [] (lv_event_t* e) {mInstance->WakeEnableSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(
if(wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state wakeToggle,
[](lv_event_t *e) { mInstance->WakeEnableSetting_event_cb(e); },
LV_EVENT_VALUE_CHANGED, NULL);
if (mHardware->getWakeupByIMUEnabled())
lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
menuLabel = lv_label_create(menuBox); menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Timeout"); lv_label_set_text(menuLabel, "Timeout");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
lv_obj_t* drop = lv_dropdown_create(menuBox); lv_obj_t *drop = lv_dropdown_create(menuBox);
lv_dropdown_set_options(drop, "10s\n" lv_dropdown_set_options(drop, "10s\n"
"30s\n" "30s\n"
"1m\n" "1m\n"
"3m"); "3m");
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61); lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
lv_obj_set_size(drop, 70, 22); lv_obj_set_size(drop, 70, 22);
//lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN); // lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
//lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN); // lv_obj_set_style_text_font(lv_dropdown_get_list(drop),
// &lv_font_montserrat_12, LV_PART_MAIN);
lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN); lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN);
lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN);
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary,
LV_PART_MAIN);
lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN); lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN);
lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN); lv_obj_set_style_border_color(lv_dropdown_get_list(drop),
lv_color_hex(0x505050), LV_PART_MAIN);
int sleepTimeoutMapSize =
sizeof(sleepTimeoutMap) / sizeof(sleepTimeoutMap[0]);
int currentTimeout = mHardware->getSleepTimeout();
for (int i = 0; i < sleepTimeoutMapSize; i++) {
if (currentTimeout == sleepTimeoutMap[i])
lv_dropdown_set_selected(drop, i);
}
lv_obj_add_event_cb(
drop, [](lv_event_t *e) { mInstance->wakeTimeoutSetting_event_cb(e); },
LV_EVENT_VALUE_CHANGED, NULL);
} }