Updated user interface with wifi settings page

This commit is contained in:
Thomas Bittner 2023-08-15 23:11:25 +02:00 committed by MatthewColvin
parent b114e99338
commit 02d973f8b1
9 changed files with 613 additions and 277 deletions

View file

@ -23,4 +23,26 @@ std::optional<HardwareAbstract::batteryStatus> HardwareAbstract::getBatteryStatu
void HardwareAbstract::onBatteryChange(std::function<void(HardwareAbstract::batteryStatus)> onBatteryStatusChangeHandler){ void HardwareAbstract::onBatteryChange(std::function<void(HardwareAbstract::batteryStatus)> onBatteryStatusChangeHandler){
mBatteryNotification.onNotify(std::move(onBatteryStatusChangeHandler)); mBatteryNotification.onNotify(std::move(onBatteryStatusChangeHandler));
} }
void HardwareAbstract::onStartWifiScan(std::function<void()> cb_func){
this->wifi_scan_start_cb.push_back(cb_func);
}
void HardwareAbstract::onWifiScanDone(std::function<void(std::shared_ptr<std::vector<WifiInfo>>)> cb_func){
this->wifi_scan_done_cb.push_back(cb_func);
}
void HardwareAbstract::notifyStartWifiScan(){
for (std::function<void()> cb_func:this->wifi_scan_start_cb)
{
cb_func();
}
}
void HardwareAbstract::notifyWifiScanDone(std::shared_ptr<std::vector<WifiInfo>> info){
for (std::function<void(std::shared_ptr<std::vector<WifiInfo>>)> cb_func: this->wifi_scan_done_cb)
{
cb_func(info);
}
}

View file

