Esp32-snippets: How can you force a disconnect of a BLE client from the server?

Created on 1 Feb 2018  路  11Comments  路  Source: nkolban/esp32-snippets

Hi,

I am developing an application where the ESP32 act as server.
Some times if the client disconnect without any information to server (for example, application crash), the server continue in "connected to client" status and it is not advertising and do not accept any other connection.
I would like to do a whatchdog task that it disconnect the client if no activity (read or write) during certain time.
How can I force disconnection from client, so BLE server start advertising and accept new connections?

study required

Most helpful comment

I have been busy lately but finally I tried it.
Based on suggestion by chegewara, I have added a function to BLEServer library (Code below).
As my client is periodically (few seconds) communication with server once connected, I have a task in server that check the time-stamp of last communication received from client (updated in BLECharacteristicCallbacks.onWrite callback function). If older than certain threshold (10 seconds in my case) I call this function.

It works perfectly for me. It disconnect, start advertising and accept connection if requested by client. No need to do any additional action.

void BLEServer::disconnectClient() {
ESP_LOGD(LOG_TAG, ">> disconnectClient. GATTS IF: %d. CONN ID: %d", m_gatts_if, m_connId);
if (m_gatts_if >= 0 and m_connId >= 0) {
esp_err_t result = ::esp_ble_gatts_close(m_gatts_if, m_connId);
if (result != ESP_OK) {
ESP_LOGE(LOG_TAG, "Disconnection FAILED. Code: %d.", result);
}
} else {
ESP_LOGD(LOG_TAG, "Can not disconnect Client.");
}

ESP_LOGD(LOG_TAG, "<< disconnectClient");

} // disconnectClient

All 11 comments

There is no function implemented in this library that can let you disconnect client. You have 2 options:

This is an interesting question. I'm imagining a BLE Server (a peripheral) which is advertising happily. It is then connected to by a BLE Client (a central) and hence it stops advertising. Now the client crashes (powers down or goes out of communication range) and the BLE Server should start advertising again. The interesting question is how should the server detect this? In TCP communications, we have the notion of a keep-alive packet. This is a packet periodically sent between peers to validate that the connection is still logically present. In BLE ... is there an equivalent concept? Is the responsibility down to us (BLE application writers) such that when we have to maintain our own timers in BLE servers and when we haven't received a request in a period, then we disconnect?

I have the exact same problem. I haven't tried it yet, but since I am in control of the client as well, I am thinking of having my app periodically write to a certain characteristic, which the ESP32 will check and reset regularly. If there is nothing written when the ESP32 checks, it will disconnect the client.

@SalvaPedraza Please let us know if you found any other solution.

I have been busy lately but finally I tried it.
Based on suggestion by chegewara, I have added a function to BLEServer library (Code below).
As my client is periodically (few seconds) communication with server once connected, I have a task in server that check the time-stamp of last communication received from client (updated in BLECharacteristicCallbacks.onWrite callback function). If older than certain threshold (10 seconds in my case) I call this function.

It works perfectly for me. It disconnect, start advertising and accept connection if requested by client. No need to do any additional action.

void BLEServer::disconnectClient() {
ESP_LOGD(LOG_TAG, ">> disconnectClient. GATTS IF: %d. CONN ID: %d", m_gatts_if, m_connId);
if (m_gatts_if >= 0 and m_connId >= 0) {
esp_err_t result = ::esp_ble_gatts_close(m_gatts_if, m_connId);
if (result != ESP_OK) {
ESP_LOGE(LOG_TAG, "Disconnection FAILED. Code: %d.", result);
}
} else {
ESP_LOGD(LOG_TAG, "Can not disconnect Client.");
}

ESP_LOGD(LOG_TAG, "<< disconnectClient");

} // disconnectClient

I spoke to soon...

Hello everyone !

I came across this conversation with the same idea of being able to remove the connection to a client.
@SalvaPedraza 's solution looks like it's the right one. Will this code be added in the library any time soon ?
Thanks !

@nkolban I have a use case for being able to force disconnect a client.

Some Android devices can be slow to detect a disconnection if you need to restart the ESP (which I do when I get configuration changes). Explicitly disconnecting a device will help with that user experience before re-starting the ESP32.

Hi @nsamala
i can add disconnect to BLEServer, but it will require you to track/store connected peer devices or at least their connID, because this is how esp-idf close function looks like:
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/bluetooth/esp_gatts.html#_CPPv219esp_ble_gatts_close13esp_gatt_if_t8uint16_t

and this library implementation is build to connect different peer devices to one BLEServer which holds its own gattsIf but every client got different connId.

On a tangential note:
1) When the server stops advertising, it shouldn't automagically start advertising again.
2) When a client disconnects from the Server it shouldn't automagically start advertising again.

These should both be handled from callbacks within the app (IF that is required). Otherwise the app can't control when it is advertising a BT Server.

I have created an issue for this : https://github.com/nkolban/esp32-snippets/issues/816

I have a similar situation (could be counted as a use case):

"MyDevice" (server - peripheral) works on batteries and after say, 30 minutes of inactivity, it goes into deep sleep mode without wake up timer set. The purpose of that is to require the client (central - ex. Android phone) reset "MyDevice" using on/off switch.

My aim is to iterate on all client connections and close the connection one by one.

Hello @SalvaPedraza Do you have an example how to implement your function ? I'm not that good in C++ / Adruino and i'm confused as to how to implement it .

Was this page helpful?
0 / 5 - 0 ratings