esp32-snippets: BLE client gets stuck while calling BLEClient::connect()

First of all, hello and thank you for your libraries and excuse me for this probably very simple question.

Very recently I have begun learning BLE and the esp32 and my goal for the moment is to successully establish a BLE connection between an esp32 (as client) and the nRF52 (as server). I believe the nRF52 works, since I can connect to it using my phone and control the value of characteristics in it. However, I can’t get the esp32 to connect to it successully. It is able to scan and detect nearby devices and find the nRF52’s adress no problem, but when a connection attempt is made using the connect() function, the program seems to wait indefinitely and no connection is ever established. While I have done some research on semaphores, I am still quite unfamilliar with them.

I wish to understand where it gets stuck in the connect() fuction, why it does that and how can I make it work. Here is my code (I am using the Arduino framework in PlatformIO):

#include <Arduino.h>

#include "BLEDevice.h"


static BLEUUID serviceUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
static BLEUUID characteristicUUID("0000004f-0000-1000-8000-00805f9b34fb");
String My_BLE_Address = "d1:c7:bd:79:c4:05";

static BLERemoteCharacteristic* pRemoteCharacteristic;
BLEScan* pBLEScan;
BLEScanResults foundDevices;
static BLEAddress *Server_BLE_Address;
String Scanned_BLE_Address;

boolean paired = false;      // Flag verifying if we are paired with our device
boolean foundDevice = false; // Flag verifying if we found our device

bool connectToserver (BLEAddress pAddress){
    
    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");
     
     
    // Connect to the BLE Server.
    pClient->connect(pAddress); // Stuck here...
    Serial.println(" - Connected to server");

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService != nullptr)
    {
      Serial.println(" - Found our service");
      return true;
    }
    else
    return false;

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(characteristicUUID);
    if (pRemoteCharacteristic != nullptr)
      Serial.println(" - Found our characteristic");

      return true;
}

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks 
{ 
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      Serial.printf("Scan Result: %s \n", advertisedDevice.toString().c_str());
      if(foundDevice == false){   // Flag verifying if we found our device
      Server_BLE_Address = new BLEAddress(advertisedDevice.getAddress()); // Update Server_BLE_Address if we didn't
      Scanned_BLE_Address = Server_BLE_Address->toString().c_str();
      }
      if(Scanned_BLE_Address == My_BLE_Address) // Compares the scanned adress to what we are looking for
      {
        foundDevice = true; // Found our device
      }
      Serial.println("Comparing to our server adress: ");
      Serial.println(My_BLE_Address);
    }
};

void setup() {
    Serial.begin(115200); //Start serial monitor 
    Serial.println("ESP32 BLE Client program"); //Intro message 

    BLEDevice::init("ESP32");
    pBLEScan = BLEDevice::getScan(); //create new scan
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); //Call the class that is defined above 
    pBLEScan->setActiveScan(false); //active scan uses more power, but get results faster
}

void loop() {

  foundDevices = pBLEScan->start(3); //Scan for 3 seconds to find the server
  uint8_t devicesCount = foundDevices.getCount(); 
  Serial.printf("%d devices found \n", devicesCount);
  while (devicesCount >= 1 && foundDevice == true) // We found our server
  {
    if (foundDevice == true && paired == false) // We're not connected yet
    {
      Serial.println("Found our Device... connecting to Server as client \n");
       if (connectToserver(*Server_BLE_Address)) // Attempt a connection to the server   ...Stuck here...
      {
      paired = true;
      Serial.println("********************CONNECTED TO SERVER************************");
     
      break;
      }
      else
      {
      Serial.println("Pairing failed");
      foundDevice = false;
      break;
      }
    }
    devicesCount = 0; // Reset the number of devices
  }
  pBLEScan->stop();
  delay(5000);
}

And here is what the serial monitor looks like:

