Esp32-snippets: registerForNotify on a BLERemoteCharacteristic crashes

Created on 26 Sep 2019  路  10Comments  路  Source: nkolban/esp32-snippets

The problem

Hi,
I have managed connecting my ESP to a BLE service, and finding the correct remote characteristic. However, calling registerForNotify results in a crash. I have already tried adding this line:
pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notifyOn, 2, true);
However, after calling this, the ESP crashes as well.

The errors

The error (without writing to the descriptor) is:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d47b3  PS      : 0x00060330  A0      : 0x800d4116  A1      : 0x3ffc85a0  
A2      : 0x00000000  A3      : 0x3ffc85de  A4      : 0x00000002  A5      : 0x00000000  
A6      : 0x3ffdf114  A7      : 0x3f018620  A8      : 0x800d3ea4  A9      : 0x3ffc8550  
A10     : 0x3ffc859c  A11     : 0x3fc322e8  A12     : 0x3ffc5f34  A13     : 0x3fc322e8  
A14     : 0x000000d1  A15     : 0xff000000  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000030  LBEG    : 0x4000c349  LEND    : 0x4000c36b  LCOUNT  : 0x00000000  

The error (when writing to the descriptor) is:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d47ff  PS      : 0x00060130  A0      : 0x800d179d  A1      : 0x3ffc85f0  
A2      : 0x00000000  A3      : 0x3ffc8632  A4      : 0x00000002  A5      : 0x00000001  
A6      : 0x3ffdec48  A7      : 0x3f018670  A8      : 0x800d3ef0  A9      : 0x3ffc85a0  
A10     : 0x3ffc85ec  A11     : 0x6691ff4c  A12     : 0x3ffc5f34  A13     : 0x6691ff4c  
A14     : 0x00000001  A15     : 0x0000002a  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000030  LBEG    : 0x4000c349  LEND    : 0x4000c36b  LCOUNT  : 0x00000000  

Backtrace: 0x400d47ff:0x3ffc85f0 0x400d179a:0x3ffc8620 0x400d1943:0x3ffc8670 0x400d76dd:0x3ffc86b0 0x4008ff39:0x3ffc86d0

I tried pasting these into the "ESP Exception Decoder" but it just says "Decode failed"...

Code

Here is my full code.

#include "BLEDevice.h"
#include <stdint.h>
//#include "BLEScan.h"

// The remote service we wish to connect to.
static BLEUUID serviceUUID("71c1e128-d92f-4fa8-a2b2-0f171db3436c");
// The characteristic of the remote service we are interested in.
static BLEUUID    charUUID("503dd605-9bcb-4f6e-b235-270a57483026");


static BLEAddress *pServerAddress;
static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEClient* pClient;

volatile bool notifyTrigger = false;

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
    if (isNotify) {
      notifyTrigger = true;
    }
}

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

    // Connect to the remove BLE Server.
    bool connected = pClient->connect(pAddress);
    if (!connected) {
      Serial.println("Connection failed.");
      return false;
    }

    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.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");
    Serial.println("Can read:");
    Serial.println(pRemoteCharacteristic->canRead());

    const uint8_t notifyOn[] = {0x01, 0x00};
    Serial.println("Setting descriptor");
    pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notifyOn, 2, true);
    Serial.println("Registering");
    pRemoteCharacteristic->registerForNotify(notifyCallback);

    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)) {
      advertisedDevice.getScan()->stop();
      pServerAddress = new BLEAddress(advertisedDevice.getAddress());
      doConnect = true;
      Serial.println("This device is correct!");
    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks


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

  pClient = BLEDevice::createClient();

  scan();
} // End of setup.

void scan() {
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->start(5, false);
}

// This is the Arduino main loop function.
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;
      doConnect = false;
    } else {
      Serial.println("We have failed to connect to the server; which means we will try again.");
      doConnect = false;
      scan();
    }
  }

  if (notifyTrigger == true) {
    std::string value = pRemoteCharacteristic->readValue();
    Serial.println(value.c_str());
  }



  delay(1000); // Delay a second between loops.
} // End of loop

Most helpful comment

This has been answered already and closed by author.

Which is, as I believe, a problem of the BLE service on the other end, not of this API.

You have to check in app if characteristic has property notify/indicate. Then it is good to check if that characteristic has descriptor 0x2902. I saw few opened issues where the problem was it was missing this descriptor. When you try to write it and it is missing then app will crash.

