Improve cleanup in BLEClient (#4742)

- Remove client from the list of devices in case registration fails
- Filter other events not related to registration during registration phase
- Cleanup if connect fails
- Reset if after disconnect
- Disconnect callback *after* cleanup is done so object can be deleted

This fixes some of the issues I had like:
- `BLEClient::connect` hangs up and never recovered because registration failed
- `BLEClient` could not be deleted after disconnect or deletion creating ghost events https://github.com/espressif/arduino-esp32/issues/4047
- `BLEClient` could not be properly reused after a connection was attempted (successful or not) 

* Cleanup in case of registration and connect failure.
Cleanup before calling disconnect callback for safe delete.
Reject other events during registration.
Adresses #4047, #4055

* Clear if after unregister #4047
This commit is contained in:
Emanuel Posescu 2021-02-16 11:21:45 +02:00 committed by GitHub
parent 7cdfb8bc7c
commit 9be784f69b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -110,7 +110,17 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false; return false;
} }
m_semaphoreRegEvt.wait("connect"); uint32_t rc = m_semaphoreRegEvt.wait("connect");
if (rc != ESP_GATT_OK) {
// fixes ESP_GATT_NO_RESOURCES error mostly
log_e("esp_ble_gattc_app_register_error: rc=%d", rc);
BLEDevice::removePeerDevice(m_appId, true);
// not sure if this is needed here
// esp_ble_gattc_app_unregister(m_gattc_if);
// m_gattc_if = ESP_GATT_IF_NONE;
return false;
}
m_peerAddress = address; m_peerAddress = address;
@ -128,7 +138,13 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false; return false;
} }
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
// check the status of the connection and cleanup in case of failure
if (rc != ESP_GATT_OK) {
BLEDevice::removePeerDevice(m_appId, true);
esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
}
log_v("<< connect(), rc=%d", rc==ESP_GATT_OK); log_v("<< connect(), rc=%d", rc==ESP_GATT_OK);
return rc == ESP_GATT_OK; return rc == ESP_GATT_OK;
} // connect } // connect
@ -160,6 +176,11 @@ void BLEClient::gattClientEventHandler(
log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s", log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s",
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str()); gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
// it is possible to receive events from other connections while waiting for registration
if (m_gattc_if == ESP_GATT_IF_NONE && event != ESP_GATTC_REG_EVT) {
return;
}
// Execute handler code based on the type of event received. // Execute handler code based on the type of event received.
switch(event) { switch(event) {
@ -184,15 +205,17 @@ void BLEClient::gattClientEventHandler(
if (evtParam->disconnect.conn_id != getConnId()) break; if (evtParam->disconnect.conn_id != getConnId()) break;
// If we receive a disconnect event, set the class flag that indicates that we are // If we receive a disconnect event, set the class flag that indicates that we are
// no longer connected. // no longer connected.
if (m_isConnected && m_pClientCallbacks != nullptr) { bool m_wasConnected = m_isConnected;
m_pClientCallbacks->onDisconnect(this);
}
m_isConnected = false; m_isConnected = false;
esp_ble_gattc_app_unregister(m_gattc_if); esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE); m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
m_semaphoreRssiCmplEvt.give(); m_semaphoreRssiCmplEvt.give();
m_semaphoreSearchCmplEvt.give(1); m_semaphoreSearchCmplEvt.give(1);
BLEDevice::removePeerDevice(m_appId, true); BLEDevice::removePeerDevice(m_appId, true);
if (m_wasConnected && m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
break; break;
} // ESP_GATTC_DISCONNECT_EVT } // ESP_GATTC_DISCONNECT_EVT
@ -228,7 +251,8 @@ void BLEClient::gattClientEventHandler(
// //
case ESP_GATTC_REG_EVT: { case ESP_GATTC_REG_EVT: {
m_gattc_if = gattc_if; m_gattc_if = gattc_if;
m_semaphoreRegEvt.give(); // pass on the registration status result, in case of failure
m_semaphoreRegEvt.give(evtParam->reg.status);
break; break;
} // ESP_GATTC_REG_EVT } // ESP_GATTC_REG_EVT