WiFi fixes and improvements (#100)
This commit is contained in:
parent
33bb742dfb
commit
e9c02ab58e
@ -15,7 +15,6 @@
|
|||||||
- 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
|
||||||
- De-duplicate WiFi SSIDs.
|
|
||||||
- Replace M5Unified and M5GFX with custom drivers (so we can fix the Core2 SD card mounting bug, and so we regain some firmware space)
|
- Replace M5Unified and M5GFX with custom drivers (so we can fix the Core2 SD card mounting bug, and so we regain some firmware space)
|
||||||
- Commit fix to esp_lvgl_port to have esp_lvgl_port_disp.c user driver_data instead of user_data
|
- Commit fix to esp_lvgl_port to have esp_lvgl_port_disp.c user driver_data instead of user_data
|
||||||
|
|
||||||
@ -28,10 +27,11 @@
|
|||||||
- Wi-Fi using dispatcher to dispatch its main functionality to the dedicated Wi-Fi CPU core (to avoid main loop hack)
|
- Wi-Fi using dispatcher to dispatch its main functionality to the dedicated Wi-Fi CPU core (to avoid main loop hack)
|
||||||
|
|
||||||
# App Ideas
|
# App Ideas
|
||||||
|
- Add FreeRTOS task manager functionality to System Info app
|
||||||
- BlueTooth keyboard app
|
- BlueTooth keyboard app
|
||||||
- Chip 8 emulator
|
- Chip 8 emulator
|
||||||
- BadUSB
|
- BadUSB (in December 2024, TinyUSB has a bug where uninstalling and re-installing the driver fails)
|
||||||
- Discord bot
|
- Discord bot
|
||||||
- IR transceiver app
|
- IR transceiver app
|
||||||
- GPS app
|
- GPS app
|
||||||
- Investigate CSI https://stevenmhernandez.github.io/ESP32-CSI-Tool/
|
- Investigate CSI https://stevenmhernandez.github.io/ESP32-CSI-Tool/
|
||||||
|
|||||||
@ -38,7 +38,7 @@ typedef void (*AppOnShow)(App& app, lv_obj_t* parent);
|
|||||||
typedef void (*AppOnHide)(App& app);
|
typedef void (*AppOnHide)(App& app);
|
||||||
typedef void (*AppOnResult)(App& app, Result result, const Bundle& resultData);
|
typedef void (*AppOnResult)(App& app, Result result, const Bundle& resultData);
|
||||||
|
|
||||||
typedef struct Manifest {
|
struct Manifest {
|
||||||
/**
|
/**
|
||||||
* The identifier by which the app is launched by the system and other apps.
|
* The identifier by which the app is launched by the system and other apps.
|
||||||
*/
|
*/
|
||||||
@ -83,7 +83,7 @@ typedef struct Manifest {
|
|||||||
* Handle the result for apps that are launched
|
* Handle the result for apps that are launched
|
||||||
*/
|
*/
|
||||||
const AppOnResult _Nullable onResult = nullptr;
|
const AppOnResult _Nullable onResult = nullptr;
|
||||||
} Manifest;
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool operator()(const Manifest* left, const Manifest* right) const { return left->name < right->name; }
|
bool operator()(const Manifest* left, const Manifest* right) const { return left->name < right->name; }
|
||||||
|
|||||||
@ -6,10 +6,10 @@ typedef void (*OnWifiToggled)(bool enable);
|
|||||||
typedef void (*OnConnectSsid)(const char* ssid);
|
typedef void (*OnConnectSsid)(const char* ssid);
|
||||||
typedef void (*OnDisconnect)();
|
typedef void (*OnDisconnect)();
|
||||||
|
|
||||||
typedef struct {
|
struct Bindings{
|
||||||
OnWifiToggled on_wifi_toggled;
|
OnWifiToggled onWifiToggled;
|
||||||
OnConnectSsid on_connect_ssid;
|
OnConnectSsid onConnectSsid;
|
||||||
OnDisconnect on_disconnect;
|
OnDisconnect onDisconnect;
|
||||||
} WifiManageBindings;
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
33
Tactility/Source/app/wifimanage/State.cpp
Normal file
33
Tactility/Source/app/wifimanage/State.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <Check.h>
|
||||||
|
#include "WifiManage.h"
|
||||||
|
|
||||||
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
|
void State::setScanning(bool isScanning) {
|
||||||
|
tt_check(mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||||
|
scanning = isScanning;
|
||||||
|
tt_check(mutex.release() == TtStatusOk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::setRadioState(service::wifi::WifiRadioState state) {
|
||||||
|
tt_check(mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||||
|
radioState = state;
|
||||||
|
tt_check(mutex.release() == TtStatusOk);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<service::wifi::WifiApRecord>& State::lockApRecords() const {
|
||||||
|
tt_check(mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||||
|
return apRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::unlockApRecords() const {
|
||||||
|
tt_check(mutex.release() == TtStatusOk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::updateApRecords() {
|
||||||
|
tt_check(mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||||
|
apRecords = service::wifi::getScanResults();
|
||||||
|
tt_check(mutex.release() == TtStatusOk);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
37
Tactility/Source/app/wifimanage/State.h
Normal file
37
Tactility/Source/app/wifimanage/State.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "service/wifi/Wifi.h"
|
||||||
|
#include "Mutex.h"
|
||||||
|
|
||||||
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View's state
|
||||||
|
*/
|
||||||
|
class State {
|
||||||
|
|
||||||
|
Mutex mutex;
|
||||||
|
bool scanning;
|
||||||
|
service::wifi::WifiRadioState radioState;
|
||||||
|
std::vector<service::wifi::WifiApRecord> apRecords;
|
||||||
|
std::string connectSsid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
State() {}
|
||||||
|
|
||||||
|
void setScanning(bool isScanning);
|
||||||
|
bool isScanning() const { return scanning; }
|
||||||
|
|
||||||
|
void setRadioState(service::wifi::WifiRadioState state);
|
||||||
|
service::wifi::WifiRadioState getRadioState() const { return radioState; }
|
||||||
|
|
||||||
|
void updateApRecords();
|
||||||
|
|
||||||
|
const std::vector<service::wifi::WifiApRecord>& lockApRecords() const;
|
||||||
|
void unlockApRecords() const;
|
||||||
|
|
||||||
|
void setConnectSsid(std::string ssid) { connectSsid = ssid; }
|
||||||
|
std::string getConnectSsid() const { return connectSsid; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
215
Tactility/Source/app/wifimanage/View.cpp
Normal file
215
Tactility/Source/app/wifimanage/View.cpp
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#include "View.h"
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
#include "State.h"
|
||||||
|
#include "service/statusbar/Statusbar.h"
|
||||||
|
#include "service/wifi/Wifi.h"
|
||||||
|
#include "lvgl/Style.h"
|
||||||
|
#include "lvgl/Toolbar.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
|
#define TAG "wifi_main_view"
|
||||||
|
#define SPINNER_HEIGHT 40
|
||||||
|
|
||||||
|
static void on_enable_switch_changed(lv_event_t* event) {
|
||||||
|
lv_event_code_t code = lv_event_get_code(event);
|
||||||
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
||||||
|
if (code == LV_EVENT_VALUE_CHANGED) {
|
||||||
|
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
auto* bindings = static_cast<Bindings*>(lv_event_get_user_data(event));
|
||||||
|
bindings->onWifiToggled(is_on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_disconnect_pressed(lv_event_t* event) {
|
||||||
|
auto* bindings = static_cast<Bindings*>(lv_event_get_user_data(event));
|
||||||
|
bindings->onDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Secondary updates
|
||||||
|
|
||||||
|
static void connect(lv_event_t* event) {
|
||||||
|
lv_obj_t* button = lv_event_get_current_target_obj(event);
|
||||||
|
// Assumes that the second child of the button is a label ... risky
|
||||||
|
lv_obj_t* label = lv_obj_get_child(button, 1);
|
||||||
|
// We get the SSID from the button label because it's safer than alloc'ing
|
||||||
|
// our own and passing it as the event data
|
||||||
|
const char* ssid = lv_label_get_text(label);
|
||||||
|
TT_LOG_I(TAG, "Clicked AP: %s", ssid);
|
||||||
|
auto* bindings = static_cast<Bindings*>(lv_event_get_user_data(event));
|
||||||
|
bindings->onConnectSsid(ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::createNetworkButton(Bindings* bindings, const service::wifi::WifiApRecord& record) {
|
||||||
|
const char* icon = service::statusbar::getWifiStatusIconForRssi(record.rssi, record.auth_mode != WIFI_AUTH_OPEN);
|
||||||
|
lv_obj_t* ap_button = lv_list_add_btn(
|
||||||
|
networks_list,
|
||||||
|
icon,
|
||||||
|
record.ssid.c_str()
|
||||||
|
);
|
||||||
|
lv_obj_add_event_cb(ap_button, &connect, LV_EVENT_CLICKED, bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::updateNetworkList(State* state, Bindings* bindings) {
|
||||||
|
lv_obj_clean(networks_list);
|
||||||
|
switch (state->getRadioState()) {
|
||||||
|
case service::wifi::WIFI_RADIO_ON_PENDING:
|
||||||
|
case service::wifi::WIFI_RADIO_ON:
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE: {
|
||||||
|
lv_obj_clear_flag(networks_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
auto& ap_records = state->lockApRecords();
|
||||||
|
std::set<std::string> used_ssids;
|
||||||
|
if (!ap_records.empty()) {
|
||||||
|
for (auto& record : ap_records) {
|
||||||
|
if (used_ssids.find(record.ssid) == used_ssids.end()) {
|
||||||
|
createNetworkButton(bindings, record);
|
||||||
|
used_ssids.insert(record.ssid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_obj_clear_flag(networks_list, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else if (state->isScanning()) {
|
||||||
|
lv_obj_add_flag(networks_list, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_clear_flag(networks_list, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_t* label = lv_label_create(networks_list);
|
||||||
|
lv_label_set_text(label, "No networks found.");
|
||||||
|
}
|
||||||
|
state->unlockApRecords();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case service::wifi::WIFI_RADIO_OFF_PENDING:
|
||||||
|
case service::wifi::WIFI_RADIO_OFF: {
|
||||||
|
lv_obj_add_flag(networks_list, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_add_flag(networks_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::updateScanning(State* state) {
|
||||||
|
if (state->getRadioState() == service::wifi::WIFI_RADIO_ON && state->isScanning()) {
|
||||||
|
lv_obj_clear_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::updateWifiToggle(State* state) {
|
||||||
|
lv_obj_clear_state(enable_switch, LV_STATE_ANY);
|
||||||
|
switch (state->getRadioState()) {
|
||||||
|
case service::wifi::WIFI_RADIO_ON:
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE:
|
||||||
|
lv_obj_add_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
break;
|
||||||
|
case service::wifi::WIFI_RADIO_ON_PENDING:
|
||||||
|
lv_obj_add_state(enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED);
|
||||||
|
break;
|
||||||
|
case service::wifi::WIFI_RADIO_OFF:
|
||||||
|
lv_obj_remove_state(enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED);
|
||||||
|
break;
|
||||||
|
case service::wifi::WIFI_RADIO_OFF_PENDING:
|
||||||
|
lv_obj_remove_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
lv_obj_add_state(enable_switch, LV_STATE_DISABLED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::updateConnectedAp(State* state, TT_UNUSED Bindings* bindings) {
|
||||||
|
switch (state->getRadioState()) {
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
||||||
|
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE:
|
||||||
|
lv_obj_clear_flag(connected_ap_container, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(connected_ap_label, state->getConnectSsid().c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lv_obj_add_flag(connected_ap_container, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion Secondary updates
|
||||||
|
|
||||||
|
// region Main
|
||||||
|
|
||||||
|
void View::init(const App& app, Bindings* bindings, lv_obj_t* parent) {
|
||||||
|
root = parent;
|
||||||
|
|
||||||
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lvgl::toolbar_create(parent, app);
|
||||||
|
|
||||||
|
lv_obj_t* wrapper = lv_obj_create(parent);
|
||||||
|
lv_obj_set_width(wrapper, LV_PCT(100));
|
||||||
|
lv_obj_set_flex_grow(wrapper, 1);
|
||||||
|
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
||||||
|
|
||||||
|
// Top row: enable/disable
|
||||||
|
lv_obj_t* switch_container = lv_obj_create(wrapper);
|
||||||
|
lv_obj_set_width(switch_container, LV_PCT(100));
|
||||||
|
lv_obj_set_height(switch_container, LV_SIZE_CONTENT);
|
||||||
|
lvgl::obj_set_style_no_padding(switch_container);
|
||||||
|
lvgl::obj_set_style_bg_invisible(switch_container);
|
||||||
|
|
||||||
|
lv_obj_t* enable_label = lv_label_create(switch_container);
|
||||||
|
lv_label_set_text(enable_label, "Wi-Fi");
|
||||||
|
lv_obj_set_align(enable_label, LV_ALIGN_LEFT_MID);
|
||||||
|
|
||||||
|
enable_switch = lv_switch_create(switch_container);
|
||||||
|
lv_obj_add_event_cb(enable_switch, on_enable_switch_changed, LV_EVENT_ALL, bindings);
|
||||||
|
lv_obj_set_align(enable_switch, LV_ALIGN_RIGHT_MID);
|
||||||
|
|
||||||
|
connected_ap_container = lv_obj_create(wrapper);
|
||||||
|
lv_obj_set_size(connected_ap_container, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_min_height(connected_ap_container, SPINNER_HEIGHT, 0);
|
||||||
|
lvgl::obj_set_style_no_padding(connected_ap_container);
|
||||||
|
lv_obj_set_style_border_width(connected_ap_container, 0, 0);
|
||||||
|
|
||||||
|
connected_ap_label = lv_label_create(connected_ap_container);
|
||||||
|
lv_obj_align(connected_ap_label, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
|
|
||||||
|
lv_obj_t* disconnect_button = lv_btn_create(connected_ap_container);
|
||||||
|
lv_obj_add_event_cb(disconnect_button, &on_disconnect_pressed, LV_EVENT_CLICKED, bindings);
|
||||||
|
lv_obj_t* disconnect_label = lv_label_create(disconnect_button);
|
||||||
|
lv_label_set_text(disconnect_label, "Disconnect");
|
||||||
|
lv_obj_align(disconnect_button, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
|
// Networks
|
||||||
|
|
||||||
|
lv_obj_t* networks_header = lv_obj_create(wrapper);
|
||||||
|
lv_obj_set_size(networks_header, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_min_height(networks_header, SPINNER_HEIGHT, 0);
|
||||||
|
lvgl::obj_set_style_no_padding(networks_header);
|
||||||
|
lv_obj_set_style_border_width(networks_header, 0, 0);
|
||||||
|
|
||||||
|
networks_label = lv_label_create(networks_header);
|
||||||
|
lv_label_set_text(networks_label, "Networks");
|
||||||
|
lv_obj_align(networks_label, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
|
|
||||||
|
scanning_spinner = lv_spinner_create(networks_header);
|
||||||
|
lv_spinner_set_anim_params(scanning_spinner, 1000, 60);
|
||||||
|
lv_obj_set_size(scanning_spinner, SPINNER_HEIGHT, SPINNER_HEIGHT);
|
||||||
|
lv_obj_set_style_pad_top(scanning_spinner, 4, 0);
|
||||||
|
lv_obj_set_style_pad_bottom(scanning_spinner, 4, 0);
|
||||||
|
lv_obj_align_to(scanning_spinner, networks_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0);
|
||||||
|
|
||||||
|
networks_list = lv_obj_create(wrapper);
|
||||||
|
lv_obj_set_flex_flow(networks_list, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_width(networks_list, LV_PCT(100));
|
||||||
|
lv_obj_set_height(networks_list, LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_pad_top(networks_list, 8, 0);
|
||||||
|
lv_obj_set_style_pad_bottom(networks_list, 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::update(Bindings* bindings, State* state) {
|
||||||
|
updateWifiToggle(state);
|
||||||
|
updateScanning(state);
|
||||||
|
updateNetworkList(state, bindings);
|
||||||
|
updateConnectedAp(state, bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
34
Tactility/Source/app/wifimanage/View.h
Normal file
34
Tactility/Source/app/wifimanage/View.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/App.h"
|
||||||
|
#include "Bindings.h"
|
||||||
|
#include "State.h"
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
|
class View {
|
||||||
|
private:
|
||||||
|
lv_obj_t* root = nullptr;
|
||||||
|
lv_obj_t* enable_switch = nullptr;
|
||||||
|
lv_obj_t* scanning_spinner = nullptr;
|
||||||
|
lv_obj_t* networks_label = nullptr;
|
||||||
|
lv_obj_t* networks_list = nullptr;
|
||||||
|
lv_obj_t* connected_ap_container = nullptr;
|
||||||
|
lv_obj_t* connected_ap_label = nullptr;
|
||||||
|
public:
|
||||||
|
View() {}
|
||||||
|
void init(const App& app, Bindings* bindings, lv_obj_t* parent);
|
||||||
|
void update(Bindings* bindings, State* state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void updateConnectedAp(State* state, TT_UNUSED Bindings* bindings);
|
||||||
|
void updateWifiToggle(State* state);
|
||||||
|
void updateScanning(State* state);
|
||||||
|
void updateNetworkList(State* state, Bindings* bindings);
|
||||||
|
void createNetworkButton(Bindings* bindings, const service::wifi::WifiApRecord& record);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@ -6,17 +6,14 @@
|
|||||||
#include "service/loader/Loader.h"
|
#include "service/loader/Loader.h"
|
||||||
#include "service/wifi/WifiSettings.h"
|
#include "service/wifi/WifiSettings.h"
|
||||||
#include "lvgl/LvglSync.h"
|
#include "lvgl/LvglSync.h"
|
||||||
#include "WifiManageStateUpdating.h"
|
#include "View.h"
|
||||||
#include "WifiManageView.h"
|
#include "State.h"
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
#define TAG "wifi_manage"
|
#define TAG "wifi_manage"
|
||||||
|
|
||||||
// Forward declarations
|
static void onConnect(const char* ssid) {
|
||||||
static void event_callback(const void* message, void* context);
|
|
||||||
|
|
||||||
static void on_connect(const char* ssid) {
|
|
||||||
service::wifi::settings::WifiApSettings settings;
|
service::wifi::settings::WifiApSettings settings;
|
||||||
if (service::wifi::settings::load(ssid, &settings)) {
|
if (service::wifi::settings::load(ssid, &settings)) {
|
||||||
TT_LOG_I(TAG, "Connecting with known credentials");
|
TT_LOG_I(TAG, "Connecting with known credentials");
|
||||||
@ -30,79 +27,55 @@ static void on_connect(const char* ssid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_disconnect() {
|
static void onDisconnect() {
|
||||||
service::wifi::disconnect();
|
service::wifi::disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_wifi_toggled(bool enabled) {
|
static void onWifiToggled(bool enabled) {
|
||||||
service::wifi::setEnabled(enabled);
|
service::wifi::setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WifiManage* wifi_manage_alloc() {
|
WifiManage::WifiManage() {
|
||||||
auto* wifi = static_cast<WifiManage*>(malloc(sizeof(WifiManage)));
|
bindings = (Bindings) {
|
||||||
|
.onWifiToggled = &onWifiToggled,
|
||||||
wifi->wifi_subscription = nullptr;
|
.onConnectSsid = &onConnect,
|
||||||
wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
|
.onDisconnect = &onDisconnect
|
||||||
wifi->state = (WifiManageState) {
|
|
||||||
.scanning = service::wifi::isScanning(),
|
|
||||||
.radio_state = service::wifi::getRadioState(),
|
|
||||||
.connect_ssid = { 0 },
|
|
||||||
.ap_records = { },
|
|
||||||
.ap_records_count = 0
|
|
||||||
};
|
};
|
||||||
wifi->view_enabled = false;
|
|
||||||
wifi->bindings = (WifiManageBindings) {
|
|
||||||
.on_wifi_toggled = &on_wifi_toggled,
|
|
||||||
.on_connect_ssid = &on_connect,
|
|
||||||
.on_disconnect = &on_disconnect
|
|
||||||
};
|
|
||||||
|
|
||||||
return wifi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wifi_manage_free(WifiManage* wifi) {
|
void WifiManage::lock() {
|
||||||
tt_mutex_free(wifi->mutex);
|
tt_check(mutex.acquire(TtWaitForever) == TtStatusOk);
|
||||||
|
|
||||||
free(wifi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock(WifiManage* wifi) {
|
void WifiManage::unlock() {
|
||||||
tt_assert(wifi);
|
tt_check(mutex.release() == TtStatusOk);
|
||||||
tt_assert(wifi->mutex);
|
|
||||||
tt_mutex_acquire(wifi->mutex, TtWaitForever);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock(WifiManage* wifi) {
|
void WifiManage::requestViewUpdate() {
|
||||||
tt_assert(wifi);
|
lock();
|
||||||
tt_assert(wifi->mutex);
|
if (isViewEnabled) {
|
||||||
tt_mutex_release(wifi->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void request_view_update(WifiManage* wifi) {
|
|
||||||
lock(wifi);
|
|
||||||
if (wifi->view_enabled) {
|
|
||||||
if (lvgl::lock(1000)) {
|
if (lvgl::lock(1000)) {
|
||||||
view_update(&wifi->view, &wifi->bindings, &wifi->state);
|
view.update(&bindings, &state);
|
||||||
lvgl::unlock();
|
lvgl::unlock();
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_E(TAG, "failed to lock lvgl");
|
TT_LOG_E(TAG, "failed to lock lvgl");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock(wifi);
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wifi_manage_event_callback(const void* message, void* context) {
|
static void wifiManageEventCallback(const void* message, void* context) {
|
||||||
auto* event = (service::wifi::WifiEvent*)message;
|
auto* event = (service::wifi::WifiEvent*)message;
|
||||||
auto* wifi = (WifiManage*)context;
|
auto* wifi = (WifiManage*)context;
|
||||||
TT_LOG_I(TAG, "Update with state %d", service::wifi::getRadioState());
|
TT_LOG_I(TAG, "Update with state %d", service::wifi::getRadioState());
|
||||||
state_set_radio_state(wifi, service::wifi::getRadioState());
|
wifi->getState().setRadioState(service::wifi::getRadioState());
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case tt::service::wifi::WifiEventTypeScanStarted:
|
case tt::service::wifi::WifiEventTypeScanStarted:
|
||||||
state_set_scanning(wifi, true);
|
wifi->getState().setScanning(true);
|
||||||
break;
|
break;
|
||||||
case tt::service::wifi::WifiEventTypeScanFinished:
|
case tt::service::wifi::WifiEventTypeScanFinished:
|
||||||
state_set_scanning(wifi, false);
|
wifi->getState().setScanning(false);
|
||||||
state_update_scanned_records(wifi);
|
wifi->getState().updateApRecords();
|
||||||
break;
|
break;
|
||||||
case tt::service::wifi::WifiEventTypeRadioStateOn:
|
case tt::service::wifi::WifiEventTypeRadioStateOn:
|
||||||
if (!service::wifi::isScanning()) {
|
if (!service::wifi::isScanning()) {
|
||||||
@ -113,27 +86,25 @@ static void wifi_manage_event_callback(const void* message, void* context) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
request_view_update(wifi);
|
wifi->requestViewUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_show(App& app, lv_obj_t* parent) {
|
void WifiManage::onShow(App& app, lv_obj_t* parent) {
|
||||||
auto* wifi = (WifiManage*)app.getData();
|
|
||||||
|
|
||||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||||
wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_manage_event_callback, wifi);
|
wifiSubscription = tt_pubsub_subscribe(wifi_pubsub, &wifiManageEventCallback, this);
|
||||||
|
|
||||||
// State update (it has its own locking)
|
// State update (it has its own locking)
|
||||||
state_set_radio_state(wifi, service::wifi::getRadioState());
|
state.setRadioState(service::wifi::getRadioState());
|
||||||
state_set_scanning(wifi, service::wifi::isScanning());
|
state.setScanning(service::wifi::isScanning());
|
||||||
state_update_scanned_records(wifi);
|
state.updateApRecords();
|
||||||
|
|
||||||
// View update
|
// View update
|
||||||
lock(wifi);
|
lock();
|
||||||
wifi->view_enabled = true;
|
isViewEnabled = true;
|
||||||
strcpy((char*)wifi->state.connect_ssid, "Connected"); // TODO update with proper SSID
|
state.setConnectSsid("Connected"); // TODO update with proper SSID
|
||||||
view_create(app, &wifi->view, &wifi->bindings, parent);
|
view.init(app, &bindings, parent);
|
||||||
view_update(&wifi->view, &wifi->bindings, &wifi->state);
|
view.update(&bindings, &state);
|
||||||
unlock(wifi);
|
unlock();
|
||||||
|
|
||||||
service::wifi::WifiRadioState radio_state = service::wifi::getRadioState();
|
service::wifi::WifiRadioState radio_state = service::wifi::getRadioState();
|
||||||
bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON ||
|
bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON ||
|
||||||
@ -144,36 +115,50 @@ static void app_show(App& app, lv_obj_t* parent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_hide(App& app) {
|
void WifiManage::onHide(TT_UNUSED App& app) {
|
||||||
auto* wifi = (WifiManage*)app.getData();
|
lock();
|
||||||
lock(wifi);
|
|
||||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||||
tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription);
|
tt_pubsub_unsubscribe(wifi_pubsub, wifiSubscription);
|
||||||
wifi->wifi_subscription = nullptr;
|
wifiSubscription = nullptr;
|
||||||
wifi->view_enabled = false;
|
isViewEnabled = false;
|
||||||
unlock(wifi);
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_start(App& app) {
|
// region Manifest methods
|
||||||
WifiManage* wifi = wifi_manage_alloc();
|
|
||||||
|
static void onStart(App& app) {
|
||||||
|
auto* wifi = new WifiManage();
|
||||||
app.setData(wifi);
|
app.setData(wifi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_stop(App& app) {
|
static void onStop(App& app) {
|
||||||
auto* wifi = (WifiManage*)app.getData();
|
auto* wifi = (WifiManage*)app.getData();
|
||||||
tt_assert(wifi != nullptr);
|
tt_assert(wifi != nullptr);
|
||||||
wifi_manage_free(wifi);
|
delete wifi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void onShow(App& app, lv_obj_t* parent) {
|
||||||
|
auto* wifi = (WifiManage*)app.getData();
|
||||||
|
wifi->onShow(app, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onHide(App& app) {
|
||||||
|
auto* wifi = (WifiManage*)app.getData();
|
||||||
|
wifi->onHide(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
extern const Manifest manifest = {
|
extern const Manifest manifest = {
|
||||||
.id = "WifiManage",
|
.id = "WifiManage",
|
||||||
.name = "Wi-Fi",
|
.name = "Wi-Fi",
|
||||||
.icon = LV_SYMBOL_WIFI,
|
.icon = LV_SYMBOL_WIFI,
|
||||||
.type = TypeSettings,
|
.type = TypeSettings,
|
||||||
.onStart = &app_start,
|
.onStart = onStart,
|
||||||
.onStop = &app_stop,
|
.onStop = onStop,
|
||||||
.onShow = &app_show,
|
.onShow = onShow,
|
||||||
.onHide = &app_hide
|
.onHide = onHide
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -1,24 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "WifiManageView.h"
|
#include "View.h"
|
||||||
|
#include "State.h"
|
||||||
#include "service/wifi/Wifi.h"
|
#include "service/wifi/Wifi.h"
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
typedef struct {
|
class WifiManage {
|
||||||
PubSubSubscription* wifi_subscription;
|
|
||||||
Mutex* mutex;
|
|
||||||
WifiManageState state;
|
|
||||||
WifiManageView view;
|
|
||||||
bool view_enabled;
|
|
||||||
WifiManageBindings bindings;
|
|
||||||
} WifiManage;
|
|
||||||
|
|
||||||
void lock(WifiManage* wifi);
|
PubSubSubscription* wifiSubscription = nullptr;
|
||||||
|
Mutex mutex;
|
||||||
|
tt::app::wifimanage::State state;
|
||||||
|
tt::app::wifimanage::View view;
|
||||||
|
Bindings bindings = { };
|
||||||
|
bool isViewEnabled = false;
|
||||||
|
|
||||||
void unlock(WifiManage* wifi);
|
public:
|
||||||
|
|
||||||
void request_view_update(WifiManage* wifi);
|
WifiManage();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
void onShow(App& app, lv_obj_t* parent);
|
||||||
|
void onHide(App& app);
|
||||||
|
|
||||||
|
State& getState() { return state; }
|
||||||
|
|
||||||
|
void requestViewUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "service/wifi/Wifi.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
|
||||||
|
|
||||||
#define WIFI_SCAN_AP_RECORD_COUNT 16
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View's state
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
bool scanning;
|
|
||||||
service::wifi::WifiRadioState radio_state;
|
|
||||||
uint8_t connect_ssid[33];
|
|
||||||
service::wifi::WifiApRecord ap_records[WIFI_SCAN_AP_RECORD_COUNT];
|
|
||||||
uint16_t ap_records_count;
|
|
||||||
} WifiManageState;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#include "WifiManage.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
|
||||||
|
|
||||||
void state_set_scanning(WifiManage* wifi, bool is_scanning) {
|
|
||||||
lock(wifi);
|
|
||||||
wifi->state.scanning = is_scanning;
|
|
||||||
unlock(wifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void state_set_radio_state(WifiManage* wifi, service::wifi::WifiRadioState state) {
|
|
||||||
lock(wifi);
|
|
||||||
wifi->state.radio_state = state;
|
|
||||||
unlock(wifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void state_update_scanned_records(WifiManage* wifi) {
|
|
||||||
lock(wifi);
|
|
||||||
service::wifi::getScanResults(
|
|
||||||
wifi->state.ap_records,
|
|
||||||
WIFI_SCAN_AP_RECORD_COUNT,
|
|
||||||
&wifi->state.ap_records_count
|
|
||||||
);
|
|
||||||
unlock(wifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WifiManage.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
|
||||||
|
|
||||||
void state_set_scanning(WifiManage* wifi, bool is_scanning);
|
|
||||||
void state_set_radio_state(WifiManage* wifi, service::wifi::WifiRadioState state);
|
|
||||||
void state_update_scanned_records(WifiManage* wifi);
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,207 +0,0 @@
|
|||||||
#include "WifiManageView.h"
|
|
||||||
|
|
||||||
#include "Log.h"
|
|
||||||
#include "WifiManageState.h"
|
|
||||||
#include "service/statusbar/Statusbar.h"
|
|
||||||
#include "service/wifi/Wifi.h"
|
|
||||||
#include "lvgl/Style.h"
|
|
||||||
#include "lvgl/Toolbar.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
|
||||||
|
|
||||||
#define TAG "wifi_main_view"
|
|
||||||
#define SPINNER_HEIGHT 40
|
|
||||||
|
|
||||||
static void on_enable_switch_changed(lv_event_t* event) {
|
|
||||||
lv_event_code_t code = lv_event_get_code(event);
|
|
||||||
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
|
||||||
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
|
||||||
auto* bindings = static_cast<WifiManageBindings*>(lv_event_get_user_data(event));
|
|
||||||
bindings->on_wifi_toggled(is_on);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_disconnect_pressed(lv_event_t* event) {
|
|
||||||
auto* bindings = static_cast<WifiManageBindings*>(lv_event_get_user_data(event));
|
|
||||||
bindings->on_disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// region Secondary updates
|
|
||||||
|
|
||||||
static void connect(lv_event_t* event) {
|
|
||||||
lv_obj_t* button = lv_event_get_current_target_obj(event);
|
|
||||||
// Assumes that the second child of the button is a label ... risky
|
|
||||||
lv_obj_t* label = lv_obj_get_child(button, 1);
|
|
||||||
// We get the SSID from the button label because it's safer than alloc'ing
|
|
||||||
// our own and passing it as the event data
|
|
||||||
const char* ssid = lv_label_get_text(label);
|
|
||||||
TT_LOG_I(TAG, "Clicked AP: %s", ssid);
|
|
||||||
auto* bindings = static_cast<WifiManageBindings*>(lv_event_get_user_data(event));
|
|
||||||
bindings->on_connect_ssid(ssid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_network_button(WifiManageView* view, WifiManageBindings* bindings, service::wifi::WifiApRecord* record) {
|
|
||||||
const char* ssid = (const char*)record->ssid;
|
|
||||||
const char* icon = service::statusbar::getWifiStatusIconForRssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN);
|
|
||||||
lv_obj_t* ap_button = lv_list_add_btn(
|
|
||||||
view->networks_list,
|
|
||||||
icon,
|
|
||||||
ssid
|
|
||||||
);
|
|
||||||
lv_obj_add_event_cb(ap_button, &connect, LV_EVENT_CLICKED, bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_network_list(WifiManageView* view, WifiManageState* state, WifiManageBindings* bindings) {
|
|
||||||
lv_obj_clean(view->networks_list);
|
|
||||||
switch (state->radio_state) {
|
|
||||||
case service::wifi::WIFI_RADIO_ON_PENDING:
|
|
||||||
case service::wifi::WIFI_RADIO_ON:
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE: {
|
|
||||||
lv_obj_clear_flag(view->networks_label, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
if (state->ap_records_count > 0) {
|
|
||||||
for (int i = 0; i < state->ap_records_count; ++i) {
|
|
||||||
create_network_button(view, bindings, &state->ap_records[i]);
|
|
||||||
}
|
|
||||||
lv_obj_clear_flag(view->networks_list, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
} else if (state->scanning) {
|
|
||||||
lv_obj_add_flag(view->networks_list, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
} else {
|
|
||||||
lv_obj_clear_flag(view->networks_list, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
lv_obj_t* label = lv_label_create(view->networks_list);
|
|
||||||
lv_label_set_text(label, "No networks found.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case service::wifi::WIFI_RADIO_OFF_PENDING:
|
|
||||||
case service::wifi::WIFI_RADIO_OFF: {
|
|
||||||
lv_obj_add_flag(view->networks_list, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
lv_obj_add_flag(view->networks_label, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_scanning(WifiManageView* view, WifiManageState* state) {
|
|
||||||
if (state->radio_state == service::wifi::WIFI_RADIO_ON && state->scanning) {
|
|
||||||
lv_obj_clear_flag(view->scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
} else {
|
|
||||||
lv_obj_add_flag(view->scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_wifi_toggle(WifiManageView* view, WifiManageState* state) {
|
|
||||||
lv_obj_clear_state(view->enable_switch, LV_STATE_ANY);
|
|
||||||
switch (state->radio_state) {
|
|
||||||
case service::wifi::WIFI_RADIO_ON:
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE:
|
|
||||||
lv_obj_add_state(view->enable_switch, LV_STATE_CHECKED);
|
|
||||||
break;
|
|
||||||
case service::wifi::WIFI_RADIO_ON_PENDING:
|
|
||||||
lv_obj_add_state(view->enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED);
|
|
||||||
break;
|
|
||||||
case service::wifi::WIFI_RADIO_OFF:
|
|
||||||
lv_obj_remove_state(view->enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED);
|
|
||||||
break;
|
|
||||||
case service::wifi::WIFI_RADIO_OFF_PENDING:
|
|
||||||
lv_obj_remove_state(view->enable_switch, LV_STATE_CHECKED);
|
|
||||||
lv_obj_add_state(view->enable_switch, LV_STATE_DISABLED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_connected_ap(WifiManageView* view, WifiManageState* state, TT_UNUSED WifiManageBindings* bindings) {
|
|
||||||
switch (state->radio_state) {
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_PENDING:
|
|
||||||
case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE:
|
|
||||||
lv_obj_clear_flag(view->connected_ap_container, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
lv_label_set_text(view->connected_ap_label, (const char*)state->connect_ssid);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lv_obj_add_flag(view->connected_ap_container, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion Secondary updates
|
|
||||||
|
|
||||||
// region Main
|
|
||||||
|
|
||||||
void view_create(const App& app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent) {
|
|
||||||
view->root = parent;
|
|
||||||
|
|
||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lvgl::toolbar_create(parent, app);
|
|
||||||
|
|
||||||
lv_obj_t* wrapper = lv_obj_create(parent);
|
|
||||||
lv_obj_set_width(wrapper, LV_PCT(100));
|
|
||||||
lv_obj_set_flex_grow(wrapper, 1);
|
|
||||||
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
|
||||||
|
|
||||||
// Top row: enable/disable
|
|
||||||
lv_obj_t* switch_container = lv_obj_create(wrapper);
|
|
||||||
lv_obj_set_width(switch_container, LV_PCT(100));
|
|
||||||
lv_obj_set_height(switch_container, LV_SIZE_CONTENT);
|
|
||||||
lvgl::obj_set_style_no_padding(switch_container);
|
|
||||||
lvgl::obj_set_style_bg_invisible(switch_container);
|
|
||||||
|
|
||||||
lv_obj_t* enable_label = lv_label_create(switch_container);
|
|
||||||
lv_label_set_text(enable_label, "Wi-Fi");
|
|
||||||
lv_obj_set_align(enable_label, LV_ALIGN_LEFT_MID);
|
|
||||||
|
|
||||||
view->enable_switch = lv_switch_create(switch_container);
|
|
||||||
lv_obj_add_event_cb(view->enable_switch, on_enable_switch_changed, LV_EVENT_ALL, bindings);
|
|
||||||
lv_obj_set_align(view->enable_switch, LV_ALIGN_RIGHT_MID);
|
|
||||||
|
|
||||||
view->connected_ap_container = lv_obj_create(wrapper);
|
|
||||||
lv_obj_set_size(view->connected_ap_container, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_min_height(view->connected_ap_container, SPINNER_HEIGHT, 0);
|
|
||||||
lvgl::obj_set_style_no_padding(view->connected_ap_container);
|
|
||||||
lv_obj_set_style_border_width(view->connected_ap_container, 0, 0);
|
|
||||||
|
|
||||||
view->connected_ap_label = lv_label_create(view->connected_ap_container);
|
|
||||||
lv_obj_align(view->connected_ap_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
lv_obj_t* disconnect_button = lv_btn_create(view->connected_ap_container);
|
|
||||||
lv_obj_add_event_cb(disconnect_button, &on_disconnect_pressed, LV_EVENT_CLICKED, bindings);
|
|
||||||
lv_obj_t* disconnect_label = lv_label_create(disconnect_button);
|
|
||||||
lv_label_set_text(disconnect_label, "Disconnect");
|
|
||||||
lv_obj_align(disconnect_button, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
|
|
||||||
// Networks
|
|
||||||
|
|
||||||
lv_obj_t* networks_header = lv_obj_create(wrapper);
|
|
||||||
lv_obj_set_size(networks_header, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_min_height(networks_header, SPINNER_HEIGHT, 0);
|
|
||||||
lvgl::obj_set_style_no_padding(networks_header);
|
|
||||||
lv_obj_set_style_border_width(networks_header, 0, 0);
|
|
||||||
|
|
||||||
view->networks_label = lv_label_create(networks_header);
|
|
||||||
lv_label_set_text(view->networks_label, "Networks");
|
|
||||||
lv_obj_align(view->networks_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
view->scanning_spinner = lv_spinner_create(networks_header);
|
|
||||||
lv_spinner_set_anim_params(view->scanning_spinner, 1000, 60);
|
|
||||||
lv_obj_set_size(view->scanning_spinner, SPINNER_HEIGHT, SPINNER_HEIGHT);
|
|
||||||
lv_obj_set_style_pad_top(view->scanning_spinner, 4, 0);
|
|
||||||
lv_obj_set_style_pad_bottom(view->scanning_spinner, 4, 0);
|
|
||||||
lv_obj_align_to(view->scanning_spinner, view->networks_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0);
|
|
||||||
|
|
||||||
view->networks_list = lv_obj_create(wrapper);
|
|
||||||
lv_obj_set_flex_flow(view->networks_list, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lv_obj_set_width(view->networks_list, LV_PCT(100));
|
|
||||||
lv_obj_set_height(view->networks_list, LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_top(view->networks_list, 8, 0);
|
|
||||||
lv_obj_set_style_pad_bottom(view->networks_list, 8, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void view_update(WifiManageView* view, WifiManageBindings* bindings, WifiManageState* state) {
|
|
||||||
update_wifi_toggle(view, state);
|
|
||||||
update_scanning(view, state);
|
|
||||||
update_network_list(view, state, bindings);
|
|
||||||
update_connected_ap(view, state, bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "app/App.h"
|
|
||||||
#include "WifiManageBindings.h"
|
|
||||||
#include "WifiManageState.h"
|
|
||||||
#include "lvgl.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
lv_obj_t* root;
|
|
||||||
lv_obj_t* enable_switch;
|
|
||||||
lv_obj_t* scanning_spinner;
|
|
||||||
lv_obj_t* networks_label;
|
|
||||||
lv_obj_t* networks_list;
|
|
||||||
lv_obj_t* connected_ap_container;
|
|
||||||
lv_obj_t* connected_ap_label;
|
|
||||||
} WifiManageView;
|
|
||||||
|
|
||||||
void view_create(const App& app, WifiManageView* view, WifiManageBindings* bindings, lv_obj_t* parent);
|
|
||||||
void view_update(WifiManageView* view, WifiManageBindings* bindings, WifiManageState* state);
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -53,7 +53,7 @@ TT_NORETURN void tt_crash_implementation();
|
|||||||
* @param optional message (const char*)
|
* @param optional message (const char*)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define tt_check(x, ...) if (!(x)) { TT_LOG_E("check", "Failed: %s", #x); tt_crash_implementation(); };
|
#define tt_check(x, ...) if (!(x)) { TT_LOG_E("check", "Failed: %s", #x); tt_crash_implementation(); }
|
||||||
|
|
||||||
/** Only in debug build: Assert condition and crash if assert failed */
|
/** Only in debug build: Assert condition and crash if assert failed */
|
||||||
#ifdef TT_DEBUG
|
#ifdef TT_DEBUG
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
#include "WifiGlobals.h"
|
#include "WifiGlobals.h"
|
||||||
#include "WifiSettings.h"
|
#include "WifiSettings.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
@ -32,7 +34,7 @@ typedef enum {
|
|||||||
|
|
||||||
namespace tt::service::wifi {
|
namespace tt::service::wifi {
|
||||||
|
|
||||||
typedef enum {
|
enum WifiEventType {
|
||||||
/** Radio was turned on */
|
/** Radio was turned on */
|
||||||
WifiEventTypeRadioStateOn,
|
WifiEventTypeRadioStateOn,
|
||||||
/** Radio is turning on. */
|
/** Radio is turning on. */
|
||||||
@ -49,26 +51,26 @@ typedef enum {
|
|||||||
WifiEventTypeConnectionPending,
|
WifiEventTypeConnectionPending,
|
||||||
WifiEventTypeConnectionSuccess,
|
WifiEventTypeConnectionSuccess,
|
||||||
WifiEventTypeConnectionFailed
|
WifiEventTypeConnectionFailed
|
||||||
} WifiEventType;
|
};
|
||||||
|
|
||||||
typedef enum {
|
enum WifiRadioState {
|
||||||
WIFI_RADIO_ON_PENDING,
|
WIFI_RADIO_ON_PENDING,
|
||||||
WIFI_RADIO_ON,
|
WIFI_RADIO_ON,
|
||||||
WIFI_RADIO_CONNECTION_PENDING,
|
WIFI_RADIO_CONNECTION_PENDING,
|
||||||
WIFI_RADIO_CONNECTION_ACTIVE,
|
WIFI_RADIO_CONNECTION_ACTIVE,
|
||||||
WIFI_RADIO_OFF_PENDING,
|
WIFI_RADIO_OFF_PENDING,
|
||||||
WIFI_RADIO_OFF
|
WIFI_RADIO_OFF
|
||||||
} WifiRadioState;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct WifiEvent {
|
||||||
WifiEventType type;
|
WifiEventType type;
|
||||||
} WifiEvent;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct WifiApRecord {
|
||||||
uint8_t ssid[TT_WIFI_SSID_LIMIT + 1];
|
std::string ssid;
|
||||||
int8_t rssi;
|
int8_t rssi;
|
||||||
wifi_auth_mode_t auth_mode;
|
wifi_auth_mode_t auth_mode;
|
||||||
} WifiApRecord;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get wifi pubsub
|
* @brief Get wifi pubsub
|
||||||
@ -89,10 +91,8 @@ bool isScanning();
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the access points from the last scan (if any). It only contains public APs.
|
* @brief Returns the access points from the last scan (if any). It only contains public APs.
|
||||||
* @param records the allocated buffer to store the records in
|
|
||||||
* @param limit the maximum amount of records to store
|
|
||||||
*/
|
*/
|
||||||
void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count);
|
std::vector<WifiApRecord> getScanResults();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Overrides the default scan result size of 16.
|
* @brief Overrides the default scan result size of 16.
|
||||||
|
|||||||
@ -21,6 +21,7 @@ namespace tt::service::wifi {
|
|||||||
#define TAG "wifi_service"
|
#define TAG "wifi_service"
|
||||||
#define WIFI_CONNECTED_BIT BIT0
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
#define WIFI_FAIL_BIT BIT1
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
#define AUTO_SCAN_INTERVAL 10000 // ms
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WifiMessageTypeRadioOn,
|
WifiMessageTypeRadioOn,
|
||||||
@ -65,6 +66,8 @@ public:
|
|||||||
/** @brief Maximum amount of records to scan (value > 0) */
|
/** @brief Maximum amount of records to scan (value > 0) */
|
||||||
uint16_t scan_list_limit = TT_WIFI_SCAN_RECORD_LIMIT;
|
uint16_t scan_list_limit = TT_WIFI_SCAN_RECORD_LIMIT;
|
||||||
bool scan_active = false;
|
bool scan_active = false;
|
||||||
|
/** @brief when we last requested a scan. Loops around every 50 days. */
|
||||||
|
TickType_t last_scan_time;
|
||||||
bool secure_connection = false;
|
bool secure_connection = false;
|
||||||
esp_event_handler_instance_t event_handler_any_id = nullptr;
|
esp_event_handler_instance_t event_handler_any_id = nullptr;
|
||||||
esp_event_handler_instance_t event_handler_got_ip = nullptr;
|
esp_event_handler_instance_t event_handler_got_ip = nullptr;
|
||||||
@ -74,6 +77,7 @@ public:
|
|||||||
.password = { 0 },
|
.password = { 0 },
|
||||||
.auto_connect = false
|
.auto_connect = false
|
||||||
};
|
};
|
||||||
|
bool pause_auto_connect = false; // Pause when manually disconnecting until manually connecting again
|
||||||
bool connection_target_remember = false; // Whether to store the connection_target on successful connection or not
|
bool connection_target_remember = false; // Whether to store the connection_target on successful connection or not
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,6 +117,7 @@ WifiRadioState getRadioState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scan() {
|
void scan() {
|
||||||
|
TT_LOG_I(TAG, "scan()");
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
WifiMessage message = {.type = WifiMessageTypeScan};
|
WifiMessage message = {.type = WifiMessageTypeScan};
|
||||||
@ -130,16 +135,19 @@ bool isScanning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void connect(const settings::WifiApSettings* ap, bool remember) {
|
void connect(const settings::WifiApSettings* ap, bool remember) {
|
||||||
|
TT_LOG_I(TAG, "connect(%s, %d)", ap->ssid, remember);
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
memcpy(&wifi_singleton->connection_target, ap, sizeof(settings::WifiApSettings));
|
memcpy(&wifi_singleton->connection_target, ap, sizeof(settings::WifiApSettings));
|
||||||
wifi_singleton->connection_target_remember = remember;
|
wifi_singleton->connection_target_remember = remember;
|
||||||
|
wifi_singleton->pause_auto_connect = false;
|
||||||
WifiMessage message = {.type = WifiMessageTypeConnect};
|
WifiMessage message = {.type = WifiMessageTypeConnect};
|
||||||
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
||||||
unlock(wifi_singleton);
|
unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disconnect() {
|
void disconnect() {
|
||||||
|
TT_LOG_I(TAG, "disconnect()");
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
wifi_singleton->connection_target = (settings::WifiApSettings) {
|
wifi_singleton->connection_target = (settings::WifiApSettings) {
|
||||||
@ -147,12 +155,14 @@ void disconnect() {
|
|||||||
.password = { 0 },
|
.password = { 0 },
|
||||||
.auto_connect = false
|
.auto_connect = false
|
||||||
};
|
};
|
||||||
|
wifi_singleton->pause_auto_connect = true;
|
||||||
WifiMessage message = {.type = WifiMessageTypeDisconnect};
|
WifiMessage message = {.type = WifiMessageTypeDisconnect};
|
||||||
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
||||||
unlock(wifi_singleton);
|
unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScanRecords(uint16_t records) {
|
void setScanRecords(uint16_t records) {
|
||||||
|
TT_LOG_I(TAG, "setScanRecords(%d)", records);
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
if (records != wifi_singleton->scan_list_limit) {
|
if (records != wifi_singleton->scan_list_limit) {
|
||||||
@ -162,30 +172,30 @@ void setScanRecords(uint16_t records) {
|
|||||||
unlock(wifi_singleton);
|
unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count) {
|
std::vector<WifiApRecord> getScanResults() {
|
||||||
|
TT_LOG_I(TAG, "getScanResults()");
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
tt_assert(result_count);
|
|
||||||
|
std::vector<WifiApRecord> records;
|
||||||
|
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
if (wifi_singleton->scan_list_count == 0) {
|
if (wifi_singleton->scan_list_count > 0) {
|
||||||
*result_count = 0;
|
|
||||||
} else {
|
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
TT_LOG_I(TAG, "processing up to %d APs", wifi_singleton->scan_list_count);
|
for (; i < wifi_singleton->scan_list_count; ++i) {
|
||||||
uint16_t last_index = TT_MIN(wifi_singleton->scan_list_count, limit);
|
records.push_back((WifiApRecord) {
|
||||||
for (; i < last_index; ++i) {
|
.ssid = (const char*)wifi_singleton->scan_list[i].ssid,
|
||||||
memcpy(records[i].ssid, wifi_singleton->scan_list[i].ssid, 33);
|
.rssi = wifi_singleton->scan_list[i].rssi,
|
||||||
records[i].rssi = wifi_singleton->scan_list[i].rssi;
|
.auth_mode = wifi_singleton->scan_list[i].authmode
|
||||||
records[i].auth_mode = wifi_singleton->scan_list[i].authmode;
|
});
|
||||||
}
|
}
|
||||||
// The index already overflowed right before the for-loop was terminated,
|
|
||||||
// so it effectively became the list count:
|
|
||||||
*result_count = i;
|
|
||||||
}
|
}
|
||||||
unlock(wifi_singleton);
|
unlock(wifi_singleton);
|
||||||
|
|
||||||
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnabled(bool enabled) {
|
void setEnabled(bool enabled) {
|
||||||
|
TT_LOG_I(TAG, "setEnabled(%d)", enabled);
|
||||||
tt_assert(wifi_singleton);
|
tt_assert(wifi_singleton);
|
||||||
lock(wifi_singleton);
|
lock(wifi_singleton);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
@ -196,7 +206,10 @@ void setEnabled(bool enabled) {
|
|||||||
WifiMessage message = {.type = WifiMessageTypeRadioOff};
|
WifiMessage message = {.type = WifiMessageTypeRadioOff};
|
||||||
// No need to lock for queue
|
// No need to lock for queue
|
||||||
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
||||||
|
// Reset pause state
|
||||||
}
|
}
|
||||||
|
wifi_singleton->pause_auto_connect = false;
|
||||||
|
wifi_singleton->last_scan_time = 0;
|
||||||
unlock(wifi_singleton);
|
unlock(wifi_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +295,7 @@ static bool copy_scan_list(Wifi* wifi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void auto_connect(Wifi* wifi) {
|
static void auto_connect(Wifi* wifi) {
|
||||||
|
TT_LOG_I(TAG, "auto_connect()");
|
||||||
for (int i = 0; i < wifi->scan_list_count; ++i) {
|
for (int i = 0; i < wifi->scan_list_count; ++i) {
|
||||||
auto ssid = reinterpret_cast<const char*>(wifi->scan_list[i].ssid);
|
auto ssid = reinterpret_cast<const char*>(wifi->scan_list[i].ssid);
|
||||||
if (settings::contains(ssid)) {
|
if (settings::contains(ssid)) {
|
||||||
@ -489,6 +503,7 @@ static void scan_internal(Wifi* wifi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!wifi->scan_active) {
|
if (!wifi->scan_active) {
|
||||||
|
wifi->last_scan_time = tt::get_ticks();
|
||||||
if (esp_wifi_scan_start(nullptr, false) == ESP_OK) {
|
if (esp_wifi_scan_start(nullptr, false) == ESP_OK) {
|
||||||
TT_LOG_I(TAG, "Starting scan");
|
TT_LOG_I(TAG, "Starting scan");
|
||||||
wifi->scan_active = true;
|
wifi->scan_active = true;
|
||||||
@ -664,6 +679,18 @@ static void disconnect_internal_but_keep_active(Wifi* wifi) {
|
|||||||
TT_LOG_I(TAG, "Disconnected");
|
TT_LOG_I(TAG, "Disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool shouldScanForAutoConnect(Wifi* wifi) {
|
||||||
|
bool is_radio_in_scannable_state = wifi->radio_state == WIFI_RADIO_ON && !wifi->scan_active;
|
||||||
|
if (!wifi->pause_auto_connect && is_radio_in_scannable_state) {
|
||||||
|
TickType_t current_time = tt::get_ticks();
|
||||||
|
bool scan_time_has_looped = (current_time < wifi->last_scan_time);
|
||||||
|
bool no_recent_scan = (current_time - wifi->last_scan_time) > (AUTO_SCAN_INTERVAL / portTICK_PERIOD_MS);
|
||||||
|
return scan_time_has_looped || no_recent_scan;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ESP Wi-Fi APIs need to run from the main task, so we can't just spawn a thread
|
// ESP Wi-Fi APIs need to run from the main task, so we can't just spawn a thread
|
||||||
_Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
_Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
||||||
TT_LOG_I(TAG, "Started main loop");
|
TT_LOG_I(TAG, "Started main loop");
|
||||||
@ -678,6 +705,7 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
|||||||
|
|
||||||
WifiMessage message;
|
WifiMessage message;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
TT_LOG_I(TAG, "Message queue %ld", queue.getCount());
|
||||||
if (queue.get(&message, 10000 / portTICK_PERIOD_MS) == TtStatusOk) {
|
if (queue.get(&message, 10000 / portTICK_PERIOD_MS) == TtStatusOk) {
|
||||||
TT_LOG_I(TAG, "Processing message of type %d", message.type);
|
TT_LOG_I(TAG, "Processing message of type %d", message.type);
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
@ -708,7 +736,9 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
|||||||
break;
|
break;
|
||||||
case WifiMessageTypeAutoConnect:
|
case WifiMessageTypeAutoConnect:
|
||||||
lock(wifi);
|
lock(wifi);
|
||||||
auto_connect(wifi_singleton);
|
if (!wifi->pause_auto_connect) {
|
||||||
|
auto_connect(wifi_singleton);
|
||||||
|
}
|
||||||
unlock(wifi);
|
unlock(wifi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -716,9 +746,9 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
|||||||
|
|
||||||
// Automatic scanning is done so we can automatically connect to access points
|
// Automatic scanning is done so we can automatically connect to access points
|
||||||
lock(wifi);
|
lock(wifi);
|
||||||
bool should_start_scan = wifi->radio_state == WIFI_RADIO_ON && !wifi->scan_active;
|
bool should_auto_scan = shouldScanForAutoConnect(wifi);
|
||||||
unlock(wifi);
|
unlock(wifi);
|
||||||
if (should_start_scan) {
|
if (should_auto_scan) {
|
||||||
scan_internal(wifi);
|
scan_internal(wifi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,34 +100,41 @@ void setScanRecords(uint16_t records) {
|
|||||||
// TODO: implement
|
// TODO: implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count) {
|
std::vector<WifiApRecord> getScanResults() {
|
||||||
tt_check(wifi);
|
tt_check(wifi);
|
||||||
tt_check(result_count);
|
|
||||||
|
|
||||||
if (limit >= 5) {
|
std::vector<WifiApRecord> records;
|
||||||
strcpy((char*)records[0].ssid, "Home WiFi");
|
records.push_back((WifiApRecord) {
|
||||||
records[0].auth_mode = WIFI_AUTH_WPA2_PSK;
|
.ssid = "Home Wifi",
|
||||||
records[0].rssi = -30;
|
.rssi = -30,
|
||||||
strcpy((char*)records[1].ssid, "Living Room");
|
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||||
records[1].auth_mode = WIFI_AUTH_WPA2_PSK;
|
});
|
||||||
records[1].rssi = -67;
|
records.push_back((WifiApRecord) {
|
||||||
strcpy((char*)records[2].ssid, "No place like 127.0.0.1");
|
.ssid = "Living Room",
|
||||||
records[2].auth_mode = WIFI_AUTH_WPA2_PSK;
|
.rssi = -67,
|
||||||
records[2].rssi = -70;
|
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||||
strcpy((char*)records[3].ssid, "Public Wi-Fi");
|
});
|
||||||
records[3].auth_mode = WIFI_AUTH_WPA2_PSK;
|
records.push_back((WifiApRecord) {
|
||||||
records[3].rssi = -80;
|
.ssid = "No place like 127.0.0.1",
|
||||||
strcpy((char*)records[4].ssid, "Bad Reception");
|
.rssi = -70,
|
||||||
records[4].auth_mode = WIFI_AUTH_WPA2_PSK;
|
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||||
records[4].rssi = -90;
|
});
|
||||||
*result_count = 5;
|
records.push_back((WifiApRecord) {
|
||||||
} else {
|
.ssid = "Public Wi-Fi",
|
||||||
*result_count = 0;
|
.rssi = -80,
|
||||||
}
|
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||||
|
});
|
||||||
|
records.push_back((WifiApRecord) {
|
||||||
|
.ssid = "Bad Reception",
|
||||||
|
.rssi = -90,
|
||||||
|
.auth_mode = WIFI_AUTH_OPEN
|
||||||
|
});
|
||||||
|
|
||||||
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnabled(bool enabled) {
|
void setEnabled(bool enabled) {
|
||||||
tt_assert(wifi != NULL);
|
tt_assert(wifi != nullptr);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
wifi->radio_state = WIFI_RADIO_ON;
|
wifi->radio_state = WIFI_RADIO_ON;
|
||||||
wifi->secure_connection = true;
|
wifi->secure_connection = true;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user