All 10 comments

I have more info: the debug logs say:

[V][BLERemoteCharacteristic.cpp:438] registerForNotify(): >> registerForNotify(): Characteristic: uuid: 503dd605-9bcb-4f6e-b235-270a574830, handle: 42 0x002a, props: broadcast: 0, read: 1, write_nr: 0, write: 0, notify: 1, indicate: 0, auth: 0
[D][FreeRTOS.cpp:189] take(): Semaphore taking: name: RegForNotifyEvt (0x3ffdf9b4), owner: <N/A> for registerForNotify
[D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: RegForNotifyEvt (0x3ffdf9b4), owner: registerForNotify
[V][BLERemoteCharacteristic.cpp:323] getDescriptor(): >> getDescriptor: uuid: 2902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[V][BLERemoteCharacteristic.cpp:331] getDescriptor(): << getDescriptor: Not found

So, the descriptor is not found.

Which is, as I believe, a problem of the BLE service on the other end, not of this API.

I have the same problem, and want to make my code robust against problems on the other end. Other than a watchdog timer, is there any way I can protect against never returning from registerForNotify?

Hello!, I also run into this problem too. This is what I got

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d52f3 PS : 0x00060330 A0 : 0x800d4b4e A1 : 0x3ffc95a0
A2 : 0x00000000 A3 : 0x3ffc95de A4 : 0x00000002 A5 : 0x00000000
A6 : 0x3ffe0d4c A7 : 0x3f019620 A8 : 0x800d48d8 A9 : 0x3ffc9550
A10 : 0x3ffc959c A11 : 0x53f4a06c A12 : 0x3ffc5318 A13 : 0x53f4a06c
A14 : 0x3ffc9550 A15 : 0xff000000 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000030 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0x00000000
Backtrace: 0x400d52f3:0x3ffc95a0 0x400d4b4b:0x3ffc95d0 0x400d1f52:0x3ffc9620 0x400d2011:0x3ffc9670 0x400d7b19:0x3ffc96e0 0x4008e089:0x3ffc9700

and the exception decoder

0x400d52f3: BLERemoteDescriptor::writeValue(unsigned char, unsigned int, bool) at C:\Users\Automata\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLERemoteDescriptor.cpp line 146
0x400d4b4b: BLERemoteCharacteristic::registerForNotify(void (
)(BLERemoteCharacteristic, unsigned char, unsigned int, bool), bool) at C:\Users\Automata\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLERemoteCharacteristic.cpp line 453
0x400d1f52: connectToServer() at C:\Users\Automata\Documents\Arduino\BLE_client/BLE_client.ino line 78
0x400d2011: connectToServer() at C:\Users\Automata\Documents\Arduino\BLE_client/BLE_client.ino line 105
0x400d7b19: String::substring(unsigned int, unsigned int) const at C:\Users\Automata\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\WString.cpp line 710
0x4008e089: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

I don't know what I missing but this happened after read the characteristic value and keep rebooting.

I continue to have this issue, did the issue get resolved before it was closed?

I had hoped to hear from developers about this, for now my application is running with a watchdog timer and rebooting daily. I'm probably making some dumb rook mistake, and it's beneath anyone to comment. That or nobody has time to look at this issue. Maybe BLE is less popular than wifi. Unfortunately, for my application it's a key technology.

This has been answered already and closed by author.

Which is, as I believe, a problem of the BLE service on the other end, not of this API.

You have to check in app if characteristic has property notify/indicate. Then it is good to check if that characteristic has descriptor 0x2902. I saw few opened issues where the problem was it was missing this descriptor. When you try to write it and it is missing then app will crash.

Thanks @chegewara , is this descriptor present when creating characteristics on the BLE server using the espressif Arduino core? If not, can I simply replace the BLE code in the Arduino core with the nkolban BLE code?

Or is there an example I can look for?

You have to add it each time, but it is easy.
Search for ble 2902 and you will find plenty examples.

Thank you very much @chegewara!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

minwinmin picture minwinmin  路  9Comments

vishnunaik picture vishnunaik  路  6Comments

hansmbakker picture hansmbakker  路  6Comments

hellowtisch picture hellowtisch  路  7Comments

Tavo7995 picture Tavo7995  路  7Comments