@ -13,6 +13,11 @@
#include "wifiHandlerInterface.h" #include "wifiHandlerInterface.h"
#include "Notification.hpp" #include "Notification.hpp"
typedef struct {
std::string ssid;
int rssi;
} WifiInfo;
class HardwareAbstract { class HardwareAbstract {
public: public:
HardwareAbstract( HardwareAbstract(
@ -35,6 +40,11 @@ public:
/// @param onBatteryStatusChangeHandler - Callable to be ran when batter status changes /// @param onBatteryStatusChangeHandler - Callable to be ran when batter status changes
void onBatteryChange(std::function<void(batteryStatus)> onBatteryStatusChangeHandler); void onBatteryChange(std::function<void(batteryStatus)> onBatteryStatusChangeHandler);
void onStartWifiScan(std::function<void()> cb_func);
void onWifiScanDone(std::function<void(std::shared_ptr<std::vector<WifiInfo>>)> cb_func);
void notifyStartWifiScan();
void notifyWifiScanDone(std::shared_ptr<std::vector<WifiInfo>> info);
/// @brief Override in order to do setup of hardware devices /// @brief Override in order to do setup of hardware devices
virtual void init() = 0; virtual void init() = 0;
@ -46,6 +56,8 @@ public:
Notification<batteryStatus> mBatteryNotification; Notification<batteryStatus> mBatteryNotification;
private: private:
std::vector<std::function<void()>> wifi_scan_start_cb;
std::vector<std::function<void(std::shared_ptr<std::vector<WifiInfo>>)>> wifi_scan_done_cb;
std::shared_ptr<BatteryInterface> mBattery; std::shared_ptr<BatteryInterface> mBattery;
std::shared_ptr<wifiHandlerInterface> mWifiHandler; std::shared_ptr<wifiHandlerInterface> mWifiHandler;
std::shared_ptr<DisplayAbstract> mDisplay; std::shared_ptr<DisplayAbstract> mDisplay;

View file

@ -17,6 +17,7 @@
#include "omoteconfig.h" #include "omoteconfig.h"
class HardwareRevX : public HardwareAbstract { class HardwareRevX : public HardwareAbstract {
public: public:
enum class WakeReason { RESET, IMU, KEYPAD }; enum class WakeReason { RESET, IMU, KEYPAD };
@ -70,9 +71,6 @@ private:
IRrecv IrReceiver = IRrecv(IR_RX); IRrecv IrReceiver = IRrecv(IR_RX);
lv_color_t color_primary = lv_color_hex(0x303030); // gray
// 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

@ -51,16 +51,6 @@ std::shared_ptr<wifiHandler> wifiHandler::getInstance()
return std::shared_ptr<wifiHandler>(new wifiHandler()); return std::shared_ptr<wifiHandler>(new wifiHandler());
}; };
String wifiHandler::getFoundSSID(unsigned int index)
{
return WiFi.SSID(index);
}
int wifiHandler::getFoundRSSI(unsigned int index)
{
return WiFi.RSSI(index);
}
wifiHandler::wifiHandler() wifiHandler::wifiHandler()
{ {
this->password[0] = '\0'; this->password[0] = '\0';

View file

@ -27,22 +27,6 @@ class wifiHandler: public wifiHandlerInterface {
*/ */
void disconnect(); void disconnect();
/**
* @brief Get the SSID of the found wifi
*
* @param index index of the found wifi
* @return String SSID of the wifi
*/
String getFoundSSID(unsigned int index);
/**
* @brief Get the RSSI of the found wifi
*
* @param index index of the found wifi
* @return int RSSI value of the found wifi
*/
int getFoundRSSI(unsigned int index);
/** /**
* @brief Function to determine wether or not we are connected to a network * @brief Function to determine wether or not we are connected to a network
* *

View file

@ -90,39 +90,137 @@ void OmoteUI::loopHandler(){
lv_timer_handler(); lv_timer_handler();
} }
void OmoteUI::create_status_bar(){
// Create a status bar
lv_obj_t* statusbar = lv_btn_create(lv_scr_act());
lv_obj_set_size(statusbar, 240, 20);
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_radius(statusbar, 0, LV_PART_MAIN);
lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0);
this->WifiLabel = lv_label_create(statusbar);
lv_label_set_text(this->WifiLabel, "");
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);
this->objBattPercentage = lv_label_create(statusbar);
lv_label_set_text(this->objBattPercentage, "");
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);
this->objBattIcon = lv_label_create(statusbar);
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
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);
}
void OmoteUI::setup_settings(lv_obj_t* parent)
{
// Add content to the settings tab
// With a flex layout, setting groups/boxes will position themselves automatically
lv_obj_set_layout(parent, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE);
// Add a label, then a box for the display settings
this->settingsMenu = lv_menu_create(parent);
lv_obj_set_width(this->settingsMenu, 210);
/* Create main page for settings this->settingsMenu*/
this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL);
lv_obj_t* cont = lv_menu_cont_create(this->settingsMainPage);
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
//lv_obj_set_width(cont, lv_obj_get_width(parent));
this->display_settings(cont);
this->create_wifi_settings(this->settingsMenu, cont);
// Another setting for the battery
lv_obj_t* menuLabel = lv_label_create(cont);
lv_label_set_text(menuLabel, "Battery");
lv_obj_t* menuBox = lv_obj_create(cont);
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_border_width(menuBox, 0, LV_PART_MAIN);
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
}
void OmoteUI::ta_kb_event_cb(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e);
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e);
switch(code){
case LV_EVENT_FOCUSED:
lv_keyboard_set_textarea(kb, ta);
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_move_foreground(kb);
break;
case LV_EVENT_DEFOCUSED:
lv_keyboard_set_textarea(kb, NULL);
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
break;
default:
break;
}
}
void OmoteUI::create_keyboard()
{
this->kb = lv_keyboard_create(lv_scr_act());
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_y(this->kb, 0);
}
void OmoteUI::hide_keyboard()
{
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
}
void OmoteUI::reset_settings_menu()
{
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
}
void OmoteUI::attach_keyboard(lv_obj_t* textarea)
{
if (this->kb == NULL)
{
this->create_keyboard();
}
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(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_DEFOCUSED, this->kb);
}
void OmoteUI::layout_UI() { void OmoteUI::layout_UI() {
// --- LVGL UI Configuration --- // 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();
// 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 = tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
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, lv_obj_set_size(tabview, SCREEN_WIDTH, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
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), 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
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
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);
@ -133,64 +231,50 @@ 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 and 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))) if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
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_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 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, 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_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
// 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, lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row);
row); lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
lv_obj_set_user_data(obj,
(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_obj_set_user_data(obj, (void *)9);
} }
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, else{
LV_PART_MAIN); lv_label_set_text_fmt(buttonLabel, "0", col, row);
lv_obj_set_user_data(obj, (void*)9);
}
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( lv_obj_add_event_cb(cont, [] (lv_event_t* e) {mInstance->virtualKeypad_event_cb(e);}, LV_EVENT_CLICKED, NULL);
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);
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60);
// 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( lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)1);
button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); },
LV_EVENT_CLICKED, (void *)1);
appleImg = imgs.addAppleBackIcon(button); appleImg = imgs.addAppleDisplayImage(button);
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0); lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
button = lv_btn_create(tab3); button = lv_btn_create(tab3);
@ -198,172 +282,54 @@ 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( lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)2);
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);
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
// Add content to the settings tab this->setup_settings(tab1);
// With a flex layout, setting groups/boxes will position themselves
// automatically
lv_obj_set_layout(tab1, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(tab1, LV_SCROLLBAR_MODE_ACTIVE);
// Add a label, then a box for the display settings
lv_obj_t *menuLabel = lv_label_create(tab1);
lv_label_set_text(menuLabel, "Display");
lv_obj_t *menuBox = lv_obj_create(tab1);
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_border_width(menuBox, 0, LV_PART_MAIN);
lv_obj_t *brightnessIcon = imgs.addLowBrightnessIcon(menuBox);
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_t *slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 60, 255);
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_color(slider, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_slider_set_value(slider, backlight_brightness, LV_ANIM_OFF);
lv_obj_set_size(slider, lv_pct(66), 10);
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
brightnessIcon = imgs.addHighBrightnessIcon(menuBox);
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, NULL);
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Lift to Wake");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
lv_obj_t *wakeToggle = lv_switch_create(menuBox);
lv_obj_set_size(wakeToggle, 40, 22);
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
lv_obj_set_style_bg_color(wakeToggle, lv_color_lighten(color_primary, 50),
LV_PART_MAIN);
lv_obj_add_event_cb(
wakeToggle,
[](lv_event_t *e) { mInstance->WakeEnableSetting_event_cb(e); },
LV_EVENT_VALUE_CHANGED, NULL);
if (wakeupByIMUEnabled)
lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Timeout");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
lv_obj_t *drop = lv_dropdown_create(menuBox);
lv_dropdown_set_options(drop, "10s\n"
"30s\n"
"1m\n"
"3m");
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
lv_obj_set_size(drop, 70, 22);
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_border_width(drop, 0, 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_color(lv_dropdown_get_list(drop),
lv_color_darken(color_primary, 40),
LV_PART_MAIN);
// Add another label, then a settings box for WiFi
menuLabel = lv_label_create(tab1);
lv_label_set_text(menuLabel, "Wi-Fi");
menuBox = lv_obj_create(tab1);
lv_obj_set_size(menuBox, lv_pct(100), 80);
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Network");
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0);
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Password");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 32);
// Another setting for the battery
menuLabel = lv_label_create(tab1);
lv_label_set_text(menuLabel, "Battery");
menuBox = lv_obj_create(tab1);
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_border_width(menuBox, 0, LV_PART_MAIN);
mHardware->onBatteryChange([menuLabel](HardwareAbstract::batteryStatus aCurrentBattery){
// I dont know enough about lvgl to do this but basically take aCurrentBattery and update UI elements here.
// See Notice menuLabel is captured and useable here.
});
// Add content to the smart home tab (4) // Add content to the smart home tab (4)
lv_obj_set_layout(tab4, LV_LAYOUT_FLEX); lv_obj_set_layout(tab4, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN);
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
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");
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_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
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( lv_obj_add_event_cb(lightToggleA, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1);
lightToggleA,
[](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)1);
slider = lv_slider_create(menuBox); lv_obj_t *slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 60, 255); lv_slider_set_range(slider, 0, 100);
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), 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_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_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
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( lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1);
slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); },
LV_EVENT_VALUE_CHANGED, (void *)1);
// Add another menu box for a second appliance // Add another this->settingsMenu box for a second appliance
menuBox = lv_obj_create(tab4); 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);
@ -375,35 +341,26 @@ 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_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
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( lv_obj_add_event_cb(lightToggleB, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2);
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, 60, 255); lv_slider_set_range(slider, 0, 100);
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), 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_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_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
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( lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2);
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);
@ -414,19 +371,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, currentDevice, LV_ANIM_OFF); lv_tabview_set_act(tabview, 0, 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( lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
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);
@ -434,7 +392,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);
@ -471,15 +429,10 @@ void OmoteUI::layout_UI() {
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);
// 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_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_tabview_get_content(tabview), lv_obj_add_event_cb(tabview, [] (lv_event_t* e) {mInstance->tabview_device_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL);
[](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);
@ -492,35 +445,12 @@ 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);
// Create a status bar this->create_status_bar();
lv_obj_t *statusbar = lv_btn_create(lv_scr_act());
lv_obj_set_size(statusbar, 240, 20);
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_radius(statusbar, 0, LV_PART_MAIN);
lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_t *WifiLabel = lv_label_create(statusbar);
lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI);
lv_obj_align(WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
lv_obj_set_style_text_font(WifiLabel, &lv_font_montserrat_14, LV_PART_MAIN);
lv_obj_t *objBattPercentage = lv_label_create(statusbar);
lv_label_set_text(objBattPercentage, "");
lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
lv_obj_set_style_text_font(objBattPercentage, &lv_font_montserrat_14,
LV_PART_MAIN);
lv_obj_t *objBattIcon = lv_label_create(statusbar);
lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
lv_obj_align(objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
lv_obj_set_style_text_font(objBattIcon, &lv_font_montserrat_14, LV_PART_MAIN);
} }

