WiFi fixes and improvements (#100)
This commit is contained in:
committed by
GitHub
parent
33bb742dfb
commit
e9c02ab58e
@@ -4,6 +4,8 @@
|
||||
#include "WifiGlobals.h"
|
||||
#include "WifiSettings.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_wifi.h"
|
||||
@@ -32,7 +34,7 @@ typedef enum {
|
||||
|
||||
namespace tt::service::wifi {
|
||||
|
||||
typedef enum {
|
||||
enum WifiEventType {
|
||||
/** Radio was turned on */
|
||||
WifiEventTypeRadioStateOn,
|
||||
/** Radio is turning on. */
|
||||
@@ -49,26 +51,26 @@ typedef enum {
|
||||
WifiEventTypeConnectionPending,
|
||||
WifiEventTypeConnectionSuccess,
|
||||
WifiEventTypeConnectionFailed
|
||||
} WifiEventType;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum WifiRadioState {
|
||||
WIFI_RADIO_ON_PENDING,
|
||||
WIFI_RADIO_ON,
|
||||
WIFI_RADIO_CONNECTION_PENDING,
|
||||
WIFI_RADIO_CONNECTION_ACTIVE,
|
||||
WIFI_RADIO_OFF_PENDING,
|
||||
WIFI_RADIO_OFF
|
||||
} WifiRadioState;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct WifiEvent {
|
||||
WifiEventType type;
|
||||
} WifiEvent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t ssid[TT_WIFI_SSID_LIMIT + 1];
|
||||
struct WifiApRecord {
|
||||
std::string ssid;
|
||||
int8_t rssi;
|
||||
wifi_auth_mode_t auth_mode;
|
||||
} WifiApRecord;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @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.
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace tt::service::wifi {
|
||||
#define TAG "wifi_service"
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
#define AUTO_SCAN_INTERVAL 10000 // ms
|
||||
|
||||
typedef enum {
|
||||
WifiMessageTypeRadioOn,
|
||||
@@ -65,6 +66,8 @@ public:
|
||||
/** @brief Maximum amount of records to scan (value > 0) */
|
||||
uint16_t scan_list_limit = TT_WIFI_SCAN_RECORD_LIMIT;
|
||||
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;
|
||||
esp_event_handler_instance_t event_handler_any_id = nullptr;
|
||||
esp_event_handler_instance_t event_handler_got_ip = nullptr;
|
||||
@@ -74,6 +77,7 @@ public:
|
||||
.password = { 0 },
|
||||
.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
|
||||
};
|
||||
|
||||
@@ -113,6 +117,7 @@ WifiRadioState getRadioState() {
|
||||
}
|
||||
|
||||
void scan() {
|
||||
TT_LOG_I(TAG, "scan()");
|
||||
tt_assert(wifi_singleton);
|
||||
lock(wifi_singleton);
|
||||
WifiMessage message = {.type = WifiMessageTypeScan};
|
||||
@@ -130,16 +135,19 @@ bool isScanning() {
|
||||
}
|
||||
|
||||
void connect(const settings::WifiApSettings* ap, bool remember) {
|
||||
TT_LOG_I(TAG, "connect(%s, %d)", ap->ssid, remember);
|
||||
tt_assert(wifi_singleton);
|
||||
lock(wifi_singleton);
|
||||
memcpy(&wifi_singleton->connection_target, ap, sizeof(settings::WifiApSettings));
|
||||
wifi_singleton->connection_target_remember = remember;
|
||||
wifi_singleton->pause_auto_connect = false;
|
||||
WifiMessage message = {.type = WifiMessageTypeConnect};
|
||||
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
||||
unlock(wifi_singleton);
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
TT_LOG_I(TAG, "disconnect()");
|
||||
tt_assert(wifi_singleton);
|
||||
lock(wifi_singleton);
|
||||
wifi_singleton->connection_target = (settings::WifiApSettings) {
|
||||
@@ -147,12 +155,14 @@ void disconnect() {
|
||||
.password = { 0 },
|
||||
.auto_connect = false
|
||||
};
|
||||
wifi_singleton->pause_auto_connect = true;
|
||||
WifiMessage message = {.type = WifiMessageTypeDisconnect};
|
||||
wifi_singleton->queue.put(&message, 100 / portTICK_PERIOD_MS);
|
||||
unlock(wifi_singleton);
|
||||
}
|
||||
|
||||
void setScanRecords(uint16_t records) {
|
||||
TT_LOG_I(TAG, "setScanRecords(%d)", records);
|
||||
tt_assert(wifi_singleton);
|
||||
lock(wifi_singleton);
|
||||
if (records != wifi_singleton->scan_list_limit) {
|
||||
@@ -162,30 +172,30 @@ void setScanRecords(uint16_t records) {
|
||||
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(result_count);
|
||||
|
||||
std::vector<WifiApRecord> records;
|
||||
|
||||
lock(wifi_singleton);
|
||||
if (wifi_singleton->scan_list_count == 0) {
|
||||
*result_count = 0;
|
||||
} else {
|
||||
if (wifi_singleton->scan_list_count > 0) {
|
||||
uint16_t i = 0;
|
||||
TT_LOG_I(TAG, "processing up to %d APs", wifi_singleton->scan_list_count);
|
||||
uint16_t last_index = TT_MIN(wifi_singleton->scan_list_count, limit);
|
||||
for (; i < last_index; ++i) {
|
||||
memcpy(records[i].ssid, wifi_singleton->scan_list[i].ssid, 33);
|
||||
records[i].rssi = wifi_singleton->scan_list[i].rssi;
|
||||
records[i].auth_mode = wifi_singleton->scan_list[i].authmode;
|
||||
for (; i < wifi_singleton->scan_list_count; ++i) {
|
||||
records.push_back((WifiApRecord) {
|
||||
.ssid = (const char*)wifi_singleton->scan_list[i].ssid,
|
||||
.rssi = wifi_singleton->scan_list[i].rssi,
|
||||
.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);
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
void setEnabled(bool enabled) {
|
||||
TT_LOG_I(TAG, "setEnabled(%d)", enabled);
|
||||
tt_assert(wifi_singleton);
|
||||
lock(wifi_singleton);
|
||||
if (enabled) {
|
||||
@@ -196,7 +206,10 @@ void setEnabled(bool enabled) {
|
||||
WifiMessage message = {.type = WifiMessageTypeRadioOff};
|
||||
// No need to lock for queue
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -282,6 +295,7 @@ static bool copy_scan_list(Wifi* wifi) {
|
||||
}
|
||||
|
||||
static void auto_connect(Wifi* wifi) {
|
||||
TT_LOG_I(TAG, "auto_connect()");
|
||||
for (int i = 0; i < wifi->scan_list_count; ++i) {
|
||||
auto ssid = reinterpret_cast<const char*>(wifi->scan_list[i].ssid);
|
||||
if (settings::contains(ssid)) {
|
||||
@@ -489,6 +503,7 @@ static void scan_internal(Wifi* wifi) {
|
||||
}
|
||||
|
||||
if (!wifi->scan_active) {
|
||||
wifi->last_scan_time = tt::get_ticks();
|
||||
if (esp_wifi_scan_start(nullptr, false) == ESP_OK) {
|
||||
TT_LOG_I(TAG, "Starting scan");
|
||||
wifi->scan_active = true;
|
||||
@@ -664,6 +679,18 @@ static void disconnect_internal_but_keep_active(Wifi* wifi) {
|
||||
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
|
||||
_Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
||||
TT_LOG_I(TAG, "Started main loop");
|
||||
@@ -678,6 +705,7 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
||||
|
||||
WifiMessage message;
|
||||
while (true) {
|
||||
TT_LOG_I(TAG, "Message queue %ld", queue.getCount());
|
||||
if (queue.get(&message, 10000 / portTICK_PERIOD_MS) == TtStatusOk) {
|
||||
TT_LOG_I(TAG, "Processing message of type %d", message.type);
|
||||
switch (message.type) {
|
||||
@@ -708,7 +736,9 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
|
||||
break;
|
||||
case WifiMessageTypeAutoConnect:
|
||||
lock(wifi);
|
||||
auto_connect(wifi_singleton);
|
||||
if (!wifi->pause_auto_connect) {
|
||||
auto_connect(wifi_singleton);
|
||||
}
|
||||
unlock(wifi);
|
||||
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
|
||||
lock(wifi);
|
||||
bool should_start_scan = wifi->radio_state == WIFI_RADIO_ON && !wifi->scan_active;
|
||||
bool should_auto_scan = shouldScanForAutoConnect(wifi);
|
||||
unlock(wifi);
|
||||
if (should_start_scan) {
|
||||
if (should_auto_scan) {
|
||||
scan_internal(wifi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,34 +100,41 @@ void setScanRecords(uint16_t records) {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count) {
|
||||
std::vector<WifiApRecord> getScanResults() {
|
||||
tt_check(wifi);
|
||||
tt_check(result_count);
|
||||
|
||||
if (limit >= 5) {
|
||||
strcpy((char*)records[0].ssid, "Home WiFi");
|
||||
records[0].auth_mode = WIFI_AUTH_WPA2_PSK;
|
||||
records[0].rssi = -30;
|
||||
strcpy((char*)records[1].ssid, "Living Room");
|
||||
records[1].auth_mode = WIFI_AUTH_WPA2_PSK;
|
||||
records[1].rssi = -67;
|
||||
strcpy((char*)records[2].ssid, "No place like 127.0.0.1");
|
||||
records[2].auth_mode = WIFI_AUTH_WPA2_PSK;
|
||||
records[2].rssi = -70;
|
||||
strcpy((char*)records[3].ssid, "Public Wi-Fi");
|
||||
records[3].auth_mode = WIFI_AUTH_WPA2_PSK;
|
||||
records[3].rssi = -80;
|
||||
strcpy((char*)records[4].ssid, "Bad Reception");
|
||||
records[4].auth_mode = WIFI_AUTH_WPA2_PSK;
|
||||
records[4].rssi = -90;
|
||||
*result_count = 5;
|
||||
} else {
|
||||
*result_count = 0;
|
||||
}
|
||||
std::vector<WifiApRecord> records;
|
||||
records.push_back((WifiApRecord) {
|
||||
.ssid = "Home Wifi",
|
||||
.rssi = -30,
|
||||
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||
});
|
||||
records.push_back((WifiApRecord) {
|
||||
.ssid = "Living Room",
|
||||
.rssi = -67,
|
||||
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||
});
|
||||
records.push_back((WifiApRecord) {
|
||||
.ssid = "No place like 127.0.0.1",
|
||||
.rssi = -70,
|
||||
.auth_mode = WIFI_AUTH_WPA2_PSK
|
||||
});
|
||||
records.push_back((WifiApRecord) {
|
||||
.ssid = "Public Wi-Fi",
|
||||
.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) {
|
||||
tt_assert(wifi != NULL);
|
||||
tt_assert(wifi != nullptr);
|
||||
if (enabled) {
|
||||
wifi->radio_state = WIFI_RADIO_ON;
|
||||
wifi->secure_connection = true;
|
||||
|
||||
Reference in New Issue
Block a user