mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-30 03:23:45 +02:00
Add PoC support for BSSID
This commit is contained in:
@@ -6,42 +6,6 @@ static const char* TAG = "WiFiScanner";
|
||||
|
||||
WiFiScanner::WiFiScanner() {}
|
||||
|
||||
void WiFiScanner::scanResultCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
||||
{
|
||||
auto* scanner = static_cast<WiFiScanner*>(arg);
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE)
|
||||
{
|
||||
uint16_t ap_count = 0;
|
||||
esp_wifi_scan_get_ap_num(&ap_count);
|
||||
|
||||
if (ap_count == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "No access points found");
|
||||
return;
|
||||
}
|
||||
|
||||
wifi_ap_record_t* ap_records = new wifi_ap_record_t[ap_count];
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_count, ap_records));
|
||||
|
||||
scanner->networks.clear();
|
||||
for (uint16_t i = 0; i < ap_count; i++)
|
||||
{
|
||||
WiFiNetwork network;
|
||||
network.ssid = std::string(reinterpret_cast<char*>(ap_records[i].ssid));
|
||||
network.channel = ap_records[i].primary;
|
||||
network.rssi = ap_records[i].rssi;
|
||||
memcpy(network.mac, ap_records[i].bssid, 6);
|
||||
network.auth_mode = ap_records[i].authmode;
|
||||
|
||||
scanner->networks.push_back(network);
|
||||
}
|
||||
|
||||
delete[] ap_records;
|
||||
ESP_LOGI(TAG, "Found %d access points", ap_count);
|
||||
}
|
||||
}
|
||||
|
||||
// todo this is garbage
|
||||
std::vector<WiFiNetwork> WiFiScanner::scanNetworks(int timeout_ms)
|
||||
{
|
||||
std::vector<WiFiNetwork> scan_results;
|
||||
@@ -61,176 +25,67 @@ std::vector<WiFiNetwork> WiFiScanner::scanNetworks(int timeout_ms)
|
||||
// Stop any ongoing scan
|
||||
esp_wifi_scan_stop();
|
||||
|
||||
// Try sequential channel scanning as a workaround
|
||||
bool try_sequential_scan = true; // Enable sequential scan
|
||||
|
||||
if (!try_sequential_scan)
|
||||
{
|
||||
// Normal all-channel scan
|
||||
wifi_scan_config_t scan_config = {
|
||||
.ssid = nullptr,
|
||||
.bssid = nullptr,
|
||||
.channel = 0, // 0 means scan all channels
|
||||
.show_hidden = true,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE, // Active scan
|
||||
.scan_time = {.active =
|
||||
{
|
||||
.min = 120, // Min per channel
|
||||
.max = 300 // Max per channel
|
||||
},
|
||||
.passive = 360},
|
||||
.home_chan_dwell_time = 0, // 0 for default
|
||||
.channel_bitmap = 0 // 0 for all channels
|
||||
};
|
||||
|
||||
err = esp_wifi_scan_start(&scan_config, false);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to start scan: %s", esp_err_to_name(err));
|
||||
return scan_results;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sequential channel scan - scan each channel individually with timeout tracking
|
||||
std::vector<wifi_ap_record_t> all_records;
|
||||
int64_t start_time = esp_timer_get_time() / 1000; // Convert to ms
|
||||
|
||||
for (uint8_t ch = 1; ch <= 13; ch++)
|
||||
{
|
||||
// Check if we've exceeded the timeout
|
||||
int64_t current_time = esp_timer_get_time() / 1000;
|
||||
int64_t elapsed = current_time - start_time;
|
||||
|
||||
if (elapsed >= timeout_ms)
|
||||
{
|
||||
ESP_LOGW(TAG, "Sequential scan timeout after %lld ms at channel %d", elapsed, ch);
|
||||
break;
|
||||
}
|
||||
|
||||
wifi_scan_config_t scan_config = {.ssid = nullptr,
|
||||
.bssid = nullptr,
|
||||
.channel = ch,
|
||||
.show_hidden = true,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
.scan_time = {.active = {.min = 100, .max = 200}, .passive = 300},
|
||||
.home_chan_dwell_time = 0,
|
||||
.channel_bitmap = 0};
|
||||
|
||||
err = esp_wifi_scan_start(&scan_config, true); // Blocking scan
|
||||
if (err == ESP_OK)
|
||||
{
|
||||
uint16_t ch_count = 0;
|
||||
esp_wifi_scan_get_ap_num(&ch_count);
|
||||
if (ch_count > 0)
|
||||
{
|
||||
wifi_ap_record_t* ch_records = new wifi_ap_record_t[ch_count];
|
||||
if (esp_wifi_scan_get_ap_records(&ch_count, ch_records) == ESP_OK)
|
||||
{
|
||||
for (uint16_t i = 0; i < ch_count; i++)
|
||||
{
|
||||
all_records.push_back(ch_records[i]);
|
||||
}
|
||||
}
|
||||
delete[] ch_records;
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
// Process all collected records
|
||||
for (const auto& record : all_records)
|
||||
{
|
||||
WiFiNetwork network;
|
||||
network.ssid = std::string(reinterpret_cast<const char*>(record.ssid));
|
||||
network.channel = record.primary;
|
||||
network.rssi = record.rssi;
|
||||
memcpy(network.mac, record.bssid, 6);
|
||||
network.auth_mode = record.authmode;
|
||||
scan_results.push_back(network);
|
||||
}
|
||||
|
||||
int64_t total_time = (esp_timer_get_time() / 1000) - start_time;
|
||||
ESP_LOGI(TAG, "Sequential scan completed in %lld ms, found %d APs", total_time, scan_results.size());
|
||||
|
||||
// Skip the normal result processing
|
||||
return scan_results;
|
||||
}
|
||||
|
||||
// Wait for scan completion with timeout
|
||||
// Sequential channel scan - scan each channel individually with timeout tracking
|
||||
std::vector<wifi_ap_record_t> all_records;
|
||||
int64_t start_time = esp_timer_get_time() / 1000; // Convert to ms
|
||||
int64_t elapsed_ms = 0;
|
||||
bool scan_done = false;
|
||||
|
||||
while (elapsed_ms < timeout_ms)
|
||||
for (uint8_t ch = 1; ch <= 13; ch++)
|
||||
{
|
||||
// Check if scan is actually complete by trying to get AP count
|
||||
// When scan is done, this will return ESP_OK with a valid count
|
||||
uint16_t temp_count = 0;
|
||||
esp_err_t count_err = esp_wifi_scan_get_ap_num(&temp_count);
|
||||
// Check if we've exceeded the timeout
|
||||
int64_t current_time = esp_timer_get_time() / 1000;
|
||||
int64_t elapsed = current_time - start_time;
|
||||
|
||||
// If we can successfully get the AP count, the scan is likely complete
|
||||
// However, we should still wait for the scan to fully finish
|
||||
if (count_err == ESP_OK && temp_count > 0)
|
||||
if (elapsed >= timeout_ms)
|
||||
{
|
||||
// Give it a bit more time to ensure all channels are scanned
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
scan_done = true;
|
||||
ESP_LOGW(TAG, "Sequential scan timeout after %lld ms at channel %d", elapsed, ch);
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
elapsed_ms = (esp_timer_get_time() / 1000) - start_time;
|
||||
wifi_scan_config_t scan_config = {.ssid = nullptr,
|
||||
.bssid = nullptr,
|
||||
.channel = ch,
|
||||
.show_hidden = true,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
.scan_time = {.active = {.min = 100, .max = 200}, .passive = 300},
|
||||
.home_chan_dwell_time = 0,
|
||||
.channel_bitmap = 0};
|
||||
|
||||
err = esp_wifi_scan_start(&scan_config, true); // Blocking scan
|
||||
if (err == ESP_OK)
|
||||
{
|
||||
uint16_t ch_count = 0;
|
||||
esp_wifi_scan_get_ap_num(&ch_count);
|
||||
if (ch_count > 0)
|
||||
{
|
||||
wifi_ap_record_t* ch_records = new wifi_ap_record_t[ch_count];
|
||||
if (esp_wifi_scan_get_ap_records(&ch_count, ch_records) == ESP_OK)
|
||||
{
|
||||
for (uint16_t i = 0; i < ch_count; i++)
|
||||
{
|
||||
all_records.push_back(ch_records[i]);
|
||||
}
|
||||
}
|
||||
delete[] ch_records;
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
if (!scan_done && elapsed_ms >= timeout_ms)
|
||||
{
|
||||
ESP_LOGE(TAG, "Scan timeout after %lld ms", elapsed_ms);
|
||||
esp_wifi_scan_stop();
|
||||
return scan_results;
|
||||
}
|
||||
|
||||
// Get scan results
|
||||
uint16_t ap_count = 0;
|
||||
esp_wifi_scan_get_ap_num(&ap_count);
|
||||
|
||||
if (ap_count == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "No access points found");
|
||||
return scan_results;
|
||||
}
|
||||
|
||||
wifi_ap_record_t* ap_records = new wifi_ap_record_t[ap_count];
|
||||
err = esp_wifi_scan_get_ap_records(&ap_count, ap_records);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to get scan records: %s", esp_err_to_name(err));
|
||||
delete[] ap_records;
|
||||
return scan_results;
|
||||
}
|
||||
|
||||
// Build the results vector and track channels found
|
||||
bool channels_found[15] = {false}; // Track channels 0-14
|
||||
|
||||
for (uint16_t i = 0; i < ap_count; i++)
|
||||
// Process all collected records
|
||||
for (const auto& record : all_records)
|
||||
{
|
||||
WiFiNetwork network;
|
||||
network.ssid = std::string(reinterpret_cast<char*>(ap_records[i].ssid));
|
||||
network.channel = ap_records[i].primary;
|
||||
network.rssi = ap_records[i].rssi;
|
||||
memcpy(network.mac, ap_records[i].bssid, 6);
|
||||
network.auth_mode = ap_records[i].authmode;
|
||||
|
||||
if (network.channel <= 14)
|
||||
{
|
||||
channels_found[network.channel] = true;
|
||||
}
|
||||
|
||||
network.ssid = std::string(reinterpret_cast<const char*>(record.ssid));
|
||||
network.channel = record.primary;
|
||||
network.rssi = record.rssi;
|
||||
memcpy(network.mac, record.bssid, 6);
|
||||
network.auth_mode = record.authmode;
|
||||
scan_results.push_back(network);
|
||||
}
|
||||
|
||||
delete[] ap_records;
|
||||
ESP_LOGI(TAG, "Found %d access points", ap_count);
|
||||
int64_t total_time = (esp_timer_get_time() / 1000) - start_time;
|
||||
ESP_LOGI(TAG, "Sequential scan completed in %lld ms, found %d APs", total_time, scan_results.size());
|
||||
|
||||
// Skip the normal result processing
|
||||
return scan_results;
|
||||
}
|
||||
@@ -21,7 +21,6 @@ class WiFiScanner
|
||||
public:
|
||||
WiFiScanner();
|
||||
std::vector<WiFiNetwork> scanNetworks(int timeout_ms = 15000);
|
||||
static void scanResultCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
|
||||
private:
|
||||
std::vector<WiFiNetwork> networks;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#include "wifiManager.hpp"
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
|
||||
static auto WIFI_MANAGER_TAG = "[WIFI_MANAGER]";
|
||||
|
||||
@@ -47,7 +51,25 @@ WiFiManager::WiFiManager(std::shared_ptr<ProjectConfig> deviceConfig, QueueHandl
|
||||
{
|
||||
}
|
||||
|
||||
void WiFiManager::SetCredentials(const char* ssid, const char* password)
|
||||
std::vector<uint8_t> WiFiManager::ParseBSSID(std::string_view bssid_string)
|
||||
{
|
||||
return bssid_string
|
||||
// We format the bssid/mac address as XX:XX:XX:XX:XX:XX
|
||||
| std::views::split(':')
|
||||
// Once we have that, we can convert each sub range into a proper uint8_t value
|
||||
| std::views::transform(
|
||||
[](auto&& subrange) -> uint8_t
|
||||
{
|
||||
auto view = std::string_view(subrange);
|
||||
uint8_t result{};
|
||||
std::from_chars(view.begin(), view.end(), result, 16);
|
||||
return result;
|
||||
})
|
||||
// and now group them into the vector we need
|
||||
| std::ranges::to<std::vector<uint8_t>>();
|
||||
}
|
||||
|
||||
void WiFiManager::SetCredentials(const char* ssid, const std::vector<uint8_t> bssid, const char* password, bool use_bssid)
|
||||
{
|
||||
// Clear the config first
|
||||
memset(&_wifi_cfg, 0, sizeof(_wifi_cfg));
|
||||
@@ -62,6 +84,13 @@ void WiFiManager::SetCredentials(const char* ssid, const char* password)
|
||||
memcpy(_wifi_cfg.sta.password, password, pass_len);
|
||||
_wifi_cfg.sta.password[pass_len] = '\0';
|
||||
|
||||
// if we can use bssid, just copy it. Parser makes sure we do not exceed 6 elements so we should be safe here
|
||||
// if we fail to parse, the vec will be empty, so use_bssid won't be set
|
||||
if (use_bssid)
|
||||
{
|
||||
std::copy(bssid.begin(), bssid.end(), _wifi_cfg.sta.bssid);
|
||||
}
|
||||
|
||||
// Set other required fields
|
||||
// Use open auth if no password, otherwise allow any WPA variant
|
||||
if (strlen(password) == 0)
|
||||
@@ -81,8 +110,8 @@ void WiFiManager::SetCredentials(const char* ssid, const char* password)
|
||||
|
||||
// OPTIMIZATION: Use fast scan instead of all channel scan for quicker connection
|
||||
_wifi_cfg.sta.scan_method = WIFI_FAST_SCAN;
|
||||
_wifi_cfg.sta.bssid_set = 0; // Don't use specific BSSID
|
||||
_wifi_cfg.sta.channel = 0; // Auto channel detection
|
||||
_wifi_cfg.sta.bssid_set = use_bssid; // Don't use specific BSSID
|
||||
_wifi_cfg.sta.channel = 0; // Auto channel detection
|
||||
|
||||
// Additional settings that might help with compatibility
|
||||
_wifi_cfg.sta.listen_interval = 0; // Default listen interval
|
||||
@@ -101,7 +130,8 @@ void WiFiManager::SetCredentials(const char* ssid, const char* password)
|
||||
void WiFiManager::ConnectWithHardcodedCredentials()
|
||||
{
|
||||
SystemEvent event = {EventSource::WIFI, WiFiState_e::WiFiState_ReadyToConnect};
|
||||
this->SetCredentials(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD);
|
||||
const auto bssid = this->ParseBSSID(std::string_view(CONFIG_WIFI_BSSID));
|
||||
this->SetCredentials(CONFIG_WIFI_SSID, bssid, CONFIG_WIFI_PASSWORD, bssid.size());
|
||||
|
||||
wifi_mode_t mode;
|
||||
if (esp_wifi_get_mode(&mode) == ESP_OK)
|
||||
@@ -170,7 +200,8 @@ void WiFiManager::ConnectWithStoredCredentials()
|
||||
// Reset retry counter for each network attempt
|
||||
s_retry_num = 0;
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_FAIL_BIT | WIFI_CONNECTED_BIT);
|
||||
this->SetCredentials(network.ssid.c_str(), network.password.c_str());
|
||||
auto bssid = this->ParseBSSID(std::string_view(network.bssid));
|
||||
this->SetCredentials(network.ssid.c_str(), bssid, network.password.c_str(), bssid.size());
|
||||
|
||||
// Update config without stopping WiFi again
|
||||
ESP_LOGI(WIFI_MANAGER_TAG, "Attempting to connect to SSID: '%s'", network.ssid.c_str());
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "WiFiScanner.hpp"
|
||||
|
||||
#include "esp_event.h"
|
||||
@@ -40,10 +41,11 @@ class WiFiManager
|
||||
|
||||
int8_t power;
|
||||
|
||||
void SetCredentials(const char* ssid, const char* password);
|
||||
void SetCredentials(const char* ssid, const std::vector<uint8_t> bssid, const char* password, bool use_bssid);
|
||||
void ConnectWithHardcodedCredentials();
|
||||
void ConnectWithStoredCredentials();
|
||||
void SetupAccessPoint();
|
||||
std::vector<uint8_t> ParseBSSID(std::string_view bssid_string);
|
||||
|
||||
public:
|
||||
WiFiManager(std::shared_ptr<ProjectConfig> deviceConfig, QueueHandle_t eventQueue, StateManager* stateManager);
|
||||
|
||||
Reference in New Issue
Block a user