Detect BLE stack unrecoverable state (#4128)

This commit is contained in:
J. Nick Koston 2022-12-05 08:42:51 -10:00 committed by GitHub
parent 54caed36f7
commit 3b2bbd306f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 3 deletions

View file

@ -90,8 +90,12 @@ void ESP32BLETracker::loop() {
int connecting = 0; int connecting = 0;
int discovered = 0; int discovered = 0;
int searching = 0; int searching = 0;
int disconnecting = 0;
for (auto *client : this->clients_) { for (auto *client : this->clients_) {
switch (client->state()) { switch (client->state()) {
case ClientState::DISCONNECTING:
disconnecting++;
break;
case ClientState::DISCOVERED: case ClientState::DISCOVERED:
discovered++; discovered++;
break; break;
@ -144,7 +148,20 @@ void ESP32BLETracker::loop() {
xSemaphoreGive(this->scan_result_lock_); xSemaphoreGive(this->scan_result_lock_);
} }
if (!connecting && xSemaphoreTake(this->scan_end_lock_, 0L)) { /*
Avoid starting the scanner if:
- we are already scanning
- we are connecting to a device
- we are disconnecting from a device
Otherwise the scanner could fail to ever start again
and our only way to recover is to reboot.
https://github.com/espressif/esp-idf/issues/6688
*/
if (!connecting && !disconnecting && xSemaphoreTake(this->scan_end_lock_, 0L)) {
if (this->scan_continuous_) { if (this->scan_continuous_) {
if (!promote_to_connecting && !this->scan_start_failed_ && !this->scan_set_param_failed_) { if (!promote_to_connecting && !this->scan_start_failed_ && !this->scan_set_param_failed_) {
this->start_scan_(false); this->start_scan_(false);
@ -159,6 +176,10 @@ void ESP32BLETracker::loop() {
} }
if (this->scan_start_failed_ || this->scan_set_param_failed_) { if (this->scan_start_failed_ || this->scan_set_param_failed_) {
if (this->scan_start_fail_count_ == 255) {
ESP_LOGE(TAG, "ESP-IDF BLE scan could not restart after 255 attempts, rebooting to restore BLE stack...");
App.reboot();
}
esp_ble_gap_stop_scanning(); esp_ble_gap_stop_scanning();
if (this->scan_start_failed_) { if (this->scan_start_failed_) {
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_); ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
@ -306,7 +327,7 @@ void ESP32BLETracker::start_scan_(bool first) {
esp_ble_gap_start_scanning(this->scan_duration_); esp_ble_gap_start_scanning(this->scan_duration_);
this->set_timeout("scan", this->scan_duration_ * 2000, []() { this->set_timeout("scan", this->scan_duration_ * 2000, []() {
ESP_LOGW(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack..."); ESP_LOGE(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
App.reboot(); App.reboot();
}); });
} }
@ -366,7 +387,10 @@ void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t:
void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param) { void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param &param) {
this->scan_start_failed_ = param.status; this->scan_start_failed_ = param.status;
if (param.status != ESP_BT_STATUS_SUCCESS) { if (param.status == ESP_BT_STATUS_SUCCESS) {
this->scan_start_fail_count_ = 0;
} else {
this->scan_start_fail_count_++;
xSemaphoreGive(this->scan_end_lock_); xSemaphoreGive(this->scan_end_lock_);
} }
} }

View file

@ -253,6 +253,7 @@ class ESP32BLETracker : public Component {
uint32_t scan_duration_; uint32_t scan_duration_;
uint32_t scan_interval_; uint32_t scan_interval_;
uint32_t scan_window_; uint32_t scan_window_;
uint8_t scan_start_fail_count_;
bool scan_continuous_; bool scan_continuous_;
bool scan_active_; bool scan_active_;
bool scanner_idle_; bool scanner_idle_;