esp32-snippets icon indicating copy to clipboard operation
esp32-snippets copied to clipboard

BLE client hang after reading server multiple times (#505 closed. Still errors with new library)

Open JeroenBeemster opened this issue 6 years ago • 29 comments

Hi All I am using the example of the client collecting data from a BLE server. Works fine a couple of times. After 5 till 25 times. It stops.

Here is the log:

  • Found our device! address:
  • Forming a connection to c4:7c:8d:66:13:9a
  • Created client E (975) BT_OSI: osi_mem_dbg_clean invalid E (2749) BT_OSI: osi_mem_dbg_clean invalid
  • Connected to server
  • Found our service E (4422) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (4424) BLERemoteCharacteristic: E (4429) BLERemoteCharacteristic:
  • Found our characteristic The characteristic value was: 318 E (4508) BT_OSI: osi_mem_dbg_clean invalid W (4511) BT_APPL: bta_gattc_conn_cback() - cif=1 connected=0 conn_id=1 reason=0x0016
  • We are now connected to the BLE Server. Next connect 1

-Forming a connection to c4:7c:8d:66:13:9a

  • Created client E (7744) BT_OSI: osi_mem_dbg_clean invalid
  • Connected to server .... <this repeats itself between 5 and 25 times > .....

Next connect 24 Forming a connection to c4:7c:8d:66:13:9a

  • Created client E (127911) BT_OSI: osi_mem_dbg_clean invalid

  • Connected to server

  • Found our service E (129237) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (129239) BLERemoteCharacteristic: E (129242) BT_OSI: osi_mem_dbg_record invalid !! E (129247) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (129256) BT_OSI: osi_mem_dbg_record invalid !! E (129260) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND

  • Found our characteristic E (129304) BT_OSI: osi_mem_dbg_record invalid !! E (129305) BT_OSI: osi_mem_dbg_record invalid !! E (129305) BT_GATT: attr offset = 0 p_attr_buf = 0x0 E (129310) BT_OSI: osi_mem_dbg_record invalid !! E (130864) BT_OSI: osi_mem_dbg_record invalid !! E (133864) BT_OSI: osi_mem_dbg_record invalid !! E (136864) BT_OSI: osi_mem_dbg_record invalid !! W (137870) BT_APPL: bta_gattc_conn_cback() - cif=1 connected=0 conn_id=1 reason=0x0013 E (137874) BT_OSI: osi_mem_dbg_record invalid !! E (137875) BT_BTC: btc_gattc_cback transfer failed

So my guess is this is they key "BT_OSI: osi_mem_dbg_clean invalid" The result of that will come on the end with this "BT_OSI: osi_mem_dbg_record invalid !!"

I am using the arduino library but not the arduino environment. Here is my code: #include "Arduino.h" #include "BLEDevice.h"

static BLEUUID serviceUUID( "00001204-0000-1000-8000-00805f9b34ff"); static BLEUUID charUUID( "00001a02-0000-1000-8000-00805f9b34ff");

static BLEAddress pServerAddress; static boolean doConnect = false; static boolean connected = false; static BLERemoteCharacteristic pRemoteCharacteristic;

int countID = 0;

bool connectToServer(BLEAddress pAddress) { Serial.print("Forming a connection to "); Serial.println(pAddress.toString().c_str());

BLEClient* pClient = BLEDevice::createClient(); if (pClient == nullptr) { Serial.print(" - Failed to create client"); return false;
} delay(300); Serial.println(" - Created client"); // Connect to the remove BLE Server. pClient->connect(pAddress); Serial.println(" - Connected to server"); if(!pClient->isConnected()){ Serial.println(" - Not connected"); return false; } // Obtain a reference to the service we are after in the remote BLE server. BLERemoteService* pRemoteService = pClient->getService(serviceUUID); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(serviceUUID.toString().c_str()); pClient->disconnect();

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()); pClient->disconnect();

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());

