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:
parent
7cdfb8bc7c
commit
9be784f69b
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user