#include "WifiSetting.hpp" #include "../Wifi.hpp" #include "esp_lv_adapter.h" #include "esp_log.h" #include static const char* TAG = "WifiSetting"; WifiSetting& WifiSetting::instance() { static WifiSetting instance; return instance; } void WifiSetting::show() { if (visible_) { return; } ESP_LOGI(TAG, "Showing WiFi settings"); if (esp_lv_adapter_lock(-1) == ESP_OK) { createUI(); visible_ = true; Wifi::instance().setStatusCallback([](bool connected) { if (esp_lv_adapter_lock(100) == ESP_OK) { WifiSetting::instance().updateStatusDisplay(); esp_lv_adapter_unlock(); } }); refreshNetworkList(); refreshSavedNetworks(); updateStatusDisplay(); esp_lv_adapter_unlock(); } } void WifiSetting::hide() { if (!visible_) { return; } ESP_LOGI(TAG, "Hiding WiFi settings"); if (esp_lv_adapter_lock(-1) == ESP_OK) { Wifi::instance().setStatusCallback(nullptr); if (overlay_) { lv_obj_del(overlay_); overlay_ = nullptr; statusLabel_ = nullptr; disconnectBtn_ = nullptr; networkList_ = nullptr; savedList_ = nullptr; passwordDialog_ = nullptr; passwordInput_ = nullptr; keyboard_ = nullptr; } visible_ = false; esp_lv_adapter_unlock(); } } bool WifiSetting::isVisible() { return visible_; } void WifiSetting::createUI() { overlay_ = lv_obj_create(lv_scr_act()); lv_obj_set_size(overlay_, LV_PCT(100), LV_PCT(100)); lv_obj_set_style_bg_color(overlay_, lv_color_hex(0x202020), 0); lv_obj_set_style_bg_opa(overlay_, LV_OPA_COVER, 0); lv_obj_set_style_pad_all(overlay_, 10, 0); lv_obj_clear_flag(overlay_, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* header = lv_obj_create(overlay_); lv_obj_set_size(header, LV_PCT(100), 50); lv_obj_align(header, LV_ALIGN_TOP_MID, 0, 0); lv_obj_set_style_bg_color(header, lv_color_hex(0x303030), 0); lv_obj_set_style_pad_all(header, 5, 0); lv_obj_clear_flag(header, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* closeBtn = lv_btn_create(header); lv_obj_set_size(closeBtn, 40, 40); lv_obj_align(closeBtn, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_set_style_bg_color(closeBtn, lv_color_hex(0x804040), 0); //lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* closeLbl = lv_label_create(closeBtn); lv_label_set_text(closeLbl, "X"); lv_obj_center(closeLbl); lv_obj_t* titleLbl = lv_label_create(header); lv_label_set_text(titleLbl, "WiFi Settings"); lv_obj_set_style_text_font(titleLbl, &lv_font_montserrat_14, 0); lv_obj_align(titleLbl, LV_ALIGN_CENTER, 0, 0); lv_obj_t* statusSection = lv_obj_create(overlay_); lv_obj_set_size(statusSection, LV_PCT(100), 80); lv_obj_align_to(statusSection, header, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); lv_obj_set_style_bg_color(statusSection, lv_color_hex(0x303030), 0); lv_obj_set_style_pad_all(statusSection, 10, 0); lv_obj_clear_flag(statusSection, LV_OBJ_FLAG_SCROLLABLE); statusLabel_ = lv_label_create(statusSection); lv_label_set_text(statusLabel_, "Status: Nicht verbunden"); lv_obj_align(statusLabel_, LV_ALIGN_LEFT_MID, 0, 0); disconnectBtn_ = lv_btn_create(statusSection); lv_obj_set_size(disconnectBtn_, 100, 40); lv_obj_align(disconnectBtn_, LV_ALIGN_RIGHT_MID, 0, 0); //lv_obj_add_event_cb(disconnectBtn_, onDisconnectClick, LV_EVENT_CLICKED, nullptr); lv_obj_add_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN); lv_obj_t* disconnectLbl = lv_label_create(disconnectBtn_); lv_label_set_text(disconnectLbl, "Trennen"); lv_obj_center(disconnectLbl); lv_obj_t* availableSection = lv_obj_create(overlay_); lv_obj_set_size(availableSection, LV_PCT(100), 280); lv_obj_align_to(availableSection, statusSection, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); lv_obj_set_style_bg_color(availableSection, lv_color_hex(0x303030), 0); lv_obj_set_style_pad_all(availableSection, 10, 0); lv_obj_clear_flag(availableSection, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* availableHeader = lv_obj_create(availableSection); lv_obj_set_size(availableHeader, LV_PCT(100), 40); lv_obj_align(availableHeader, LV_ALIGN_TOP_MID, 0, 0); lv_obj_set_style_bg_opa(availableHeader, LV_OPA_TRANSP, 0); lv_obj_set_style_border_width(availableHeader, 0, 0); lv_obj_set_style_pad_all(availableHeader, 0, 0); lv_obj_clear_flag(availableHeader, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* availableLbl = lv_label_create(availableHeader); lv_label_set_text(availableLbl, "Verfuegbare Netzwerke:"); lv_obj_align(availableLbl, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_t* scanBtn = lv_btn_create(availableHeader); lv_obj_set_size(scanBtn, 100, 35); lv_obj_align(scanBtn, LV_ALIGN_RIGHT_MID, 0, 0); //lv_obj_add_event_cb(scanBtn, onScanClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* scanLbl = lv_label_create(scanBtn); lv_label_set_text(scanLbl, "Scannen"); lv_obj_center(scanLbl); networkList_ = lv_list_create(availableSection); lv_obj_set_size(networkList_, LV_PCT(100), 220); lv_obj_align_to(networkList_, availableHeader, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); lv_obj_set_style_bg_color(networkList_, lv_color_hex(0x252525), 0); lv_obj_t* savedSection = lv_obj_create(overlay_); lv_obj_set_size(savedSection, LV_PCT(100), 200); lv_obj_align_to(savedSection, availableSection, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); lv_obj_set_style_bg_color(savedSection, lv_color_hex(0x303030), 0); lv_obj_set_style_pad_all(savedSection, 10, 0); lv_obj_clear_flag(savedSection, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* savedLbl = lv_label_create(savedSection); lv_label_set_text(savedLbl, "Gespeicherte Netzwerke:"); lv_obj_align(savedLbl, LV_ALIGN_TOP_LEFT, 0, 0); savedList_ = lv_list_create(savedSection); lv_obj_set_size(savedList_, LV_PCT(100), 150); lv_obj_align(savedList_, LV_ALIGN_BOTTOM_MID, 0, 0); lv_obj_set_style_bg_color(savedList_, lv_color_hex(0x252525), 0); } void WifiSetting::refreshNetworkList() { ESP_LOGI(TAG, "Starting network scan"); if (networkList_) { lv_obj_clean(networkList_); lv_obj_t* scanningLbl = lv_list_add_text(networkList_, "Scanning..."); (void)scanningLbl; } Wifi::instance().scan([](std::vector& networks) { WifiSetting& settings = WifiSetting::instance(); settings.scannedNetworks_ = networks; if (esp_lv_adapter_lock(100) == ESP_OK) { if (settings.networkList_) { lv_obj_clean(settings.networkList_); for (const auto& ap : networks) { char signalStr[64]; int bars = 0; if (ap.rssi >= -50) bars = 4; else if (ap.rssi >= -60) bars = 3; else if (ap.rssi >= -70) bars = 2; else bars = 1; const char* barSymbols[] = {"[# ]", "[## ]", "[### ]", "[####]"}; snprintf(signalStr, sizeof(signalStr), "%s %s %ddBm", (const char*)ap.ssid, barSymbols[bars - 1], ap.rssi); lv_obj_t* btn = lv_list_add_btn(settings.networkList_, LV_SYMBOL_WIFI, signalStr); //lv_obj_add_event_cb(btn, onNetworkSelect, LV_EVENT_CLICKED, nullptr); size_t ssidLen = strlen((const char*)ap.ssid); char* ssidCopy = (char*)lv_malloc(ssidLen + 1); strcpy(ssidCopy, (const char*)ap.ssid); lv_obj_set_user_data(btn, ssidCopy); } if (networks.empty()) { lv_list_add_text(settings.networkList_, "Keine Netzwerke gefunden"); } } esp_lv_adapter_unlock(); } }); } void WifiSetting::refreshSavedNetworks() { if (!savedList_) return; lv_obj_clean(savedList_); auto savedNetworks = Wifi::instance().getSavedNetworks(); for (const auto& ssid : savedNetworks) { lv_obj_t* item = lv_obj_create(savedList_); lv_obj_set_size(item, LV_PCT(100), 40); lv_obj_set_style_bg_color(item, lv_color_hex(0x353535), 0); lv_obj_set_style_pad_all(item, 5, 0); lv_obj_clear_flag(item, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t* nameLbl = lv_label_create(item); lv_label_set_text(nameLbl, ssid.c_str()); lv_obj_align(nameLbl, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_t* deleteBtn = lv_btn_create(item); lv_obj_set_size(deleteBtn, 80, 30); lv_obj_align(deleteBtn, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_set_style_bg_color(deleteBtn, lv_color_hex(0x804040), 0); //lv_obj_add_event_cb(deleteBtn, onDeleteSavedClick, LV_EVENT_CLICKED, nullptr); char* ssidCopy = (char*)lv_malloc(ssid.size() + 1); strcpy(ssidCopy, ssid.c_str()); lv_obj_set_user_data(deleteBtn, ssidCopy); lv_obj_t* deleteLbl = lv_label_create(deleteBtn); lv_label_set_text(deleteLbl, "Loeschen"); lv_obj_center(deleteLbl); } if (savedNetworks.empty()) { lv_list_add_text(savedList_, "Keine gespeicherten Netzwerke"); } } void WifiSetting::updateStatusDisplay() { if (!statusLabel_ || !disconnectBtn_) return; Wifi& wifi = Wifi::instance(); if (wifi.isConnected()) { char statusText[64]; snprintf(statusText, sizeof(statusText), "Verbunden: %s", wifi.getCurrentSSID().c_str()); lv_label_set_text(statusLabel_, statusText); lv_obj_clear_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN); } else { lv_label_set_text(statusLabel_, "Status: Nicht verbunden"); lv_obj_add_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN); } } static void showPasswordDialogAsync(void* arg) { WifiSetting::instance().createPasswordDialogUI(); } void WifiSetting::showPasswordDialog(const char* ssid) { selectedSSID_ = ssid; lv_async_call(showPasswordDialogAsync, nullptr); } void WifiSetting::createPasswordDialogUI() { if (passwordDialog_) return; ESP_LOGI(TAG, "Creating password dialog for: %s", selectedSSID_.c_str()); passwordDialog_ = lv_obj_create(lv_scr_act()); lv_obj_set_size(passwordDialog_, LV_PCT(100), LV_PCT(100)); lv_obj_set_pos(passwordDialog_, 0, 0); lv_obj_set_style_bg_color(passwordDialog_, lv_color_hex(0x303030), 0); lv_obj_set_style_bg_opa(passwordDialog_, LV_OPA_COVER, 0); lv_obj_set_style_pad_all(passwordDialog_, 20, 0); lv_obj_clear_flag(passwordDialog_, LV_OBJ_FLAG_SCROLLABLE); char title[64]; snprintf(title, sizeof(title), "Verbinden mit: %s", selectedSSID_.c_str()); lv_obj_t* titleLbl = lv_label_create(passwordDialog_); lv_label_set_text(titleLbl, title); lv_obj_align(titleLbl, LV_ALIGN_TOP_MID, 0, 10); lv_obj_t* pwLabel = lv_label_create(passwordDialog_); lv_label_set_text(pwLabel, "Passwort:"); lv_obj_align(pwLabel, LV_ALIGN_TOP_LEFT, 10, 50); passwordInput_ = lv_textarea_create(passwordDialog_); lv_obj_set_size(passwordInput_, LV_PCT(90), 50); lv_obj_align(passwordInput_, LV_ALIGN_TOP_MID, 0, 80); lv_textarea_set_password_mode(passwordInput_, true); lv_textarea_set_one_line(passwordInput_, true); lv_textarea_set_placeholder_text(passwordInput_, "Passwort eingeben..."); lv_obj_t* cancelBtn = lv_btn_create(passwordDialog_); lv_obj_set_size(cancelBtn, 150, 50); lv_obj_align(cancelBtn, LV_ALIGN_TOP_LEFT, 20, 150); lv_obj_set_style_bg_color(cancelBtn, lv_color_hex(0x606060), 0); //lv_obj_add_event_cb(cancelBtn, onCancelClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* cancelLbl = lv_label_create(cancelBtn); lv_label_set_text(cancelLbl, "Abbrechen"); lv_obj_center(cancelLbl); lv_obj_t* connectBtn = lv_btn_create(passwordDialog_); lv_obj_set_size(connectBtn, 150, 50); lv_obj_align(connectBtn, LV_ALIGN_TOP_RIGHT, -20, 150); lv_obj_set_style_bg_color(connectBtn, lv_color_hex(0x408040), 0); //lv_obj_add_event_cb(connectBtn, onConnectClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* connectLbl = lv_label_create(connectBtn); lv_label_set_text(connectLbl, "Verbinden"); lv_obj_center(connectLbl); keyboard_ = lv_keyboard_create(passwordDialog_); lv_obj_set_size(keyboard_, LV_PCT(100), 300); lv_obj_align(keyboard_, LV_ALIGN_BOTTOM_MID, 0, 0); lv_keyboard_set_textarea(keyboard_, passwordInput_); //lv_obj_add_event_cb(keyboard_, onKeyboardReady, LV_EVENT_READY, nullptr); ESP_LOGI(TAG, "Password dialog created"); } void WifiSetting::hidePasswordDialog() { if (passwordDialog_) { lv_obj_del(passwordDialog_); passwordDialog_ = nullptr; passwordInput_ = nullptr; keyboard_ = nullptr; } selectedSSID_.clear(); } void WifiSetting::onCloseClick(lv_event_t* e) { (void)e; WifiSetting::instance().hide(); } void WifiSetting::onNetworkSelect(lv_event_t* e) { lv_obj_t* btn = (lv_obj_t*)lv_event_get_target(e); char* ssid = (char*)lv_obj_get_user_data(btn); if (ssid) { ESP_LOGI(TAG, "Selected network: %s", ssid); WifiSetting::instance().showPasswordDialog(ssid); } } void WifiSetting::onScanClick(lv_event_t* e) { (void)e; WifiSetting::instance().refreshNetworkList(); } void WifiSetting::onDisconnectClick(lv_event_t* e) { (void)e; Wifi::instance().disconnect(); WifiSetting::instance().updateStatusDisplay(); } void WifiSetting::onConnectClick(lv_event_t* e) { (void)e; WifiSetting& settings = WifiSetting::instance(); if (settings.passwordInput_ && !settings.selectedSSID_.empty()) { const char* password = lv_textarea_get_text(settings.passwordInput_); ESP_LOGI(TAG, "Connecting to %s", settings.selectedSSID_.c_str()); Wifi::instance().connect(settings.selectedSSID_.c_str(), password); Wifi::instance().saveNetwork(settings.selectedSSID_.c_str(), password); settings.hidePasswordDialog(); settings.refreshSavedNetworks(); } } void WifiSetting::onCancelClick(lv_event_t* e) { (void)e; WifiSetting::instance().hidePasswordDialog(); } void WifiSetting::onDeleteSavedClick(lv_event_t* e) { lv_obj_t* btn = (lv_obj_t*)lv_event_get_target(e); char* ssid = (char*)lv_obj_get_user_data(btn); if (ssid) { ESP_LOGI(TAG, "Deleting saved network: %s", ssid); Wifi::instance().removeNetwork(ssid); lv_free(ssid); WifiSetting::instance().refreshSavedNetworks(); } } void WifiSetting::onKeyboardReady(lv_event_t* e) { (void)e; onConnectClick(nullptr); }