Serial.println(""); pClient->disconnect(); delay(200); return true; } /** Scan for BLE servers and find the first one that advertises the service we are looking for. / class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { /* Called for each advertising BLE server. */ void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); // We have found a device, let us now see if it contains the service we are looking for. //if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { if (advertisedDevice.haveName() && (advertisedDevice.getName() == "Flower care")) {

    //
    Serial.print("Found our device!  address: ");
    advertisedDevice.getScan()->stop();

    pServerAddress = new BLEAddress(advertisedDevice.getAddress());
    doConnect = true;

  } // Found our server
} // onResult

}; // MyAdvertisedDeviceCallbacks

void setup() { Serial.begin(115200); Serial.println("Starting Arduino BLE Client application..."); BLEDevice::init("");

// Retrieve a Scanner and set the callback we want to use to be informed when we // have detected a new device. Specify that we want active scanning and start the // scan to run for 30 seconds. Serial.print("Device is initialized -> ");Serial.println(BLEDevice::getInitialized());

BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->start(30); } // End of setup.

void loop() {

// If the flag "doConnect" is true then we have scanned for and found the desired // BLE Server with which we wish to connect. Now we connect to it. Once we are // connected we set the connected flag to be true. if (doConnect == true) { if (connectToServer(*pServerAddress)) { Serial.println("We are now connected to the BLE Server."); connected = true; } else { Serial.println("We have failed to connect to the server; there is nothing more we will do."); } //doConnect = false; }

delay(1000); // Delay a second between loops. countID++; Serial.print("Next connect "); Serial.println(countID); } // End of loop

I will solve this. But for now I am stuck. Need help to debug.

JeroenBeemster avatar Jul 12 '18 19:07 JeroenBeemster

Its possible there might be some memory leak somewhere (just guessing now), but this requires some more heap trace debugging or at least free heap printing, somewhere in onConnect(): ESP_LOGW("TAG", "%d: - RAM left %d", __LINE__, esp_get_free_heap_size()); Im not sure this will work in arduino without changes but im sure you can find a way to print it.

chegewara avatar Jul 12 '18 19:07 chegewara

Your line works. It starts 135772 memory with and ends with 4096 after looping 24 times. I will tomorrow check in detail where the leak is.

JeroenBeemster avatar Jul 12 '18 20:07 JeroenBeemster

I found the memory leak. pClient = BLEDevice::createClient(); should be in setup instead of connecttoserver(). Thanks

JeroenBeemster avatar Jul 14 '18 10:07 JeroenBeemster

I am heading a new issue. I do not understand: After running some time. I got the following issue:Forming a connection to c4:7c:8d:66:13:9a E (106920) BT_GATT: application already registered. E (106920) BT_APPL: Register with GATT stack failed. E (106923) BT_GATT: application already registered. E (106929) BT_APPL: Register with GATT stack failed. E (106935) BT_GATT: application already registered. E (106940) BT_APPL: Register with GATT stack failed. E (106946) BT_GATT: application already registered. E (106951) BT_APPL: Register with GATT stack failed. E (106957) BT_GATT: application already registered. E (106963) BT_APPL: Register with GATT stack failed. E (106969) BT_GATT: application already registered. E (106974) BT_APPL: Register with GATT stack failed. E (106981) BT_APPL: bta_gattc_process_api_open Failed, unknown client_if: 0 And then it stops running. I can see that this causes the issue. pClient->connect(pAddress); When connecting twise. (the message is quite clear :) ) I added a delay of 200ms. between pClient->isConnected() That makes is much more stable.. But still not relyable. The following construction does not help either. if(!pClient->isConnected()){
pClient->connect(pAddress); } Any suggestion?

JeroenBeemster avatar Jul 14 '18 11:07 JeroenBeemster

This lines:

E (106920) BT_GATT: application already registered.
E (106920) BT_APPL: Register with GATT stack failed.

