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

ESP32 BLE dual role: Callback error when connecting to Client

Open SAOKIM99 opened this issue 1 year ago • 3 comments

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

  • [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.

SAOKIM99 avatar Dec 18 '23 07:12 SAOKIM99