Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown when trying to connect to Wahoo Tickr #1169

Open
esranonff opened this issue Jul 9, 2023 · 0 comments

Comments

@esranonff
Copy link

Hey folks,

The following code worked perfectly well when the library was separate from the Arduino base libraries, however it now throws the above error.

The device is an ESP32Dev-C1, and I'm programming via platformio.

Platformio Ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
; change microcontroller
board_build.mcu = esp32
build_flags = !./bin/build_flags.sh
board_build.partitions = min_spiffs.csv
lib_deps = 
	knolleary/PubSubClient@^2.8.0
;	nkolban/ESP32 BLE Arduino@^1.0.1
	bblanchon/ArduinoJson@^6.18.0

buildflags.sh

#!/bin/bash
source .env
echo -n "
-DWIFI_PASS=${WIFI_PASS}
-DWIFI_SSID=${WIFI_SSID}
-DMQTT_SERVER=${MQTT_SERVER}
-DMQTT_USER=${MQTT_USER}
-DMQTT_PASS=${MQTT_PASS}
-DMQTT_PORT=${MQTT_PORT}
-DMQTT_PROTO=${MQTT_PROTO}
"

Application Code:

#include "BLEDevice.h"
#include "ArduinoJson.h"
#include <WiFi.h>
#include <PubSubClient.h>
#define ST(A) #A
#define STR(A) ST(A)

char device_type[] = "heartrate_monitor";

// TypeDef
typedef struct {
  char ID[20];
  uint16_t HRM;
}HRM;
HRM hrm;
// BLE
// The remote HRM service we wish to connect to.
static  BLEUUID serviceUUID(BLEUUID((uint16_t)0x180D));
// The HRM characteristic of the remote service we are interested in.
static  BLEUUID    charUUID(BLEUUID((uint16_t)0x2A37));

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

// Wifi
WiFiClient wifi_client;
const char* ssid     = STR(WIFI_SSID);
const char* password = STR(WIFI_PASS);

// MQTT
PubSubClient mqtt(wifi_client);
const char* mqtt_server = STR(MQTT_SERVER);
const String base_topic = "st/heartrate/status";
long lastReconnectAttempt = 0;

//--------------------------------------------------------------------------------------------
// A dummy callback for mqtt
//--------------------------------------------------------------------------------------------
void callback(char* topic, byte* payload, unsigned int length) {
    Serial.println(topic);
}
//
//--------------------------------------------------------------------------------------------
// MQTT reconnect
//--------------------------------------------------------------------------------------------
boolean reconnect() {
  if (mqtt.connect("ESP32Client", (base_topic + "esp32" + F("/$online")).c_str(), 1, true, "false")) {
    Serial.println(F("MQTT Connected"));
    
    // Once connected, publish an announcement...
    //sendMqttStats();
    
    // ... and resubscribe
  }
  return mqtt.connected();
} // End of reconnect


//--------------------------------------------------------------------------------------------
// Send HRM stats to MQTT
//--------------------------------------------------------------------------------------------
void sendHRMData() {
  String macaddr = String(WiFi.macAddress());
  macaddr.replace(":", "");
  macaddr.toLowerCase();
  char pub_mac_addr[16];
  macaddr.toCharArray(pub_mac_addr, 16);
  String pub_topic = "heartrate";
  char snd_topic[100];
  pub_topic.toCharArray(snd_topic, 100);
  Serial.println("Message received from chest strap, sending to MQTT");
  DynamicJsonDocument  dataJson(20);

  dataJson[F("HRM")]             = hrm.HRM;
  char buffer[20];
  serializeJson(dataJson, buffer);
  mqtt.publish(snd_topic, buffer);
}

//--------------------------------------------------------------------------------------------
// BLE notifyCallback
//--------------------------------------------------------------------------------------------
static void notifyCallback( BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
    Serial.println("Callback attached");

  if (bitRead(pData[0], 0) == 1) {
    Serial.println(F("16bit HeartRate Detected"));
  } else {
    Serial.println(F("8bit HeartRate Detected"));
  }

  Serial.print("Length passed is ");
  Serial.println(length);


  if (length > 2) {
    hrm.HRM = pData[1];
    Serial.print("Heart Rate ");
    Serial.print(hrm.HRM, DEC);
    Serial.println("bpm");

    sendHRMData();
  }
}