mean you have BLEDevice::createServer() somewhere in loop, but it can be invoked only one time in setup.

chegewara avatar Jul 14 '18 12:07 chegewara

Just one question, how many characteristics and descriptors are you creating?

chegewara avatar Jul 14 '18 12:07 chegewara

Many thanks chegeware. Helping me with this. I am actually using only a client to get data from a server. So zero descriptors or characteristics are created. Only reading. (see code above)
BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->start(30);
pClient = BLEDevice::createClient();

It works fine now.

The other issue is in the loop: start function

if(!pClient->isConnected()){ // should never appear pClient->connect(pAddress); } delay(400); Serial.println(" - Connected to server"); if(!pClient->isConnected()){ Serial.println(" - Not connected"); return false; } .... some code. pClient->disconnect(); end of function I can see that sometimes it is not connected. I stop the function When I run the function again. It is still not not connected But will give the message:

E (106920) BT_GATT: application already registered. E (106920) BT_APPL: Register with GATT stack failed.

JeroenBeemster avatar Jul 14 '18 12:07 JeroenBeemster

For some reason, i dont know why because i dont know your code, you are calling pClient->connect(pAddress); when your client is already connected but pClient->isConnected() is still returning false: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEClient.cpp#L99

Please try to use longer delay.

chegewara avatar Jul 14 '18 13:07 chegewara

a longer delay did the trick. Again thanks a lot. 400ms was too short. I am using 1000ms now. But that sounds a lot. Anyway it runs stable now.

JeroenBeemster avatar Jul 14 '18 13:07 JeroenBeemster

This is required only because your code is write this way. You have to remember there is always some latency between peer devices, even if 400ms sounds a lot to me, for some reason you need more delay. Maybe you need to think about re-writing code, or leave it as it is if that fits you.

chegewara avatar Jul 14 '18 14:07 chegewara

#Now I am facing the last error. Most likely the hardest one. Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled. Core 0 register dump: PC : 0x4013c802 PS : 0x00060030 A0 : 0x80122498 A1 : 0x3ffd2400 0x4013c802: L2CA_CheckIsCongest at C:/esp32/esp-idf/components/bt/bluedroid/stack/l2cap/l2c_api.c:1849

A2 : 0x00000000 A3 : 0x00000000 A4 : 0x3ffdf0d6 A5 : 0x3ffdf0cc A6 : 0x00000000 A7 : 0x6c615665 A8 : 0x8013c7f7 A9 : 0x3ffd23d0 A10 : 0x3ffda840 A11 : 0x3ffd24ac A12 : 0x0000000a A13 : 0x3ffc3ae8 A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000010 EXCCAUSE: 0x0000001c EXCVADDR: 0x000000e8 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff

Backtrace: 0x4013c802:0x3ffd2400 0x40122495:0x3ffd2430 0x4011f255:0x3ffd2490 0x400f7547:0x3ffd24e0 0x400f7949:0x3ffd2570 0x400f675a:0x3ffd25c0 0x400e3fc4:0x3ffd25f0 0x4013c802: L2CA_CheckIsCongest at C:/esp32/esp-idf/components/bt/bluedroid/stack/l2cap/l2c_api.c:1849 0x40122495: esp_ble_gattc_write_char at C:/esp32/esp-idf/components/bt/bluedroid/api/esp_gattc_api.c:536 0x4011f255: BLERemoteCharacteristic::writeValue(std::__cxx11::basic_string<char, std::char_traits, std::allocator >, bool) at C:/esp32/msys32/home/Jeroenbeemster/esp/temphumiditytest/components/arduino/libraries/B LE/src/BLERemoteCharacteristic.cpp:541 0x400f7547: connectToServerFlowerCare(BLEAddress) at C:/esp32/msys32/home/Jeroenbeemster/esp/temphumiditytest/main/ble.cpp:143 (discriminator 1) 0x400f7949: bleReadHumiditySensor() at C:/esp32/msys32/home/Jeroenbeemster/esp/temphumiditytest/main/ble.cpp:381 It stops at this line: pRemoteCharacteristic->writeValue(valueToWrite, true); It is not clear for me why. It is just once every 20-25 times.

JeroenBeemster avatar Jul 14 '18 18:07 JeroenBeemster

https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/ArduinoBLE.md#decoding-an-exception-stack-trace

chegewara avatar Jul 14 '18 19:07 chegewara

Thanks. I will find the cause.

JeroenBeemster avatar Jul 14 '18 19:07 JeroenBeemster

Hi everybody, during my test I found some problems when a client connect and disconnect several time to a server. As You suggested I tried to add a delay(1000) on if(!pClient->isConnected()){ // should never appear pClient->connect(pAddress); } delay(1000); Serial.println(" - Connected to server"); if(!pClient->isConnected()){......

but sometimes this not work for me, I supposed this situation: pClient->connect(pAddress); is called stay pending for some reasons pClient->isConnected() is not set correctly because connect is pending after a while pClient->connect(pAddress); is called again and this hang the board

As workaround before to call a pClient->connect(pAddress); I call pClient->disconnect(); This solved the problem for me. Best Regards Marco

mpbejo avatar Nov 19 '18 14:11 mpbejo

@mpbejo Could you test code i just pushed to features branch? Now library should be able to work with multiple clients so no need to disconnect, also fixed few other issues, like scan memory leak etc.

chegewara avatar Nov 19 '18 14:11 chegewara

Hi chegewara, thank You for the great work. A little problem... I don't know how to do. (sorry) I explain better, actually I installed arduino ide, add the esp32 board and I found the Esp32 BLE Arduino in the Samples. Now how can I install the new library from features branch that You suggest? I have to copy and paste the files or what. Thank You for your patience Best Regards Marco

mpbejo avatar Nov 19 '18 16:11 mpbejo

I can prepare zip file if you wish, then you can use this tutorial: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/ArduinoBLE.md#replacing-the-version-that-comes-with-arduino-esp32

chegewara avatar Nov 19 '18 16:11 chegewara

Yes please, so I am sure that the files are correct. And then I start to test! A big question, do You know how many clients can connect to a server? Best Regards Marco

mpbejo avatar Nov 20 '18 07:11 mpbejo

bluetooth specs says about 8 devices, but arduino-esp32 is setup to 3 or 4. I performed yesterday test (im not sure it was correct test) and i was able to connect 9 clients to one esp32 server, which is very strange.

chegewara avatar Nov 20 '18 08:11 chegewara

Hi chegewara, I have downloaded the zip file from github selecting Branch:features. Then following the instructions of the link that You sent me I tried to build the ESP32_BLE.zip but the "make" command is not recognized on windows. Could You attach the ESP32_BLE.zip file with your latest changes. Thank You Best Regards Marco

mpbejo avatar Nov 20 '18 14:11 mpbejo

Well, I think that I was able to install the library, I deleted the BLE folder from /hardware/esp32. Then in the Arduino IDE / Sketch / #include library / Add library from .ZIP file / and I selected the ZIP file downloaded from github, I compiled with no errors I hope it is correct!

mpbejo avatar Nov 21 '18 10:11 mpbejo

Sorry is not working, I don't understand if I wrong to install the new library or if there is some new bugs. The server version of my sketch is compiled with no problem. The client have errors during compile it say that there is more than one "SPI.h" library I tried to change the order of the #include #include "xbm.h" // Sketch tab header for xbm images #include <TFT_eSPI.h> // Hardware-specific library #include <SPI.h> #include "Wire.h" #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEScan.h> #include <BLEAdvertisedDevice.h>

and I was able to compile: Now the client connect to server but when pRemoteCharacAddr = pRemoteService->getCharacteristic(charUUID_Addr); is called I have this error: E (14478) boot: Assert failed in heap_caps_free, /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/heap_caps.c:261 (heap != NULL && "free() target pointer is outside heap areas") Task watchdog got triggered. The following tasks did not reset the watchdog in time:

  • IDLE (CPU 0) Tasks currently running: CPU 0: Btc_task CPU 1: IDLE

As You wrote on https://github.com/espressif/arduino-esp32/issues/2012

mpbejo avatar Nov 21 '18 13:11 mpbejo

@mpbejo Can you check charUUID_Addr is the same on ble peripheral and pRemoteService != nullptr?

chegewara avatar Nov 21 '18 18:11 chegewara

Yes is the same, and now I have reinstalled the default BLE library and the sketch run correctly. Any suggestion? Can You confirm that my steps (wrote upper) to install the new library are correct? Because I think if You don't have my same problem I suppose I wrong something

mpbejo avatar Nov 22 '18 07:11 mpbejo

@mpbejo Could you try with this zip file: https://github.com/nkolban/esp32-snippets/issues/717#issuecomment-440858956

chegewara avatar Nov 22 '18 07:11 chegewara

No difference. with #717 zip. When the BLE is too far away it hangs. Does this help?

JeroenBeemster avatar Feb 21 '19 19:02 JeroenBeemster

I am having the same issue. do yo solve this problem?

Fazarmd avatar Jun 06 '20 06:06 Fazarmd

I think It was in my code. I believe I pointed to a nullpointer. I am not sure anymore (too long ago). Anyway. I restarted the ESP if there was a time out. (after 2 minutes). Here is my code:

/* >>>>>>>> bandaid begin try do continue even when no data is there / / */ hw_timer_t * timer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

void IRAM_ATTR onTimer() { portENTER_CRITICAL_ISR(&timerMux); ESP.restart(); // restart the ESP when it takes too long //Serial.print("Something happend. Please take action! "); portEXIT_CRITICAL_ISR(&timerMux);

}

void bandAidStartTimer() { timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &onTimer, true); timerAlarmWrite(timer, 1000000*120, false); // 2 minutes once a reset true); timerAlarmEnable(timer); }

void bandAidStopTimer() { timerEnd(timer); timer = NULL; }

/* <<<<<<<<<< band iad end */

bandAidStartTimer(); // start BandAid , restart ESP32 after 2 minutes. So that hangs in write() is not causing a full stop. ..............Your BLE reading, that might hang......................... bandAidStopTimer(); // stop BandAid

JeroenBeemster avatar Jun 07 '20 11:06 JeroenBeemster

Hello, I have spent 3 days & nights trying to exchange data between my 2 ESP32 (DOIT ESP32 DEVKIT 1) without success. I tryed also your solution but I am always stuck there: the client replies in serial: "We have failed to connect to the server; there is nothing more we will do." I can test BLE_Server with my smartphone and everything is OK: read and write operation. I give you below the serial output. It is possible to share your codes: for the server and for the client ? Thanks for any help.

"Starting Arduino BLE Client application... BLE Advertised Device found: Name: , Address: 30:61:e6:c9:4f:80, manufacturer data: 0600010f20021a1e6cbdf0bc92667989c792c80877f8abfdc8d7444dda BLE Advertised Device found: Name: Long name works now, Address: 94:b9:7e:e4:a3:da, serviceUUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, txPower: 3 Forming a connection to 94:b9:7e:e4:a3:da

  • Created client
  • Connected to server TAG120980: - RAM left 1073610484
  • Found our service
  • Found our characteristic The characteristic value was: Hello World says Neil We have failed to connect to the server; there is nothin more we will do. Setting new characteristic value to "Time since boot: 2" Setting new characteristic value to "Time since boot: 4" Setting new characteristic value to "Time since boot: 5" " Used sources are : https://github.com/nkolban/ESP32_BLE_Arduino

JoFRT avatar Sep 07 '21 04:09 JoFRT