View file

@ -46,23 +46,196 @@ 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 connect_btn_cb(lv_event_t* event);
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 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
* text area is defocused. This function can be used if the keyboard need to be hidden due to some script event.
*
*/
void hide_keyboard();
/**
* @brief Function to show the keyboard. If a text area needs the keybaord, it 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.
*
*/
void show_keyboard();
private: private:
static std::shared_ptr<OmoteUI> mInstance; static std::shared_ptr<OmoteUI> mInstance;
std::shared_ptr<HardwareAbstract> mHardware; std::shared_ptr<HardwareAbstract> mHardware;
void reset_settings_menu();
void attach_keyboard(lv_obj_t* textarea);
/**
* @brief Keyboard object used whenever a keyboard is needed.
*
*/
lv_obj_t* kb;
/**
* @brief Function to create the keyboard object which can then be attached to different text areas.
*
*/
void create_keyboard();
/**
* @brief Set the up settings object
*
* @param parent
*/
void setup_settings(lv_obj_t* parent);
/**
* @brief LVGL Menu for settings pages as needed.
*
*/
lv_obj_t* settingsMenu;
/**
* @brief Main page of the settings menu
*
*/
lv_obj_t* settingsMainPage;
/**
* @brief Battery percentage label
*
*/
lv_obj_t* objBattPercentage;
/**
* @brief Battery icon object in the status bar
*
*/
lv_obj_t* objBattIcon;
void create_status_bar();
lv_obj_t *panel = nullptr; lv_obj_t *panel = nullptr;
Images imgs = Images(); Images imgs = Images();
uint_fast8_t currentDevice = 4; uint_fast8_t currentDevice = 4;
int backlight_brightness = 255;
lv_color_t color_primary = lv_color_hex(0x303030); // gray lv_color_t color_primary = lv_color_hex(0x303030); // gray
bool wakeupByIMUEnabled = true; 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 *******************************************************/
/**
* @brief Container within the wifi selection page
*/
lv_obj_t* wifi_setting_cont;
/**
* @brief Wifi settings entry point on the settings tab
*
*/
lv_obj_t* wifiOverview;
/**
* @brief Label in the wifi password page. This label is updated with the selected SSID when the credentials for
* a wifi network is entered.
*
*/
lv_obj_t* wifi_password_label;
/**
* @brief Menu Subpage for the wifi password
*/
lv_obj_t* wifi_password_page;
/**
* @brief Menu Subpage for wifi selection
*/
lv_obj_t* wifi_selection_page;
/**
* @brief Wifi Label shown in the top status bar
*/
lv_obj_t* WifiLabel;
/**
* @brief Number of wifi subpage needed to display the found wifi networks
*
*/
unsigned int no_subpages;
/**
* @brief number of wifi networks found
*
*/
unsigned int no_wifi_networks;
/**
* @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
*/
void next_wifi_selection_subpage(lv_event_t* e);
/**
* @brief Create a wifi selection sub page object
*
* @param menu LVGL Menu where the sub page should be added to
* @return lv_obj_t* Menu sub page object pointer
*/
lv_obj_t* create_wifi_selection_page(lv_obj_t* menu);
/**
* @brief Method to create the wifi password sub page
*
* @param menu Menu where the sub page should be created
* @return lv_obj_t* menu sub page object pointer
*/
lv_obj_t* create_wifi_password_page(lv_obj_t* menu);
/**
* @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
*/
void create_wifi_main_page(lv_obj_t* parent);
/**
* @brief Method to create wifi settings. This method will call the 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 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);
/**
* @brief Function to update the wifi selection sub page
*
* @param page index of the page to display
*/
void update_wifi_selection_subpage(int page);
/************************************** Display settings menu ********************************************************/
/**
* Variable to store the current backlight brightness level
*/
unsigned int backlight_brightness;
/**
* @brief Function to create the display settings page.
*
* @param parent LVGL object acting as a parent for the display settings page
*/
void display_settings(lv_obj_t* parent);
}; };