//--------------------------------------------------------------------------------------------
//  Connect to BLE HRM
//--------------------------------------------------------------------------------------------
bool connectToServer(BLEAddress pAddress) {
    Serial.print(F("Forming a connection to "));
    Serial.println(pAddress.toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(F(" - Created client"));
    
    // Connect to the HRM BLE Server.
    pClient->connect(pAddress, BLE_ADDR_TYPE_RANDOM);
    Serial.println(F(" - 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(F("Failed to find our service UUID: "));
      Serial.println(serviceUUID.toString().c_str());
      return false;
    }
    Serial.println(F(" - 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(F("Failed to find our characteristic UUID: "));
      Serial.println(charUUID.toString().c_str());
      return false;
    }
    Serial.println(F(" - Found our characteristic"));

    // Register for Notify
    pRemoteCharacteristic->registerForNotify(notifyCallback);
}

//--------------------------------------------------------------------------------------------
// 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(F("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)) {

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

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

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks

void firmware_updates(char* topic, byte* payload, unsigned int length) {
  Serial.println(topic);
};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  /* Explicitly set the ESP32 to be a WiFi-client, otherwise, it by default,
     would try to act as both a client and an access-point and could cause
     network-issues with your other WiFi-devices on your WiFi-network. */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(F("."));
  }

  Serial.println("");
  Serial.println(F("WiFi connected"));
  Serial.print(F("IP address: "));
  Serial.println(WiFi.localIP());

  // MQTT
  mqtt.setServer(mqtt_server, 1883);
  mqtt.setCallback(callback);

  lastReconnectAttempt = 0;
  // Start BLE
  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.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
}


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(F("We are now connected to the BLE HRM"));
      connected = true;
    } else {
      Serial.println(F("We have failed to connect to the HRM; there is nothin more we will do."));
    }
    doConnect = false;
  }

  // Turn notification on
  if (connected) {
    if (notification == false) {
      Serial.println(F("Turning Notifocation On"));
      const uint8_t onPacket[] = {0x1, 0x0};
      pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)onPacket, 2, true);
      notification = true;
    }

  }

  if (!mqtt.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;
      // Attempt to reconnect
      if (reconnect()) {
        Serial.println("connected");
        DynamicJsonDocument systemDescription(1024);

        String macaddr = String(WiFi.macAddress());
        Serial.print("Found MAC ADDRESS: ");
        Serial.println(macaddr);
        macaddr.replace(":", "");
        macaddr.toLowerCase();
        char pub_mac_addr[16];
        macaddr.toCharArray(pub_mac_addr, 16);

        systemDescription["device_type"] = "heartrate_monitor";
        systemDescription["device_details"]["name"] = "heartrate_01";
	systemDescription["device_details"]["end_device_count"] = 1;
	systemDescription["device_details"]["devices"][0]["name"] = "chest_strap";

        char bodyString[500];
        serializeJson(systemDescription, bodyString, sizeof(bodyString));
        serializeJson(systemDescription, Serial);
        Serial.println();
        Serial.println(bodyString);
        String pub_topic = "st/register";
        char pub_topic_name[50];
        pub_topic.toCharArray(pub_topic_name, 50);
        Serial.print("Publishing to: ");
        Serial.println(pub_topic_name);
        // Once connected, publish an announcement...
        mqtt.publish(pub_topic_name, bodyString);
        lastReconnectAttempt = 0;
      }
    }
  } else {
    // Client connected
    mqtt.loop();
  }
}

The error in full (MAC address redacted)

BLE Advertised Device found: Name: TICKR B444, Address: <MAC>, appearance: 833, serviceUUID: 0000180d-0000-1000-8000-00805f9b34fb
Found our device!  address: Forming a connection to <MAC>
 - Created client
 - Connected to server
 - Found our service
[  6911][E][BLERemoteCharacteristic.cpp:287] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
 - Found our characteristic

assert failed: heap_caps_free heap_caps.c:339 (heap != NULL && "free() target pointer is outside heap areas")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant