Skip to content

ESP32 BLE dual role: Callback error when connecting to Client #9013

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

Closed
1 task done
SAOKIM99 opened this issue Dec 18, 2023 · 4 comments
Closed
1 task done

ESP32 BLE dual role: Callback error when connecting to Client #9013

SAOKIM99 opened this issue Dec 18, 2023 · 4 comments

Comments

@SAOKIM99
Copy link

Board

ESP32 Dev Module

Device Description

KIT ESP32 Dev Module
kit-rf-thu-phat-wifi-bluetooth-esp32-vsto-1

Hardware Configuration

[env:esp32dev]
platform = espressif32 @ 6.4.0
board = esp32dev
framework = arduino
upload_port = COM19
monitor_port = COM19
monitor_speed = 115200

Version

latest master (checkout manually)

IDE Name

Platform IO

Operating System

Windows 11

Flash frequency

40MHz

PSRAM enabled

no

Upload speed

default

Description

I am developing a project using ESP32's BLE with 2 roles at the same time:

  • Server: connects to the phone to send information

  • Client: connects to another BLE device
    Problem:

  • When connecting and disconnecting from the phone:

    • Callback function: only onConnectServer & onDisconnectServer
  • When connecting and disconnecting from a BLE device:

  • Callback functions: onConnectServer & onDisconnectServer and onConnectClient & onDisconnecrClient
    (see message log)

This affects the connection between the ESP32 and the phone when the ESP32 connects or disconnects with another BLE device.
How can the ESP32 recall the correct device being connected and not cause confusion?

Sketch

#include <Arduino.h>
#include "BLEDevice.h"
//#include "BLEScan.h"
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#define SERVICE_UUID        "390950ed-51ff-445f-a6c6-f6a95a6a465f"
#define CHARACTERISTIC_UUID "f2c513b7-6b51-4363-b6aa-1ef8bd08c56a"

static BLEUUID advServiceUUID("db1df223-4020-4c5a-930c-1989ea04991f");
// The remote service we wish to connect to.
static BLEUUID serviceUUID("efedd9eb-24a9-492a-b66a-ed8543ee096e");
// The characteristic of the remote service we are interested in.
static BLEUUID    charUUID("22e5bbd9-62d8-45eb-9ffd-4a2b88cd6c3a");

bool deviceConnected = false;
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;

static void eventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) {
  if (event == ESP_GAP_BLE_SCAN_RESULT_EVT ||
      event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT ||
      event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT 
  ) return;
  Serial.printf("BLE event: %d\n", event);
}  

static void eventClientHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param) {

  Serial.printf("BLE Client event: %d\n", event);
}  

static void eventServerHandler(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param) {

  Serial.printf("BLE Server event: %d\n", event);
}  


static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
}

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("on Connect Server");
      
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("on DisConnect Server");
      BLEDevice::startAdvertising();
    }
};

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
    Serial.println("on Connect Client");
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("on Disconnect Client");
  }
};

bool connectToServer() {
    // Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());
    
    BLEClient*  pClient  = BLEDevice::createClient();
    // Serial.println(" - Created client");

    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    // Serial.println(" - Connected to server");
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)
  
    // 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;
    }


    // 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;
    }

    if(pRemoteCharacteristic->canNotify())
      pRemoteCharacteristic->registerForNotify(notifyCallback);

    connected = true;
    return true;
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {

  void onResult(BLEAdvertisedDevice advertisedDevice) {

    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(advServiceUUID)) {

      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

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


void setup() {
  Serial.begin(115200);
  BLEDevice::init("ESP32 dual role");

  // BLEDevice::setCustomGapHandler(eventHandler);
  // BLEDevice::setCustomGattcHandler(eventClientHandler);
  // BLEDevice::setCustomGattsHandler(eventServerHandler);

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();

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

  Serial.println("START");
} // End of setup.


// This is the Arduino main loop function.
void loop() {
  if (doConnect == true) {
    if (connectToServer()) {
      // Serial.println("Connected to the BLE Server");
    } else {
      // Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;
  }

  if (connected) {

  }else if(doScan){
    BLEDevice::getScan()->start(5);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
  }
  
  delay(1000); // Delay a second between loops.
} // End of loop

Debug Message

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 271414342, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13232
load:0x40080400,len:3028
entry 0x400805e4
START
ac:0b:fb:67:fd:6a
on Connect Server
on Connect Client
[  5940][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[  5941][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[  5950][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
on DisConnect Server
on Disconnect Client
ac:0b:fb:67:fd:6a
on Connect Server
on Connect Client
[1062633][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[1062633][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[1062642][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
on DisConnect Server
on Disconnect Client
ac:0b:fb:67:fd:6a
on Connect Server
on Connect Client
[1376076][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[1376077][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[1376086][E][BLERemoteCharacteristic.cpp:289] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@SAOKIM99 SAOKIM99 added the Status: Awaiting triage Issue is waiting for triage label Dec 18, 2023
@dcsleep
Copy link

dcsleep commented Jan 21, 2024

I ran into this issue with similar code using PlatformIO. That is, BLEServerCallbacks::onConnect is called when a connection is made using BLEClient::connect. Only BLEClientCallbacks::onConnect should be called when a connection is made.

platform = espressif32 @ 6.5.0
board = adafruit_feather_esp32s3_nopsram
framework = arduino

The problem is also documented in #7115. This comment offers a workaround. The PR (#7851) that closed #7115 resolves an issue related to the workaround but does not address the underlying problem.

@SAOKIM99
Copy link
Author

SAOKIM99 commented Oct 4, 2024

Is there any solution to the problem?
Why does the Espressif framework not have this problem but the Arduino framework does?
@lucasssvaz

@lucasssvaz
Copy link
Collaborator

cc @SuGlider

@Parsaabasi Parsaabasi removed the Status: Awaiting triage Issue is waiting for triage label Jan 15, 2025
@Parsaabasi
Copy link

Hello,

Due to the overwhelming volume of issues currently being addressed, we have decided to close the previously received tickets. If you still require assistance or if the issue persists, please don't hesitate to reopen the ticket.

Thanks.

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

4 participants