From 6d80144e12fbc0de163e0c7092f8556d7085cf59 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Thu, 14 Nov 2024 22:31:13 +0100 Subject: [PATCH] WiFi improvements (#79) --- docs/ideas.md | 1 + tactility-headless/src/services/wifi/wifi.h | 9 +- .../src/services/wifi/wifi_esp.c | 51 ++++++---- .../src/services/wifi/wifi_mock.c | 12 ++- .../src/services/wifi/wifi_settings.h | 2 +- .../src/services/wifi/wifi_settings_esp.c | 12 +-- .../src/apps/wifi_connect/wifi_connect.c | 32 +++++-- .../apps/wifi_connect/wifi_connect_bindings.h | 3 +- .../apps/wifi_connect/wifi_connect_state.h | 6 +- .../wifi_connect_state_updating.c | 16 +++- .../wifi_connect_state_updating.h | 4 +- .../src/apps/wifi_connect/wifi_connect_view.c | 92 +++++++++++++++---- .../src/apps/wifi_connect/wifi_connect_view.h | 4 + tactility/src/apps/wifi_manage/wifi_manage.c | 2 +- 14 files changed, 178 insertions(+), 68 deletions(-) diff --git a/docs/ideas.md b/docs/ideas.md index 31c963bd..eee3fe81 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -15,6 +15,7 @@ - Explore LVGL9's FreeRTOS functionality - Explore LVGL9's ILI93414 driver for 2.4" Yellow Board - Bug: in LVGL9 with M5Core2, crash when bottom item is clicked without scrolling first +- Publish firmwares with upload tool # Core Ideas - Make a HAL? It would mainly be there to support PC development. It's a lot of effort for supporting what's effectively a dev-only feature. diff --git a/tactility-headless/src/services/wifi/wifi.h b/tactility-headless/src/services/wifi/wifi.h index 829676de..78537b80 100644 --- a/tactility-headless/src/services/wifi/wifi.h +++ b/tactility-headless/src/services/wifi/wifi.h @@ -5,12 +5,14 @@ extern "C" { #endif #include "pubsub.h" +#include "wifi_globals.h" +#include "wifi_settings.h" #include #include -#include "wifi_globals.h" #ifdef ESP_PLATFORM #include "esp_wifi.h" +#include "wifi_settings.h" #else #include // From esp_wifi_types.h in ESP-IDF 5.2 @@ -110,10 +112,9 @@ void wifi_set_enabled(bool enabled); /** * @brief Connect to a network. Disconnects any existing connection. * Returns immediately but runs in the background. Results are through pubsub. - * @param ssid - * @param password + * @param ap */ -void wifi_connect(const char* ssid, _Nullable const char* password); +void wifi_connect(const WifiApSettings* ap, bool remember); /** * @brief Disconnect from the access point. Doesn't have any effect when not connected. diff --git a/tactility-headless/src/services/wifi/wifi_esp.c b/tactility-headless/src/services/wifi/wifi_esp.c index 0497af60..15f479af 100644 --- a/tactility-headless/src/services/wifi/wifi_esp.c +++ b/tactility-headless/src/services/wifi/wifi_esp.c @@ -39,6 +39,8 @@ typedef struct { esp_event_handler_instance_t event_handler_got_ip; EventGroupHandle_t event_group; WifiRadioState radio_state; + WifiApSettings connection_target; + bool connection_target_remember; // Whether to store the connection_target on successful connection or not } Wifi; typedef enum { @@ -50,8 +52,6 @@ typedef enum { } WifiMessageType; typedef struct { - uint8_t ssid[TT_WIFI_SSID_LIMIT]; - uint8_t password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT]; } WifiConnectMessage; typedef struct { @@ -89,6 +89,12 @@ static Wifi* wifi_alloc() { instance->event_group = xEventGroupCreate(); instance->radio_state = WIFI_RADIO_OFF; instance->secure_connection = false; + instance->connection_target = (WifiApSettings) { + .ssid = { 0 }, + .password = { 0 }, + .auto_connect = false + }; + instance->connection_target_remember = false; return instance; } @@ -133,24 +139,25 @@ bool wifi_is_scanning() { return is_scanning; } -void wifi_connect(const char* ssid, _Nullable const char* password) { +void wifi_connect(const WifiApSettings* ap, bool remember) { tt_assert(wifi_singleton); - WifiMessage message = {.type = WifiMessageTypeConnect}; wifi_lock(wifi_singleton); - memcpy(message.connect_message.ssid, ssid, TT_WIFI_SSID_LIMIT); - if (password != NULL) { - memcpy(message.connect_message.password, password, TT_WIFI_CREDENTIALS_PASSWORD_LIMIT); - } else { - message.connect_message.password[0] = 0; - } + memcpy(&wifi_singleton->connection_target, ap, sizeof(WifiApSettings)); + wifi_singleton->connection_target_remember = remember; + WifiMessage message = {.type = WifiMessageTypeConnect}; tt_message_queue_put(wifi_singleton->queue, &message, 100 / portTICK_PERIOD_MS); wifi_unlock(wifi_singleton); } void wifi_disconnect() { tt_assert(wifi_singleton); - WifiMessage message = {.type = WifiMessageTypeDisconnect}; wifi_lock(wifi_singleton); + wifi_singleton->connection_target = (WifiApSettings) { + .ssid = { 0 }, + .password = { 0 }, + .auto_connect = false + }; + WifiMessage message = {.type = WifiMessageTypeDisconnect}; tt_message_queue_put(wifi_singleton->queue, &message, 100 / portTICK_PERIOD_MS); wifi_unlock(wifi_singleton); } @@ -289,7 +296,7 @@ static void wifi_auto_connect(Wifi* wifi) { WifiApSettings ap_settings; if (tt_wifi_settings_load(ssid, &ap_settings)) { if (ap_settings.auto_connect) { - wifi_connect(ssid, ap_settings.secret); + wifi_connect(&ap_settings, false); } } else { TT_LOG_E(TAG, "Failed to load credentials for ssid %s", ssid); @@ -440,7 +447,6 @@ static void wifi_disable(Wifi* wifi) { } TT_LOG_I(TAG, "Disabling"); - xEventGroupClearBits(wifi_singleton->event_group, WIFI_FAIL_BIT | WIFI_CONNECTED_BIT); wifi->radio_state = WIFI_RADIO_OFF_PENDING; wifi_publish_event_simple(wifi, WifiEventTypeRadioStateOffPending); @@ -528,9 +534,9 @@ static void wifi_connect_internal(Wifi* wifi, WifiConnectMessage* connect_messag }, }; - static_assert(sizeof(wifi_config.sta.ssid) == sizeof(connect_message->ssid), "SSID size mismatch"); - memcpy(wifi_config.sta.ssid, connect_message->ssid, sizeof(wifi_config.sta.ssid)); - memcpy(wifi_config.sta.password, connect_message->password, sizeof(wifi_config.sta.password)); + static_assert(sizeof(wifi_config.sta.ssid) == (sizeof(wifi_singleton->connection_target.ssid)-1), "SSID size mismatch"); + memcpy(wifi_config.sta.ssid, wifi_singleton->connection_target.ssid, sizeof(wifi_config.sta.ssid)); + memcpy(wifi_config.sta.password, wifi_singleton->connection_target.password, sizeof(wifi_config.sta.password)); wifi->secure_connection = (wifi_config.sta.password[0] != 0x00); @@ -564,16 +570,25 @@ static void wifi_connect_internal(Wifi* wifi, WifiConnectMessage* connect_messag if (bits & WIFI_CONNECTED_BIT) { wifi->radio_state = WIFI_RADIO_CONNECTION_ACTIVE; wifi_publish_event_simple(wifi, WifiEventTypeConnectionSuccess); - TT_LOG_I(TAG, "Connected to %s", connect_message->ssid); + TT_LOG_I(TAG, "Connected to %s", wifi->connection_target.ssid); + if (wifi->connection_target_remember) { + if (!tt_wifi_settings_save(&wifi->connection_target)) { + TT_LOG_E(TAG, "Failed to store credentials"); + } else { + TT_LOG_I(TAG, "Stored credentials"); + } + } } else if (bits & WIFI_FAIL_BIT) { wifi->radio_state = WIFI_RADIO_ON; wifi_publish_event_simple(wifi, WifiEventTypeConnectionFailed); - TT_LOG_I(TAG, "Failed to connect to %s", connect_message->ssid); + TT_LOG_I(TAG, "Failed to connect to %s", wifi->connection_target.ssid); } else { wifi->radio_state = WIFI_RADIO_ON; wifi_publish_event_simple(wifi, WifiEventTypeConnectionFailed); TT_LOG_E(TAG, "UNEXPECTED EVENT"); } + + xEventGroupClearBits(wifi_singleton->event_group, WIFI_FAIL_BIT | WIFI_CONNECTED_BIT); } static void wifi_disconnect_internal(Wifi* wifi) { diff --git a/tactility-headless/src/services/wifi/wifi_mock.c b/tactility-headless/src/services/wifi/wifi_mock.c index 2f95a5ab..78025114 100644 --- a/tactility-headless/src/services/wifi/wifi_mock.c +++ b/tactility-headless/src/services/wifi/wifi_mock.c @@ -50,7 +50,7 @@ static Wifi* wifi_alloc() { instance->mutex = tt_mutex_alloc(MutexTypeRecursive); instance->pubsub = tt_pubsub_alloc(); instance->scan_active = false; - instance->radio_state = WIFI_RADIO_ON; + instance->radio_state = WIFI_RADIO_CONNECTION_ACTIVE; instance->secure_connection = false; return instance; } @@ -85,9 +85,8 @@ bool wifi_is_scanning() { return wifi_singleton->scan_active; } -void wifi_connect(const char* ssid, _Nullable const char* password) { +void wifi_connect(const WifiApSettings* ap, bool remember) { tt_assert(wifi_singleton); - tt_check(strlen(ssid) <= 32); // TODO: implement } @@ -141,8 +140,11 @@ bool wifi_is_connection_secure() { } int wifi_get_rssi() { - // TODO: implement - return -10; + if (wifi_singleton->radio_state == WIFI_RADIO_CONNECTION_ACTIVE) { + return -30; + } else { + return 0; + } } // endregion Public functions diff --git a/tactility-headless/src/services/wifi/wifi_settings.h b/tactility-headless/src/services/wifi/wifi_settings.h index 6ace9d69..db2ba76e 100644 --- a/tactility-headless/src/services/wifi/wifi_settings.h +++ b/tactility-headless/src/services/wifi/wifi_settings.h @@ -15,7 +15,7 @@ extern "C" { */ typedef struct { char ssid[TT_WIFI_SSID_LIMIT + 1]; - char secret[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT + 1]; + char password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT + 1]; bool auto_connect; } WifiApSettings; diff --git a/tactility-headless/src/services/wifi/wifi_settings_esp.c b/tactility-headless/src/services/wifi/wifi_settings_esp.c index 9fe2cd92..1b6d62e2 100644 --- a/tactility-headless/src/services/wifi/wifi_settings_esp.c +++ b/tactility-headless/src/services/wifi/wifi_settings_esp.c @@ -61,12 +61,12 @@ bool tt_wifi_settings_load(const char* ssid, WifiApSettings* settings) { tt_secure_get_iv_from_string(ssid, iv); int decrypt_result = tt_secure_decrypt( iv, - (uint8_t*)encrypted_settings.secret, - (uint8_t*)settings->secret, + (uint8_t*)encrypted_settings.password, + (uint8_t*)settings->password, TT_WIFI_CREDENTIALS_PASSWORD_LIMIT ); // Manually ensure null termination, because encryption must be a multiple of 16 bytes - encrypted_settings.secret[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0; + encrypted_settings.password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0; if (decrypt_result != 0) { result = ESP_FAIL; @@ -98,14 +98,14 @@ bool tt_wifi_settings_save(const WifiApSettings* settings) { }; strcpy((char*)encrypted_settings.ssid, settings->ssid); // We only decrypt multiples of 16, so we have to ensure the last byte is set to 0 - encrypted_settings.secret[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0; + encrypted_settings.password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT] = 0; uint8_t iv[16]; tt_secure_get_iv_from_data(settings->ssid, strlen(settings->ssid), iv); int encrypt_result = tt_secure_encrypt( iv, - (uint8_t*)settings->secret, - (uint8_t*)encrypted_settings.secret, + (uint8_t*)settings->password, + (uint8_t*)encrypted_settings.password, TT_WIFI_CREDENTIALS_PASSWORD_LIMIT ); diff --git a/tactility/src/apps/wifi_connect/wifi_connect.c b/tactility/src/apps/wifi_connect/wifi_connect.c index b564f30f..9630f7ca 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect.c +++ b/tactility/src/apps/wifi_connect/wifi_connect.c @@ -1,6 +1,7 @@ #include "wifi_connect.h" #include "app.h" +#include "services/loader/loader.h" #include "services/wifi/wifi.h" #include "tactility_core.h" #include "ui/lvgl_sync.h" @@ -11,8 +12,11 @@ // Forward declarations static void wifi_connect_event_callback(const void* message, void* context); -static void on_connect(const char* ssid, const char* password, TT_UNUSED void* parameter) { - wifi_connect(ssid, password); +static void on_connect(const WifiApSettings* ap_settings, bool remember, TT_UNUSED void* parameter) { + WifiConnect* wifi = (WifiConnect*)parameter; + wifi_connect_state_set_ap_settings(wifi, ap_settings); + wifi_connect_state_set_connecting(wifi, true); + wifi_connect(ap_settings, remember); } static WifiConnect* wifi_connect_alloc() { @@ -22,7 +26,12 @@ static WifiConnect* wifi_connect_alloc() { wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_connect_event_callback, wifi); wifi->mutex = tt_mutex_alloc(MutexTypeNormal); wifi->state = (WifiConnectState) { - .radio_state = wifi_get_radio_state() + .connection_error = false, + .settings = { + .auto_connect = false, + .ssid = { 0 }, + .password = { 0 } + } }; wifi->bindings = (WifiConnectBindings) { .on_connect_ssid = &on_connect, @@ -60,7 +69,7 @@ void wifi_connect_request_view_update(WifiConnect* wifi) { wifi_connect_view_update(&wifi->view, &wifi->bindings, &wifi->state); tt_lvgl_unlock(); } else { - TT_LOG_E(TAG, "failed to lock lvgl"); + TT_LOG_E(TAG, "Failed to lock lvgl"); } } wifi_connect_unlock(wifi); @@ -69,10 +78,19 @@ void wifi_connect_request_view_update(WifiConnect* wifi) { static void wifi_connect_event_callback(const void* message, void* context) { const WifiEvent* event = (const WifiEvent*)message; WifiConnect* wifi = (WifiConnect*)context; - wifi_connect_state_set_radio_state(wifi, wifi_get_radio_state()); switch (event->type) { - case WifiEventTypeRadioStateOn: - wifi_scan(); + case WifiEventTypeConnectionFailed: + if (wifi->state.is_connecting) { + wifi_connect_state_set_connecting(wifi, false); + wifi_connect_state_set_radio_error(wifi, true); + wifi_connect_request_view_update(wifi); + } + break; + case WifiEventTypeConnectionSuccess: + if (wifi->state.is_connecting) { + wifi_connect_state_set_connecting(wifi, false); + loader_stop_app(); + } break; default: break; diff --git a/tactility/src/apps/wifi_connect/wifi_connect_bindings.h b/tactility/src/apps/wifi_connect/wifi_connect_bindings.h index 2250e678..2d4b6586 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_bindings.h +++ b/tactility/src/apps/wifi_connect/wifi_connect_bindings.h @@ -1,8 +1,9 @@ #pragma once +#include "services/wifi/wifi_settings.h" #include -typedef void (*OnConnectSsid)(const char ssid[TT_WIFI_SSID_LIMIT], const char password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT], void* context); +typedef void (*OnConnectSsid)(const WifiApSettings* settings, bool store, void* context); typedef struct { OnConnectSsid on_connect_ssid; diff --git a/tactility/src/apps/wifi_connect/wifi_connect_state.h b/tactility/src/apps/wifi_connect/wifi_connect_state.h index e8cc430f..a9e29aa0 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_state.h +++ b/tactility/src/apps/wifi_connect/wifi_connect_state.h @@ -1,8 +1,9 @@ #pragma once -#include #include "app.h" #include "services/wifi/wifi.h" +#include "services/wifi/wifi_settings.h" +#include #ifdef __cplusplus extern "C" { @@ -12,8 +13,9 @@ extern "C" { * View's state */ typedef struct { - WifiRadioState radio_state; + WifiApSettings settings; bool connection_error; + bool is_connecting; } WifiConnectState; #ifdef __cplusplus diff --git a/tactility/src/apps/wifi_connect/wifi_connect_state_updating.c b/tactility/src/apps/wifi_connect/wifi_connect_state_updating.c index 5a8d75dc..770d065a 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_state_updating.c +++ b/tactility/src/apps/wifi_connect/wifi_connect_state_updating.c @@ -1,7 +1,19 @@ #include "wifi_connect_state_updating.h" -void wifi_connect_state_set_radio_state(WifiConnect* wifi, WifiRadioState state) { +void wifi_connect_state_set_radio_error(WifiConnect* wifi, bool error) { wifi_connect_lock(wifi); - wifi->state.radio_state = state; + wifi->state.connection_error = error; + wifi_connect_unlock(wifi); +} + +void wifi_connect_state_set_ap_settings(WifiConnect* wifi, const WifiApSettings* settings) { + wifi_connect_lock(wifi); + memcpy(&(wifi->state.settings), settings, sizeof(WifiApSettings)); + wifi_connect_unlock(wifi); +} + +void wifi_connect_state_set_connecting(WifiConnect* wifi, bool is_connecting) { + wifi_connect_lock(wifi); + wifi->state.is_connecting = is_connecting; wifi_connect_unlock(wifi); } diff --git a/tactility/src/apps/wifi_connect/wifi_connect_state_updating.h b/tactility/src/apps/wifi_connect/wifi_connect_state_updating.h index 0154396f..bc6baed9 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_state_updating.h +++ b/tactility/src/apps/wifi_connect/wifi_connect_state_updating.h @@ -6,7 +6,9 @@ extern "C" { #endif -void wifi_connect_state_set_radio_state(WifiConnect* wifi, WifiRadioState state); +void wifi_connect_state_set_radio_error(WifiConnect* wifi, bool error); +void wifi_connect_state_set_ap_settings(WifiConnect* wifi, const WifiApSettings* settings); +void wifi_connect_state_set_connecting(WifiConnect* wifi, bool is_connecting); #ifdef __cplusplus } diff --git a/tactility/src/apps/wifi_connect/wifi_connect_view.c b/tactility/src/apps/wifi_connect/wifi_connect_view.c index c0f92517..11d6851e 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_view.c +++ b/tactility/src/apps/wifi_connect/wifi_connect_view.c @@ -9,46 +9,75 @@ #include "wifi_connect.h" #include "wifi_connect_bundle.h" #include "wifi_connect_state.h" +#include "wifi_connect_state_updating.h" #define TAG "wifi_connect" +static void wifi_connect_view_set_loading(WifiConnectView* view, bool loading); + +static void wifi_reset_errors(WifiConnectView* view) { + lv_obj_add_flag(view->password_error, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(view->ssid_error, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(view->connection_error, LV_OBJ_FLAG_HIDDEN); +} + static void on_connect(lv_event_t* event) { WifiConnect* wifi = (WifiConnect*)lv_event_get_user_data(event); WifiConnectView* view = &wifi->view; + + wifi_connect_state_set_radio_error(wifi, false); + wifi_reset_errors(view); + const char* ssid = lv_textarea_get_text(view->ssid_textarea); - const char* password = lv_textarea_get_text(view->password_textarea); - - size_t password_len = strlen(password); - if (password_len > TT_WIFI_CREDENTIALS_PASSWORD_LIMIT) { - // TODO: UI feedback - TT_LOG_E(TAG, "Password too long"); - return; - } - size_t ssid_len = strlen(ssid); if (ssid_len > TT_WIFI_SSID_LIMIT) { - // TODO: UI feedback TT_LOG_E(TAG, "SSID too long"); + lv_label_set_text(view->ssid_error, "SSID too long"); + lv_obj_remove_flag(view->ssid_error, LV_OBJ_FLAG_HIDDEN); return; } + const char* password = lv_textarea_get_text(view->password_textarea); + size_t password_len = strlen(password); + if (password_len > TT_WIFI_CREDENTIALS_PASSWORD_LIMIT) { + TT_LOG_E(TAG, "Password too long"); + lv_label_set_text(view->password_error, "Password too long"); + lv_obj_remove_flag(view->password_error, LV_OBJ_FLAG_HIDDEN); + return; + } + + bool store = lv_obj_get_state(view->remember_switch) & LV_STATE_CHECKED; + + wifi_connect_view_set_loading(view, true); + WifiApSettings settings; - strcpy((char*)settings.secret, password); + strcpy((char*)settings.password, password); strcpy((char*)settings.ssid, ssid); settings.auto_connect = TT_WIFI_AUTO_CONNECT; // No UI yet, so use global setting:w WifiConnectBindings* bindings = &wifi->bindings; bindings->on_connect_ssid( - settings.ssid, - settings.secret, + &settings, + store, bindings->on_connect_ssid_context ); +} - if (lv_obj_get_state(view->remember_switch) == LV_STATE_CHECKED) { - if (!tt_wifi_settings_save(&settings)) { - TT_LOG_E(TAG, "Failed to store credentials"); - } +static void wifi_connect_view_set_loading(WifiConnectView* view, bool loading) { + if (loading) { + lv_obj_add_flag(view->connect_button, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(view->connecting_spinner, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_state(view->password_textarea, LV_STATE_DISABLED); + lv_obj_add_state(view->ssid_textarea, LV_STATE_DISABLED); + lv_obj_add_state(view->remember_switch, LV_STATE_DISABLED); + } else { + lv_obj_remove_flag(view->connect_button, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(view->connecting_spinner, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_state(view->password_textarea, LV_STATE_DISABLED); + lv_obj_remove_state(view->ssid_textarea, LV_STATE_DISABLED); + lv_obj_remove_state(view->remember_switch, LV_STATE_DISABLED); } + } void wifi_connect_view_create_bottom_buttons(WifiConnect* wifi, lv_obj_t* parent) { @@ -69,6 +98,11 @@ void wifi_connect_view_create_bottom_buttons(WifiConnect* wifi, lv_obj_t* parent lv_obj_align(remember_label, LV_ALIGN_CENTER, 0, 0); lv_obj_align_to(remember_label, view->remember_switch, LV_ALIGN_OUT_RIGHT_MID, 4, 0); + view->connecting_spinner = lv_spinner_create(button_container); + lv_obj_set_size(view->connecting_spinner, 32, 32); + lv_obj_align(view->connecting_spinner, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_add_flag(view->connecting_spinner, LV_OBJ_FLAG_HIDDEN); + view->connect_button = lv_btn_create(button_container); lv_obj_t* connect_label = lv_label_create(view->connect_button); lv_label_set_text(connect_label, "Connect"); @@ -113,6 +147,10 @@ void wifi_connect_view_create(App app, void* wifi, lv_obj_t* parent) { lv_obj_align(view->ssid_textarea, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_set_width(view->ssid_textarea, LV_PCT(50)); + view->ssid_error = lv_label_create(wrapper); + lv_obj_set_style_text_color(view->ssid_error, lv_color_make(255, 50, 50), 0); + lv_obj_add_flag(view->ssid_error, LV_OBJ_FLAG_HIDDEN); + // Password lv_obj_t* password_wrapper = lv_obj_create(wrapper); @@ -138,6 +176,15 @@ void wifi_connect_view_create(App app, void* wifi, lv_obj_t* parent) { lv_obj_align(view->password_textarea, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_set_width(view->password_textarea, LV_PCT(50)); + view->password_error = lv_label_create(wrapper); + lv_obj_set_style_text_color(view->password_error, lv_color_make(255, 50, 50), 0); + lv_obj_add_flag(view->password_error, LV_OBJ_FLAG_HIDDEN); + + // Connection error + view->connection_error = lv_label_create(wrapper); + lv_obj_set_style_text_color(view->connection_error, lv_color_make(255, 50, 50), 0); + lv_obj_add_flag(view->connection_error, LV_OBJ_FLAG_HIDDEN); + // Bottom buttons wifi_connect_view_create_bottom_buttons(wifi, wrapper); @@ -165,9 +212,14 @@ void wifi_connect_view_destroy(TT_UNUSED WifiConnectView* view) { } void wifi_connect_view_update( - TT_UNUSED WifiConnectView* view, + WifiConnectView* view, TT_UNUSED WifiConnectBindings* bindings, - TT_UNUSED WifiConnectState* state + WifiConnectState* state ) { - // NO-OP + if (state->connection_error) { + wifi_connect_view_set_loading(view, false); + wifi_reset_errors(view); + lv_label_set_text(view->connection_error, "Connection failed"); + lv_obj_remove_flag(view->connection_error, LV_OBJ_FLAG_HIDDEN); + } } diff --git a/tactility/src/apps/wifi_connect/wifi_connect_view.h b/tactility/src/apps/wifi_connect/wifi_connect_view.h index 76dea634..5ce35cfb 100644 --- a/tactility/src/apps/wifi_connect/wifi_connect_view.h +++ b/tactility/src/apps/wifi_connect/wifi_connect_view.h @@ -10,10 +10,14 @@ extern "C" { typedef struct { lv_obj_t* ssid_textarea; + lv_obj_t* ssid_error; lv_obj_t* password_textarea; + lv_obj_t* password_error; lv_obj_t* connect_button; lv_obj_t* cancel_button; lv_obj_t* remember_switch; + lv_obj_t* connecting_spinner; + lv_obj_t* connection_error; lv_group_t* group; } WifiConnectView; diff --git a/tactility/src/apps/wifi_manage/wifi_manage.c b/tactility/src/apps/wifi_manage/wifi_manage.c index b1592ce8..ee76ea6a 100644 --- a/tactility/src/apps/wifi_manage/wifi_manage.c +++ b/tactility/src/apps/wifi_manage/wifi_manage.c @@ -18,7 +18,7 @@ static void on_connect(const char* ssid) { WifiApSettings settings; if (tt_wifi_settings_load(ssid, &settings)) { TT_LOG_I(TAG, "Connecting with known credentials"); - wifi_connect(ssid, settings.secret); + wifi_connect(&settings, false); } else { TT_LOG_I(TAG, "Starting connection dialog"); Bundle bundle = tt_bundle_alloc();