ESP32 BLE Client program
Scan Result: Name: , Address: 3f:43:89:02:09:99, manufacturer data: 0600010920020273111e440a64443a2bbdb913d98c83605f724bf88dd6
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 21:5f:63:6c:59:18, manufacturer data: 0600010920024cbbbc219822bf9d445e8c12280b7f0e218a9c491fd485
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 22:08:60:11:95:b3, manufacturer data: 06000109200267b9b0dc5ac0c049f892ec1bb09f3afed1bac30914b6fb
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 3b:e3:63:51:43:55, manufacturer data: 060001092002578fe17a471e0a3fff4cb07172df27a10fc4835298acd4
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: nRF52, Address: d1:c7:bd:79:c4:05, txPower: 4
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 04:b3:68:61:52:c6, manufacturer data: 060001092002810c02a9395aa4bc0d6ca4ee830ff5dc8f1dfc49e15e74
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 74:97:07:46:24:ca, manufacturer data: 4c001005131cc48f22
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 08:c0:21:ff:af:48, manufacturer data: 060001092002585e2df55dd581bf04830fe41d2f2d0cd131b433f79c76
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: f4:5c:89:a7:90:36, manufacturer data: 4c0010050b1c604ec2
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 52:33:f9:76:9e:a1, manufacturer data: 4c000c0e00f2e83ef80545a417a96ba8e194
Comparing to our server adress:
d1:c7:bd:79:c4:05
Scan Result: Name: , Address: 7c:87:5c:cc:fd:c8, manufacturer data: 4c0010050318008367
Comparing to our server adress:
d1:c7:bd:79:c4:05
11 devices found
Found our Device... connecting to Server as client

 - Created client

Do you think you can help me? Thanks in advance.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 2
  • Comments: 50

Most upvoted comments

Hi, I have got the same problem // ------------------------------- pClient->connect(pAddress); // Stuck here… //-------------------------------- I solved this problem by modifying the FreeRTOS.cpp file. You can see this command in line 77 of FreeRTOS.cpp xSemaphoreTake(m_semaphore, portMAX_DELAY); As the portMAX_DELAY value is 0xffffffffUL, maybe the code will wait for about 50 days to connect to the BLE device. So that, I changed the code like this and my code didn’t get stuck anymore. xSemaphoreTake(m_semaphore, 60000);

Thanks.

You can not connect while scanning. Stop scanning first.

Hi! I’m also using Arduino to program ESP32. This issue is very frustrating. I don’t have solution for this problem, but I have noticed that it occurs when there are lot of scanned devices. It looks that code stucks on that line: BLERemoteService* pRemoteService = pClient->getService(serviceUUID); in Client example.

Any ideas how to fix this?

      if (pClient == nullptr) {
        Serial.println("pClient == nullptr");
        delay(100);
// you should return false here, but actually this code makes no sense because earlier you have pClient->connect() which will crash
      }

Instead try to add short delay and check pClient->isConnected();

I also advice to use this connect function (there is nothing wrong with your way to do it): https://github.com/espressif/arduino-esp32/blob/master/libraries/BLE/src/BLEClient.h#L36

If you are not working with arduino it is still possible to use library from it (copy/paste).

The code crash exactly here:

    // Obtain a reference to the service we are after in the remote BLE server.
      Serial.print("Try to connect to our service UUID: ");  Serial.println(serviceUUID.toString().c_str());
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      return false;
    }
    Serial.println(" - Found our service");

and i am suspecting that device you are connecting with is disconnecting for some reason before this code is called.

I would start with comment out this code and see whats going on:

    // Obtain a reference to the service we are after in the remote BLE server.
      Serial.print("Try to connect to our service UUID: ");  Serial.println(serviceUUID.toString().c_str());
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      return false;
    }
    Serial.println(" - Found our service");


    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    if (pRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charUUID.toString().c_str());
      return false;
    }
    Serial.println(" - Found our characteristic");

    // Read the value of the characteristic.
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());

    pRemoteCharacteristic->registerForNotify(notifyCallback);

It is possible that calling this line: pClient->connect(BLEAddress(serverAddress)); //myDevice); not necessarily ends with connecting to peer device. I would suggest to add additional check after this line:

if(!pClient->isConnected())
    return false;

Also changing semaphore to timed semaphore as many times was suggested is good idea.

So that, I changed the code like this and my code didn’t get stuck anymore. xSemaphoreTake(m_semaphore, 60000);

Thanks for sharing your hang workaround. Instead of 60000 I’m using 15000; The smaller value works well for me (shorter “hang” times).

  • Thomas