View file

@ -0,0 +1,56 @@
#include "OmoteUI.hpp"
void OmoteUI::display_settings(lv_obj_t* parent)
{
lv_obj_t* menuLabel = lv_label_create(parent);
lv_label_set_text(menuLabel, "Display");
lv_obj_t* menuBox = lv_obj_create(parent);
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_border_width(menuBox, 0, LV_PART_MAIN);
lv_obj_t* brightnessIcon = imgs.addLowBrightnessIcon(menuBox);
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_t* slider = lv_slider_create(menuBox);
lv_slider_set_range(slider, 30, 255);
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_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
lv_slider_set_value(slider, this->backlight_brightness, LV_ANIM_OFF);
lv_obj_set_size(slider, lv_pct(66), 10);
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
brightnessIcon = imgs.addHighBrightnessIcon(menuBox);
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, &this->backlight_brightness);
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Lift to Wake");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
lv_obj_t* wakeToggle = lv_switch_create(menuBox);
lv_obj_set_size(wakeToggle, 40, 22);
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_add_event_cb(wakeToggle, [] (lv_event_t* e) {mInstance->WakeEnableSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL);
if(wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
menuLabel = lv_label_create(menuBox);
lv_label_set_text(menuLabel, "Timeout");
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
lv_obj_t* drop = lv_dropdown_create(menuBox);
lv_dropdown_set_options(drop, "10s\n"
"30s\n"
"1m\n"
"3m");
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
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(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_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_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);
}

View file

@ -0,0 +1,171 @@
#include "OmoteUI.hpp"
lv_obj_t* OmoteUI::create_wifi_selection_page(lv_obj_t* menu)
{
/* Create sub page for wifi*/
lv_obj_t* subpage = lv_menu_page_create(menu, NULL);
this->wifi_setting_cont = lv_menu_cont_create(subpage);
lv_obj_set_layout(this->wifi_setting_cont, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(this->wifi_setting_cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(this->wifi_setting_cont, LV_SCROLLBAR_MODE_ACTIVE);
lv_obj_t* menuLabel = lv_label_create(this->wifi_setting_cont);
lv_label_set_text(menuLabel, "Searching for wifi networks");
return subpage;
}
/**
* @brief Callback function for the show password checkbox. Checking the box will show the password while unchecked the
* password will be shown as dots.
*
* @param e Pointer to event object for the event where this callback is called
*/
static void show_password_cb(lv_event_t* e)
{
lv_obj_t* password_field = (lv_obj_t*) e->user_data;
if (lv_obj_has_state(e->target, LV_STATE_CHECKED)){
lv_textarea_set_password_mode(password_field, false);
}
else{
lv_textarea_set_password_mode(password_field, true);
}
}
/**
* @brief Textarea callback function for the password field. In case the enter key is pressed in the text area, the
* function will try to connect to the network with the provided password.
*
* @param e Pointer to event object for the event where this callback is called
*/
void OmoteUI::password_field_event_cb(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e);
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e);
const char* password = lv_textarea_get_text(ta);
switch(code){
case LV_EVENT_READY:
//wifihandler.connect(ssid, password);
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
this->hide_keyboard();
this->reset_settings_menu();
/* Fall through on purpose. Pressing enter should disable the keyboard as well*/
default:
break;
}
}
/**
* @brief Callback which is triggered when clicking the connect button. It triggers the wifi connection.
*
* @param event Pointer to event object for the event where this callback is called
*/
void OmoteUI::connect_btn_cb(lv_event_t* event)
{
lv_obj_t* ta = (lv_obj_t*) event->user_data;
const char* password = lv_textarea_get_text(ta);
//Trigger wifi connection here
//wifihandler.connect(ssid, password);
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
this->hide_keyboard();
this->reset_settings_menu();
}
void OmoteUI::create_wifi_main_page(lv_obj_t* parent)
{
lv_obj_t* menuLabel = lv_label_create(parent);
lv_label_set_text(menuLabel, "Wi-Fi");
this->wifiOverview = lv_obj_create(parent);
lv_obj_set_size(this->wifiOverview, lv_pct(100), 80);
lv_obj_set_style_bg_color(this->wifiOverview, color_primary, LV_PART_MAIN);
lv_obj_set_style_border_width(this->wifiOverview, 0, LV_PART_MAIN);
menuLabel = lv_label_create(this->wifiOverview);
lv_obj_t* arrow = lv_label_create(this->wifiOverview);
lv_label_set_text(arrow, LV_SYMBOL_RIGHT);
lv_obj_align(arrow, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_obj_t* ip_label = lv_label_create(this->wifiOverview);
lv_label_set_text(ip_label, "IP:");
lv_obj_align(ip_label, LV_ALIGN_BOTTOM_LEFT, 0, 0);
lv_obj_t* ip = lv_label_create(this->wifiOverview);
lv_obj_align(ip, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
lv_label_set_text(menuLabel, "Disconnected");
lv_label_set_text(ip, "-");
lv_menu_set_load_page_event(this->settingsMenu, this->wifiOverview, this->wifi_selection_page);
lv_obj_add_event_cb(this->wifiOverview, [] (lv_event_t* e) {mInstance->wifi_settings_cb(e);}, LV_EVENT_CLICKED, this->wifi_setting_cont);
}
void OmoteUI::wifi_scan_done(std::shared_ptr<std::vector<WifiInfo>> info)
{
for (WifiInfo i:*info)
{
mHardware->debugPrint(i.ssid);
}
}
void OmoteUI::create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent)
{
this->wifi_selection_page = this->create_wifi_selection_page(menu);
this->wifi_password_page = this->create_wifi_password_page(this->settingsMenu);
this->create_wifi_main_page(parent);
this->mHardware->onWifiScanDone([this] (std::shared_ptr<std::vector<WifiInfo>> info) {this->wifi_scan_done(info);});
}
lv_obj_t* OmoteUI::create_wifi_password_page(lv_obj_t* menu)
{
lv_obj_t* ret_val = lv_menu_page_create(menu, NULL);
lv_obj_t* cont = lv_menu_cont_create(ret_val);
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
this->wifi_password_label = lv_label_create(cont);
lv_label_set_text(this->wifi_password_label, "Password");
lv_obj_t* password_input = lv_textarea_create(cont);
lv_obj_set_width(password_input, lv_pct(100));
lv_textarea_set_password_mode(password_input, true);
lv_textarea_set_one_line(password_input, true);
lv_textarea_set_placeholder_text(password_input, "Password");
lv_obj_add_event_cb(password_input, [] (lv_event_t* e) {mInstance->password_field_event_cb(e);} , LV_EVENT_READY, NULL );
this->attach_keyboard(password_input);
lv_obj_t* show_password = lv_checkbox_create(cont);
lv_checkbox_set_text(show_password, "Show password");
lv_obj_add_event_cb(show_password, show_password_cb, LV_EVENT_VALUE_CHANGED, password_input);
lv_obj_t* connect_button = lv_btn_create(cont);
lv_obj_t* label = lv_label_create(connect_button);
lv_label_set_text(label, "Connect");
lv_obj_add_event_cb(connect_button,[] (lv_event_t* e) { mInstance->connect_btn_cb(e);}, LV_EVENT_CLICKED, password_input);
return ret_val;
}
/**
* @brief Callback which is triggered when the wifi settings are opened (the wifi settings are pressed in the settings
* main page). This function will trigger the asynchronous scan for wifi networks and update the label of the wifi
* selection page to indicate that wifi networks are being searched for. The wifi event callback function then has to
* call the API function to fill the page with the found networks.
*
* @param event Pointer to event object for the event where this callback is called
*/
void OmoteUI::wifi_settings_cb(lv_event_t* event)
{
lv_obj_t* cont = (lv_obj_t*) lv_event_get_user_data(event);
lv_obj_clean(cont);
lv_obj_t* label = lv_label_create(cont);
lv_label_set_text(label, "Searching for wifi networks");
//This will trigger an asynchronouse network scan
// We need to trigger wifi search via HAL
//wifihandler.scan();
}