fix(blufi): GET_WIFI_LIST triggers real-time scan with guaranteed response (#1964)
* fix(blufi): GET_WIFI_LIST triggers real-time scan with guaranteed response Previously, ESP_BLUFI_EVENT_GET_WIFI_LIST waited for any in-progress scan to finish and then returned the cached result. When the cache was empty (e.g. after a config-mode transition that stopped the Wi-Fi driver), _send_wifi_list() returned silently with no response frame, leaving the App waiting until timeout. Changes: - GET_WIFI_LIST now clears the cache and starts a fresh scan immediately. - _wifi_scan_event_handler calls _send_wifi_list() after every scan triggered by a GET_WIFI_LIST request. - start_wifi_scan() calls esp_wifi_start() before esp_wifi_scan_start() to handle the case where the driver was stopped during a mode transition (ESP_ERR_WIFI_STATE is treated as already-started). - _send_wifi_list() sends ESP_BLUFI_WIFI_SCAN_FAIL when no APs are found, so the App always receives a terminal response. - Redundant static_cast in _wifi_scan_event_handler replaced with the existing local `self` pointer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(blufi): preserve cache fast-path, fall back to live scan only when needed Address review feedback on always-rescan latency regression. The GET_WIFI_LIST handler now distinguishes three cases: 1. Scan in flight: defer the response via m_send_list_after_scan; the scan-done handler dispatches when it fires. Removes the previous blocking `while (m_scan_in_progress) vTaskDelay(500)` which would stall the BluFi event task indefinitely if the scan never completed. 2. Cache populated: respond from cache immediately (~50 ms, no latency change vs original behavior). _send_wifi_list() still kicks off an async refresh scan as before to keep the cache fresh. 3. Cache empty and no scan running: trigger a live scan and dispatch from the scan-done handler. If start_wifi_scan() fails, send ESP_BLUFI_WIFI_SCAN_FAIL so the App exits its wait state. State variables are also disentangled: - m_scan_should_save_ssid keeps its original meaning (write scan results into m_ap_records). Cleared during connect-to-AP so the connect-time scan does not pollute the cache. - m_send_list_after_scan is new and tracks "the next scan-done event should respond to a pending GET_WIFI_LIST request". The previous PR conflated these two responsibilities onto m_scan_should_save_ssid, which would have caused init-time scans to spuriously emit a wifi list to the App. start_wifi_scan() now returns bool so the caller can distinguish "scan started or already running" from "could not start a scan". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Yixin Shi <shiyixin@qiniu.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -533,13 +533,13 @@ int Blufi::_get_softap_conn_num() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blufi::start_wifi_scan() {
|
bool Blufi::start_wifi_scan() {
|
||||||
ESP_LOGI(BLUFI_TAG, "Starting dedicated WiFi scan");
|
ESP_LOGI(BLUFI_TAG, "Starting dedicated WiFi scan");
|
||||||
|
|
||||||
// Check if a scan is already in progress
|
// Already running: caller can rely on the in-flight scan and await its done event.
|
||||||
if (m_scan_in_progress) {
|
if (m_scan_in_progress) {
|
||||||
ESP_LOGW(BLUFI_TAG, "Scan already in progress, skipping");
|
ESP_LOGW(BLUFI_TAG, "Scan already in progress, skipping");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scan_in_progress = true;
|
m_scan_in_progress = true;
|
||||||
@ -555,14 +555,14 @@ void Blufi::start_wifi_scan() {
|
|||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(BLUFI_TAG, "Failed to set WiFi mode to STA: %s", esp_err_to_name(err));
|
ESP_LOGE(BLUFI_TAG, "Failed to set WiFi mode to STA: %s", esp_err_to_name(err));
|
||||||
m_scan_in_progress = false;
|
m_scan_in_progress = false;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// Need to restart WiFi for mode change to take effect
|
// Need to restart WiFi for mode change to take effect
|
||||||
err = esp_wifi_start();
|
err = esp_wifi_start();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi after mode switch: %s", esp_err_to_name(err));
|
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi after mode switch: %s", esp_err_to_name(err));
|
||||||
m_scan_in_progress = false;
|
m_scan_in_progress = false;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// Register scan event handler
|
// Register scan event handler
|
||||||
esp_event_handler_instance_t scan_event_instance;
|
esp_event_handler_instance_t scan_event_instance;
|
||||||
@ -575,28 +575,36 @@ void Blufi::start_wifi_scan() {
|
|||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi scan: %s", esp_err_to_name(err));
|
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi scan: %s", esp_err_to_name(err));
|
||||||
m_scan_in_progress = false;
|
m_scan_in_progress = false;
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
} else if (current_mode == WIFI_MODE_STA || current_mode == WIFI_MODE_APSTA) {
|
||||||
|
// Ensure WiFi driver is started (may have been stopped during config mode transition)
|
||||||
|
err = esp_wifi_start();
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_WIFI_STATE) {
|
||||||
|
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi before scan: %s", esp_err_to_name(err));
|
||||||
|
m_scan_in_progress = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else if (current_mode == WIFI_MODE_STA) {
|
|
||||||
// Start scan
|
|
||||||
err = esp_wifi_scan_start(NULL, false);
|
err = esp_wifi_scan_start(NULL, false);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi scan: %s", esp_err_to_name(err));
|
ESP_LOGE(BLUFI_TAG, "Failed to start WiFi scan: %s", esp_err_to_name(err));
|
||||||
m_scan_in_progress = false;
|
m_scan_in_progress = false;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(BLUFI_TAG, "Unexpected WiFi mode: %d", current_mode);
|
ESP_LOGE(BLUFI_TAG, "Unexpected WiFi mode: %d", current_mode);
|
||||||
m_scan_in_progress = false;
|
m_scan_in_progress = false;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(BLUFI_TAG, "WiFi scan started");
|
ESP_LOGI(BLUFI_TAG, "WiFi scan started");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blufi::_send_wifi_list() {
|
void Blufi::_send_wifi_list() {
|
||||||
if (m_ap_records.empty()) {
|
if (m_ap_records.empty()) {
|
||||||
ESP_LOGW(BLUFI_TAG, "No AP records available to send");
|
ESP_LOGW(BLUFI_TAG, "No AP records available, sending WiFi scan fail");
|
||||||
|
esp_blufi_send_error_info(ESP_BLUFI_WIFI_SCAN_FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +639,7 @@ void Blufi::_wifi_scan_event_handler(void* arg, esp_event_base_t event_base, int
|
|||||||
ESP_LOGW(BLUFI_TAG, "No APs found");
|
ESP_LOGW(BLUFI_TAG, "No APs found");
|
||||||
self->m_ap_records.clear();
|
self->m_ap_records.clear();
|
||||||
} else {
|
} else {
|
||||||
if (static_cast<Blufi*>(arg)->m_scan_should_save_ssid == true) {
|
if (self->m_scan_should_save_ssid) {
|
||||||
self->m_ap_records.resize(ap_num);
|
self->m_ap_records.resize(ap_num);
|
||||||
esp_wifi_scan_get_ap_records(&ap_num, self->m_ap_records.data());
|
esp_wifi_scan_get_ap_records(&ap_num, self->m_ap_records.data());
|
||||||
|
|
||||||
@ -643,6 +651,11 @@ void Blufi::_wifi_scan_event_handler(void* arg, esp_event_base_t event_base, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self->m_scan_in_progress = false;
|
self->m_scan_in_progress = false;
|
||||||
|
// Dispatch a pending GET_WIFI_LIST response if one is waiting on this scan.
|
||||||
|
if (self->m_send_list_after_scan) {
|
||||||
|
self->m_send_list_after_scan = false;
|
||||||
|
self->_send_wifi_list();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,10 +878,29 @@ void Blufi::_handle_event(esp_blufi_cb_event_t event, esp_blufi_cb_param_t* para
|
|||||||
break;
|
break;
|
||||||
case ESP_BLUFI_EVENT_GET_WIFI_LIST: {
|
case ESP_BLUFI_EVENT_GET_WIFI_LIST: {
|
||||||
ESP_LOGI(BLUFI_TAG, "BLUFI get wifi list");
|
ESP_LOGI(BLUFI_TAG, "BLUFI get wifi list");
|
||||||
while (m_scan_in_progress) {
|
// Case 1: a scan is already in flight (init scan or refresh scan started by
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
// the previous _send_wifi_list()). Defer the response to its done handler
|
||||||
|
// instead of blocking the BluFi task.
|
||||||
|
if (m_scan_in_progress) {
|
||||||
|
m_send_list_after_scan = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Case 2: cache is populated. Respond immediately; _send_wifi_list() also
|
||||||
|
// kicks off an async refresh scan to keep the cache fresh.
|
||||||
|
if (!m_ap_records.empty()) {
|
||||||
|
_send_wifi_list();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Case 3: no cache (e.g. driver was stopped during a config-mode transition,
|
||||||
|
// init scan never completed). Trigger a real scan and dispatch from the
|
||||||
|
// scan-done handler. If the scan cannot start, return an error frame so the
|
||||||
|
// App exits its wait state instead of timing out.
|
||||||
|
m_scan_should_save_ssid = true;
|
||||||
|
m_send_list_after_scan = true;
|
||||||
|
if (!start_wifi_scan()) {
|
||||||
|
m_send_list_after_scan = false;
|
||||||
|
esp_blufi_send_error_info(ESP_BLUFI_WIFI_SCAN_FAIL);
|
||||||
}
|
}
|
||||||
_send_wifi_list();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -25,8 +25,9 @@ public:
|
|||||||
* This method intelligently handles WiFi scanning based on current WiFi state:
|
* This method intelligently handles WiFi scanning based on current WiFi state:
|
||||||
* - If WiFi config mode is active, it uses the existing scan results from WifiConfigurationAp
|
* - If WiFi config mode is active, it uses the existing scan results from WifiConfigurationAp
|
||||||
* - Otherwise, it performs a dedicated scan without interfering with normal WiFi operations
|
* - Otherwise, it performs a dedicated scan without interfering with normal WiFi operations
|
||||||
|
* @return true if a scan was started (or was already in progress); false on failure.
|
||||||
*/
|
*/
|
||||||
void start_wifi_scan();
|
bool start_wifi_scan();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the Bluetooth controller, host, and Blufi profile.
|
* @brief Initializes the Bluetooth controller, host, and Blufi profile.
|
||||||
@ -143,5 +144,13 @@ private:
|
|||||||
// WiFi scan related
|
// WiFi scan related
|
||||||
std::vector<wifi_ap_record_t> m_ap_records;
|
std::vector<wifi_ap_record_t> m_ap_records;
|
||||||
bool m_scan_in_progress = false;
|
bool m_scan_in_progress = false;
|
||||||
|
// When true, scan results are stored in m_ap_records on scan completion.
|
||||||
|
// Cleared during connect-to-AP so that the connect-time scan does not
|
||||||
|
// overwrite the cache with results gathered for connection purposes.
|
||||||
bool m_scan_should_save_ssid = true;
|
bool m_scan_should_save_ssid = true;
|
||||||
|
// When true, the next scan-done event responds to a pending GET_WIFI_LIST
|
||||||
|
// request from the App. Set by the GET_WIFI_LIST handler when no cache is
|
||||||
|
// available or a scan is already in flight; cleared by the scan-done
|
||||||
|
// handler after dispatching the response.
|
||||||
|
bool m_send_list_after_scan = false;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user