I have just one thing to say: many many many and many thanks to you Chegewara 👍 . Finally the sketch works perfectly after the addition of one delay. But let’s start by the beginning… -> I have done the changes you suggested, and then I can see that the led of the device informing of bluetooth connection switched on a few seconds later. -> So in my second trial I have enlarged the the delay you precognized to 10s (to be sure but 2-3s is enough). -> Then the miracle appears in front of me: the connection passed! -> I have tried then to modify a characteristic and it works perfectly. I am wandering if the is a way to monitor when the device will be ready to accept the server connection. But for it is ok like that for me!. So many thanks to you and also for the others for repling on issues for this 874 item and for the other items.

@LK-Simon Thank you I solved the stuck problem and made an example about it. Those who have problems with Connect can try this example.

https://github.com/MertGurdogann/BLEconnectExample/blob/main/BLEconnect/BLEconnect.ino

Here is example output from Serial Monitor

Advertised Device: Name: , Address: 6e:46:76:f6:42:3c, manufacturer data: 4c0010067e1e3f5fd2f5, txPower: 8 
Advertised Device: Name: Decathlon Dual HR, Address: ed:13:79:f4:72:01, appearance: 833, serviceUUID: 0000180d-0000-1000-8000-00805f9b34fb 
Advertised Device: Name: 36374-65, Address: c4:2a:21:cf:6e:c2, appearance: 833, manufacturer data: ffff6b00168e41400001020c, serviceUUID: 0000180d-0000-1000-8000-00805f9b34fb 
Found Devices
0.   Device Name:36374-65
1.   Device Name:Decathlon Dual HR
Connecting
Connection Successfull
Connected 	Decathlon Dual HR
Connecting
Connection Successfull
Connected 	36374-65

Best regards.

If anyone wants a confirmed-working example of BLE connections for the ESP32 boards… I have a repository as part of my Automatic Discovery & Pairing articles. https://github.com/Flowduino/ESP32_ESP-Now_Pairing It’s only really intended to facilitate Automated Discovery (I’m using BLE for Discovery, then ESP-Now for actual communication) but this code is functioning just fine.

You might be able to figure out what you need to change in your own respective codebases from my code in that repository.

Enjoy!

Do not attempt to Connect to a BLE Server before the call to BLEScan->start(...); returns!

You need to initiate the scan, on your onResult Callback method, you need to determine if it is the device in which you are interested. If it is, you need to store a reference to the BLEAdvertisedDevice

Once the scan call returns (as stated in the first line of this response) you can then connect to this BLEAdvertisedDevice and it will work.

While reading #757 I have found that connect call can actually take two arguments - BLEAddress as the first one and esp_ble_addr_type_t type as a second (optional) argument that defaults to BLE_ADDR_TYPE_PUBLIC. However, as mentioned, “most if not all smartphones, tablets and laptops are using random addressing” and esp_ble_addr_type_t type has to be set to BLE_ADDR_TYPE_RANDOM (https://github.com/nkolban/esp32-snippets/issues/757#issuecomment-448336410). Worked for me!

I’m using the latest arduino-esp32 repository (last patch was from about 30 days ago). If there are more recent semaphore fixes then I would definitely want to try them out.

  • Thomas

@jiangminghe During validation I found another xSemaphoreTake() that caused an endless hang in my client application. This required another workaround patch at line 198: I changed the timeout to 15 seconds, as follows: rc = ::xSemaphoreTake(m_semaphore, 15000UL) == pdTRUE;

I recognize that these edits are workarounds, not permanent patches. But I will use them until the semaphore issues are resolved.

  • Thomas

Please excuse for my silence, I have stopped working on the esp-32 (a little bit out of frustration) to concentrate on the other chip im working on. This morning I wanted to try again from the beginning and simply copy pasted the client example in the “ESP32 BLE Arduino” library (that I have tried before without success) and changed up the Uuids to match my other chip’s Uuids.

I gave it a go and it…connected successfully without trouble… My best guess would be that my problem was on the server side, and since I worked on it, I must have corrected the problem without realising it. I am still unsure as to why my program got stuck in the connect() function (and I see im not the only one), so I won’t close this issue just yet.

If there is one thing I know it’s that the problem dosen’t seem to come from the libraries (since it worked), but I can’t know for sure.

Same issue here. I noticed that after a reset on the client this happens, after resetting once or twice again it reconnects.