WiFi improvements (#79)
This commit is contained in:
parent
e3c8747867
commit
6d80144e12
@ -15,6 +15,7 @@
|
|||||||
- Explore LVGL9's FreeRTOS functionality
|
- Explore LVGL9's FreeRTOS functionality
|
||||||
- Explore LVGL9's ILI93414 driver for 2.4" Yellow Board
|
- Explore LVGL9's ILI93414 driver for 2.4" Yellow Board
|
||||||
- Bug: in LVGL9 with M5Core2, crash when bottom item is clicked without scrolling first
|
- Bug: in LVGL9 with M5Core2, crash when bottom item is clicked without scrolling first
|
||||||
|
- Publish firmwares with upload tool
|
||||||
|
|
||||||
# Core Ideas
|
# 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.
|
- 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.
|
||||||
|
|||||||
@ -5,12 +5,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pubsub.h"
|
#include "pubsub.h"
|
||||||
|
#include "wifi_globals.h"
|
||||||
|
#include "wifi_settings.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "wifi_globals.h"
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
|
#include "wifi_settings.h"
|
||||||
#else
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
// From esp_wifi_types.h in ESP-IDF 5.2
|
// 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.
|
* @brief Connect to a network. Disconnects any existing connection.
|
||||||
* Returns immediately but runs in the background. Results are through pubsub.
|
* Returns immediately but runs in the background. Results are through pubsub.
|
||||||
* @param ssid
|
* @param ap
|
||||||
* @param password
|
|
||||||
*/
|
*/
|
||||||
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.
|
* @brief Disconnect from the access point. Doesn't have any effect when not connected.
|
||||||
|
|||||||
@ -39,6 +39,8 @@ typedef struct {
|
|||||||
esp_event_handler_instance_t event_handler_got_ip;
|
esp_event_handler_instance_t event_handler_got_ip;
|
||||||
EventGroupHandle_t event_group;
|
EventGroupHandle_t event_group;
|
||||||
WifiRadioState radio_state;
|
WifiRadioState radio_state;
|
||||||
|
WifiApSettings connection_target;
|
||||||
|
bool connection_target_remember; // Whether to store the connection_target on successful connection or not
|
||||||
} Wifi;
|
} Wifi;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -50,8 +52,6 @@ typedef enum {
|
|||||||
} WifiMessageType;
|
} WifiMessageType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ssid[TT_WIFI_SSID_LIMIT];
|
|
||||||
uint8_t password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT];
|
|
||||||
} WifiConnectMessage;
|
} WifiConnectMessage;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -89,6 +89,12 @@ static Wifi* wifi_alloc() {
|
|||||||
instance->event_group = xEventGroupCreate();
|
instance->event_group = xEventGroupCreate();
|
||||||
instance->radio_state = WIFI_RADIO_OFF;
|
instance->radio_state = WIFI_RADIO_OFF;
|
||||||
instance->secure_connection = false;
|
instance->secure_connection = false;
|
||||||
|
instance->connection_target = (WifiApSettings) {
|
||||||
|
.ssid = { 0 },
|
||||||
|
.password = { 0 },
|
||||||
|
.auto_connect = false
|
||||||
|
};
|
||||||
|
instance->connection_target_remember = false;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,24 +139,25 @@ bool wifi_is_scanning() {
|
|||||||
return 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);
|
tt_assert(wifi_singleton);
|
||||||
WifiMessage message = {.type = WifiMessageTypeConnect};
|
|
||||||
wifi_lock(wifi_singleton);
|
wifi_lock(wifi_singleton);
|
||||||
memcpy(message.connect_message.ssid, ssid, TT_WIFI_SSID_LIMIT);
|
memcpy(&wifi_singleton->connection_target, ap, sizeof(WifiApSettings));
|
||||||
if (password != NULL) {
|
wifi_singleton->connection_target_remember = remember;
|
||||||
memcpy(message.connect_message.password, password, TT_WIFI_CREDENTIALS_PASSWORD_LIMIT);
|
WifiMessage message = {.type = WifiMessageTypeConnect};
|
||||||
} else {
|
|
||||||
message.connect_message.password[0] = 0;
|
|
||||||
}
|
|
||||||
tt_message_queue_put(wifi_singleton->queue, &message, 100 / portTICK_PERIOD_MS);
|
tt_message_queue_put(wifi_singleton->queue, &message, 100 / portTICK_PERIOD_MS);
|
||||||
wifi_unlock(wifi_singleton);
|
wifi_unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_disconnect() {
|
void wifi_disconnect() {
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
WifiMessage message = {.type = WifiMessageTypeDisconnect};
|
|
||||||
wifi_lock(wifi_singleton);
|
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);
|
tt_message_queue_put(wifi_singleton->queue, &message, 100 / portTICK_PERIOD_MS);
|
||||||
wifi_unlock(wifi_singleton);
|
wifi_unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
@ -289,7 +296,7 @@ static void wifi_auto_connect(Wifi* wifi) {
|
|||||||
WifiApSettings ap_settings;
|
WifiApSettings ap_settings;
|
||||||
if (tt_wifi_settings_load(ssid, &ap_settings)) {
|
if (tt_wifi_settings_load(ssid, &ap_settings)) {
|
||||||
if (ap_settings.auto_connect) {
|
if (ap_settings.auto_connect) {
|
||||||
wifi_connect(ssid, ap_settings.secret);
|
wifi_connect(&ap_settings, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_E(TAG, "Failed to load credentials for ssid %s", ssid);
|
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");
|
TT_LOG_I(TAG, "Disabling");
|
||||||
xEventGroupClearBits(wifi_singleton->event_group, WIFI_FAIL_BIT | WIFI_CONNECTED_BIT);
|
|
||||||
wifi->radio_state = WIFI_RADIO_OFF_PENDING;
|
wifi->radio_state = WIFI_RADIO_OFF_PENDING;
|
||||||
wifi_publish_event_simple(wifi, WifiEventTypeRadioStateOffPending);
|
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");
|
static_assert(sizeof(wifi_config.sta.ssid) == (sizeof(wifi_singleton->connection_target.ssid)-1), "SSID size mismatch");
|
||||||
memcpy(wifi_config.sta.ssid, connect_message->ssid, sizeof(wifi_config.sta.ssid));
|
memcpy(wifi_config.sta.ssid, wifi_singleton->connection_target.ssid, sizeof(wifi_config.sta.ssid));
|
||||||
memcpy(wifi_config.sta.password, connect_message->password, sizeof(wifi_config.sta.password));
|
memcpy(wifi_config.sta.password, wifi_singleton->connection_target.password, sizeof(wifi_config.sta.password));
|
||||||
|
|
||||||
wifi->secure_connection = (wifi_config.sta.password[0] != 0x00);
|
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) {
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
wifi->radio_state = WIFI_RADIO_CONNECTION_ACTIVE;
|
wifi->radio_state = WIFI_RADIO_CONNECTION_ACTIVE;
|
||||||
wifi_publish_event_simple(wifi, WifiEventTypeConnectionSuccess);
|
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) {
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
wifi->radio_state = WIFI_RADIO_ON;
|
wifi->radio_state = WIFI_RADIO_ON;
|
||||||
wifi_publish_event_simple(wifi, WifiEventTypeConnectionFailed);
|
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 {
|
} else {
|
||||||
wifi->radio_state = WIFI_RADIO_ON;
|
wifi->radio_state = WIFI_RADIO_ON;
|
||||||
wifi_publish_event_simple(wifi, WifiEventTypeConnectionFailed);
|
wifi_publish_event_simple(wifi, WifiEventTypeConnectionFailed);
|
||||||
TT_LOG_E(TAG, "UNEXPECTED EVENT");
|
TT_LOG_E(TAG, "UNEXPECTED EVENT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xEventGroupClearBits(wifi_singleton->event_group, WIFI_FAIL_BIT | WIFI_CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wifi_disconnect_internal(Wifi* wifi) {
|
static void wifi_disconnect_internal(Wifi* wifi) {
|
||||||
|
|||||||
@ -50,7 +50,7 @@ static Wifi* wifi_alloc() {
|
|||||||
instance->mutex = tt_mutex_alloc(MutexTypeRecursive);
|
instance->mutex = tt_mutex_alloc(MutexTypeRecursive);
|
||||||
instance->pubsub = tt_pubsub_alloc();
|
instance->pubsub = tt_pubsub_alloc();
|
||||||
instance->scan_active = false;
|
instance->scan_active = false;
|
||||||
instance->radio_state = WIFI_RADIO_ON;
|
instance->radio_state = WIFI_RADIO_CONNECTION_ACTIVE;
|
||||||
instance->secure_connection = false;
|
instance->secure_connection = false;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -85,9 +85,8 @@ bool wifi_is_scanning() {
|
|||||||
return wifi_singleton->scan_active;
|
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_assert(wifi_singleton);
|
||||||
tt_check(strlen(ssid) <= 32);
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +140,11 @@ bool wifi_is_connection_secure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int wifi_get_rssi() {
|
int wifi_get_rssi() {
|
||||||
// TODO: implement
|
if (wifi_singleton->radio_state == WIFI_RADIO_CONNECTION_ACTIVE) {
|
||||||
return -10;
|
return -30;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion Public functions
|
// endregion Public functions
|
||||||
|
|||||||
@ -15,7 +15,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char ssid[TT_WIFI_SSID_LIMIT + 1];
|
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;
|
bool auto_connect;
|
||||||
} WifiApSettings;
|
} WifiApSettings;
|
||||||
|
|
||||||
|
|||||||
@ -61,12 +61,12 @@ bool tt_wifi_settings_load(const char* ssid, WifiApSettings* settings) {
|
|||||||
tt_secure_get_iv_from_string(ssid, iv);
|
tt_secure_get_iv_from_string(ssid, iv);
|
||||||
int decrypt_result = tt_secure_decrypt(
|
int decrypt_result = tt_secure_decrypt(
|
||||||
iv,
|
iv,
|
||||||
(uint8_t*)encrypted_settings.secret,
|
(uint8_t*)encrypted_settings.password,
|
||||||
(uint8_t*)settings->secret,
|
(uint8_t*)settings->password,
|
||||||
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
|
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
|
||||||
);
|
);
|
||||||
// Manually ensure null termination, because encryption must be a multiple of 16 bytes
|
// 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) {
|
if (decrypt_result != 0) {
|
||||||
result = ESP_FAIL;
|
result = ESP_FAIL;
|
||||||
@ -98,14 +98,14 @@ bool tt_wifi_settings_save(const WifiApSettings* settings) {
|
|||||||
};
|
};
|
||||||
strcpy((char*)encrypted_settings.ssid, settings->ssid);
|
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
|
// 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];
|
uint8_t iv[16];
|
||||||
tt_secure_get_iv_from_data(settings->ssid, strlen(settings->ssid), iv);
|
tt_secure_get_iv_from_data(settings->ssid, strlen(settings->ssid), iv);
|
||||||
int encrypt_result = tt_secure_encrypt(
|
int encrypt_result = tt_secure_encrypt(
|
||||||
iv,
|
iv,
|
||||||
(uint8_t*)settings->secret,
|
(uint8_t*)settings->password,
|
||||||
(uint8_t*)encrypted_settings.secret,
|
(uint8_t*)encrypted_settings.password,
|
||||||
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
|
TT_WIFI_CREDENTIALS_PASSWORD_LIMIT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "wifi_connect.h"
|
#include "wifi_connect.h"
|
||||||
|
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
#include "services/loader/loader.h"
|
||||||
#include "services/wifi/wifi.h"
|
#include "services/wifi/wifi.h"
|
||||||
#include "tactility_core.h"
|
#include "tactility_core.h"
|
||||||
#include "ui/lvgl_sync.h"
|
#include "ui/lvgl_sync.h"
|
||||||
@ -11,8 +12,11 @@
|
|||||||
// Forward declarations
|
// Forward declarations
|
||||||
static void wifi_connect_event_callback(const void* message, void* context);
|
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) {
|
static void on_connect(const WifiApSettings* ap_settings, bool remember, TT_UNUSED void* parameter) {
|
||||||
wifi_connect(ssid, password);
|
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() {
|
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->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_connect_event_callback, wifi);
|
||||||
wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
|
wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||||
wifi->state = (WifiConnectState) {
|
wifi->state = (WifiConnectState) {
|
||||||
.radio_state = wifi_get_radio_state()
|
.connection_error = false,
|
||||||
|
.settings = {
|
||||||
|
.auto_connect = false,
|
||||||
|
.ssid = { 0 },
|
||||||
|
.password = { 0 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
wifi->bindings = (WifiConnectBindings) {
|
wifi->bindings = (WifiConnectBindings) {
|
||||||
.on_connect_ssid = &on_connect,
|
.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);
|
wifi_connect_view_update(&wifi->view, &wifi->bindings, &wifi->state);
|
||||||
tt_lvgl_unlock();
|
tt_lvgl_unlock();
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_E(TAG, "failed to lock lvgl");
|
TT_LOG_E(TAG, "Failed to lock lvgl");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wifi_connect_unlock(wifi);
|
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) {
|
static void wifi_connect_event_callback(const void* message, void* context) {
|
||||||
const WifiEvent* event = (const WifiEvent*)message;
|
const WifiEvent* event = (const WifiEvent*)message;
|
||||||
WifiConnect* wifi = (WifiConnect*)context;
|
WifiConnect* wifi = (WifiConnect*)context;
|
||||||
wifi_connect_state_set_radio_state(wifi, wifi_get_radio_state());
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case WifiEventTypeRadioStateOn:
|
case WifiEventTypeConnectionFailed:
|
||||||
wifi_scan();
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "services/wifi/wifi_settings.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
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 {
|
typedef struct {
|
||||||
OnConnectSsid on_connect_ssid;
|
OnConnectSsid on_connect_ssid;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "services/wifi/wifi.h"
|
#include "services/wifi/wifi.h"
|
||||||
|
#include "services/wifi/wifi_settings.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -12,8 +13,9 @@ extern "C" {
|
|||||||
* View's state
|
* View's state
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WifiRadioState radio_state;
|
WifiApSettings settings;
|
||||||
bool connection_error;
|
bool connection_error;
|
||||||
|
bool is_connecting;
|
||||||
} WifiConnectState;
|
} WifiConnectState;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
#include "wifi_connect_state_updating.h"
|
#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_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);
|
wifi_connect_unlock(wifi);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,46 +9,75 @@
|
|||||||
#include "wifi_connect.h"
|
#include "wifi_connect.h"
|
||||||
#include "wifi_connect_bundle.h"
|
#include "wifi_connect_bundle.h"
|
||||||
#include "wifi_connect_state.h"
|
#include "wifi_connect_state.h"
|
||||||
|
#include "wifi_connect_state_updating.h"
|
||||||
|
|
||||||
#define TAG "wifi_connect"
|
#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) {
|
static void on_connect(lv_event_t* event) {
|
||||||
WifiConnect* wifi = (WifiConnect*)lv_event_get_user_data(event);
|
WifiConnect* wifi = (WifiConnect*)lv_event_get_user_data(event);
|
||||||
WifiConnectView* view = &wifi->view;
|
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* 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);
|
size_t ssid_len = strlen(ssid);
|
||||||
if (ssid_len > TT_WIFI_SSID_LIMIT) {
|
if (ssid_len > TT_WIFI_SSID_LIMIT) {
|
||||||
// TODO: UI feedback
|
|
||||||
TT_LOG_E(TAG, "SSID too long");
|
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;
|
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;
|
WifiApSettings settings;
|
||||||
strcpy((char*)settings.secret, password);
|
strcpy((char*)settings.password, password);
|
||||||
strcpy((char*)settings.ssid, ssid);
|
strcpy((char*)settings.ssid, ssid);
|
||||||
settings.auto_connect = TT_WIFI_AUTO_CONNECT; // No UI yet, so use global setting:w
|
settings.auto_connect = TT_WIFI_AUTO_CONNECT; // No UI yet, so use global setting:w
|
||||||
|
|
||||||
WifiConnectBindings* bindings = &wifi->bindings;
|
WifiConnectBindings* bindings = &wifi->bindings;
|
||||||
bindings->on_connect_ssid(
|
bindings->on_connect_ssid(
|
||||||
settings.ssid,
|
&settings,
|
||||||
settings.secret,
|
store,
|
||||||
bindings->on_connect_ssid_context
|
bindings->on_connect_ssid_context
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (lv_obj_get_state(view->remember_switch) == LV_STATE_CHECKED) {
|
static void wifi_connect_view_set_loading(WifiConnectView* view, bool loading) {
|
||||||
if (!tt_wifi_settings_save(&settings)) {
|
if (loading) {
|
||||||
TT_LOG_E(TAG, "Failed to store credentials");
|
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) {
|
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(remember_label, LV_ALIGN_CENTER, 0, 0);
|
||||||
lv_obj_align_to(remember_label, view->remember_switch, LV_ALIGN_OUT_RIGHT_MID, 4, 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);
|
view->connect_button = lv_btn_create(button_container);
|
||||||
lv_obj_t* connect_label = lv_label_create(view->connect_button);
|
lv_obj_t* connect_label = lv_label_create(view->connect_button);
|
||||||
lv_label_set_text(connect_label, "Connect");
|
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_align(view->ssid_textarea, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
lv_obj_set_width(view->ssid_textarea, LV_PCT(50));
|
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
|
// Password
|
||||||
|
|
||||||
lv_obj_t* password_wrapper = lv_obj_create(wrapper);
|
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_align(view->password_textarea, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
lv_obj_set_width(view->password_textarea, LV_PCT(50));
|
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
|
// Bottom buttons
|
||||||
wifi_connect_view_create_bottom_buttons(wifi, wrapper);
|
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(
|
void wifi_connect_view_update(
|
||||||
TT_UNUSED WifiConnectView* view,
|
WifiConnectView* view,
|
||||||
TT_UNUSED WifiConnectBindings* bindings,
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,14 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
lv_obj_t* ssid_textarea;
|
lv_obj_t* ssid_textarea;
|
||||||
|
lv_obj_t* ssid_error;
|
||||||
lv_obj_t* password_textarea;
|
lv_obj_t* password_textarea;
|
||||||
|
lv_obj_t* password_error;
|
||||||
lv_obj_t* connect_button;
|
lv_obj_t* connect_button;
|
||||||
lv_obj_t* cancel_button;
|
lv_obj_t* cancel_button;
|
||||||
lv_obj_t* remember_switch;
|
lv_obj_t* remember_switch;
|
||||||
|
lv_obj_t* connecting_spinner;
|
||||||
|
lv_obj_t* connection_error;
|
||||||
lv_group_t* group;
|
lv_group_t* group;
|
||||||
} WifiConnectView;
|
} WifiConnectView;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ static void on_connect(const char* ssid) {
|
|||||||
WifiApSettings settings;
|
WifiApSettings settings;
|
||||||
if (tt_wifi_settings_load(ssid, &settings)) {
|
if (tt_wifi_settings_load(ssid, &settings)) {
|
||||||
TT_LOG_I(TAG, "Connecting with known credentials");
|
TT_LOG_I(TAG, "Connecting with known credentials");
|
||||||
wifi_connect(ssid, settings.secret);
|
wifi_connect(&settings, false);
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_I(TAG, "Starting connection dialog");
|
TT_LOG_I(TAG, "Starting connection dialog");
|
||||||
Bundle bundle = tt_bundle_alloc();
|
Bundle bundle = tt_bundle_alloc();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user