Skip to content

"BLEDevice::deinit(false);" does NOT work properly (on v3.3.1) #11906

@Rob58329

Description

@Rob58329

Board

ESP32 NodeMCU

Device Description

Board only

Hardware Configuration

Board only

Version

latest stable Release (if not listed below) ("github.com/espressif/arduino-esp32" as at 7Oct25)

Type

Task

IDE Name

Adruino IDE v1.8.19

Operating System

Window10

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

115200

Description

On v3_3_1 "BLEDevice::deinit(false);" does NOT work properly, and after a following "BLEDevice::init()" you can't connect
to the "ESP32-BLE-SECURE" Server (eg. using the "nRF Connect" Android App).

[cf. before you do a "BLEDevice::deinit(false);" when you can connect reliably every time.]

(PS. On v3_3_0 [with slight modifications to "BLEDevice.cpp"] the CONFIG_BLUEDROID_ENABLED "BLEDevice::deinit(false);" command DOES appear to work correctly!)

Sketch

// On v3_3_1 "BLEDevice::deinit(false);" does NOT work properly, and after a following "BLEDevice::init()" you can't connect
// to the "ESP32-BLE-SECURE" Server (eg. using the "nRF Connect" Android App). 

// [cf. before you do a "BLEDevice::deinit(false);" when you can connect reliably every time.]

// (PS. On v3_3_0 [with slight modifications to "BLEDevice.cpp"] the CONFIG_BLUEDROID_ENABLED "BLEDevice::deinit(false);" command DOES appear to work correctly!)

#define SERVER_PIN 123456 
#define SERVER_NAME "ESP32-BLE-SECURE"

#if (ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(3, 3, 0))
  #define USE_v3_3_0_SW
#endif

volatile boolean BLE_connect=0;
volatile boolean BLE_security=0;
boolean BLE_running=0;
int BLE_bonded=0;

#include "BLEDevice.h"
#include "BLEServer.h"
BLEServer   *pServer=nullptr;
BLESecurity *pSecurity=nullptr;

void setup() {
  Serial.begin(115200); delay(3000);
  Serial.printf("ESP_ARDUINO=v%s\n",ESP_ARDUINO_VERSION_STR);
  #ifdef USE_v3_3_0_SW
    Serial.println("Using v3.3.0");
  #else // v3.3.1
    Serial.print("Using BLE stack: "); Serial.println(BLEDevice::getBLEStackString());
  #endif
  BLE_server_start(SERVER_NAME);
  Serial.println("\nSerial Commands: d=Display Bonds, e=Erase All-Bonds, x=BLE_server_STOP, y=BLE_server_START"); 
}

uint32_t heap_old=0;
boolean security_old=false; 
void loop() { 
  boolean security=BLE_security; if (security_old!=security) {security_old=security; Serial.printf("*** BLE_security=%s ***\n", security ? "On" : "Off");} 
  while (Serial.available()) {
    char c=Serial.read();
    if (c>=32) Serial.write(c);
    else if (c==10) {}
    else Serial.println();
    #if defined(CONFIG_BLUEDROID_ENABLED)
      if (c=='d') {Serial.print("->"); show_bonded_devices();}
      if (c=='e') {Serial.print("->"); remove_all_bonded_devices();}
      if (c=='x') {Serial.print("->"); BLE_server_stop();}
      if (c=='y') {Serial.print("->"); BLE_server_start(SERVER_NAME);}
    #elif defined(CONFIG_NIMBLE_ENABLED)
      if (c=='d') {Serial.printf("->number_of_bonded_devices=%i\n", number_of_bonded_devices());}
      if (c=='e') {Serial.print("->"); remove_all_bonded_devices();}
      if (c=='x') {Serial.print("->"); BLE_server_stop();}
      if (c=='y') {Serial.print("->"); BLE_server_start(SERVER_NAME);}
   #endif
  }
  delay(100);
}

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer)    {BLE_connect=true; Serial.println("*BLE Device connected");}
  #ifdef USE_v3_3_0_SW 
    void onDisconnect(BLEServer *pServer) {BLE_connect=false; BLE_security=false; pServer->startAdvertising(); Serial.println("*Device Disconnected");}
  #else // v3.3.1
    void onDisconnect(BLEServer *pServer) {BLE_connect=false; BLE_security=false; Serial.println("*Device Disconnected");}
  #endif
};

BLEServerCallbacks  *myServerCallbacks=nullptr;

void BLE_security_disconnect() {if (pServer) pServer->disconnect(pServer->getConnId()); BLE_security=false;}


class MySecurityCallbacks : public BLESecurityCallbacks {
  uint32_t onPassKeyRequest()                             {Serial.println("BLE onPassKeyRequest"); return SERVER_PIN;} 
  void onPassKeyNotify(uint32_t pass_key)                 {Serial.printf("BLE Requested PassKey from Client=%u\n",pass_key);}
  bool onConfirmPIN(uint32_t pass_key)                    {Serial.println("BLE onConfirmPIN"); vTaskDelay(5000); return true;}
  bool onSecurityRequest()                                {Serial.println("BLE onSecurityRequest"); return true;}
  #if defined(CONFIG_BLUEDROID_ENABLED) 
    void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl) {
      BLE_security=(cmpl.success);
  #elif defined(CONFIG_NIMBLE_ENABLED)
    void onAuthenticationComplete(ble_gap_conn_desc *desc ) {
      Serial.printf("authenticated=%i\n",desc->sec_state.authenticated); delay(1);
      Serial.printf("bonded=%i\n",desc->sec_state.bonded); delay(1);
      Serial.printf("authorize=%i\n",desc->sec_state.authorize); delay(1);
      BLE_security=desc->sec_state.bonded;
  #endif
    Serial.printf("**Authentication %s\n", BLE_security ? "OK" : "FAIL"); delay(1);
    if (BLE_security==0) BLE_security_disconnect();
   }
};
MySecurityCallbacks *mySecurityCallbacks=nullptr;

void heap_display(int x=0) {
  static uint32_t heap_old=0;
  uint32_t heap_new=ESP.getFreeHeap();
  Serial.printf("Heap%i=%u (diff=%i)\n",x,heap_new,heap_old-heap_new);
  heap_old=heap_new;
}


void BLE_server_stop() {
  if (BLE_running) {
    Serial.println("BLE_server_stop");
    BLE_bonded=number_of_bonded_devices();
    BLE_running=false;
    BLEDevice::stopAdvertising(); delay(50);
    BLEDevice::deinit(false); delay(999);
    if (pSecurity) {delete pSecurity; pSecurity=nullptr; Serial.println("del pSecurity");}
    delay(50); heap_display(0);
  } else Serial.println("BLE Already Stopped");
}

void BLE_server_start(const char* BLE_NAME) {
  if (BLE_running) Serial.println("BLE Already Running");
  else {
    BLE_running=true;
    Serial.println("BLE_server_start");
    heap_display(1);
    BLEDevice::init(BLE_NAME); delay(50);
    pServer=BLEDevice::createServer(); // will only do anything if not already created!
    if (myServerCallbacks==nullptr) {myServerCallbacks=new MyServerCallbacks(); Serial.println("new MyServerCallbacks()");}
    pServer->setCallbacks(myServerCallbacks);
    BLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->setScanResponse(true); // default is already true
    pAdvertising->setMinPreferred(0x06); // set to 0x06 to help with iPhone connections issue
    pAdvertising->setMaxPreferred(0x40); // leave at 0x40 for Android connections 
    #ifndef USE_v3_3_0_SW 
      pServer->advertiseOnDisconnect(true);
    #endif
    if (mySecurityCallbacks==nullptr) {mySecurityCallbacks = new MySecurityCallbacks(); Serial.println("new MySecurityCallbacks()");} 
    BLEDevice::setSecurityCallbacks(mySecurityCallbacks);
    if (pSecurity==nullptr) {pSecurity = new BLESecurity(); Serial.println("new BLESecurity()");}
    Serial.printf("***** Server[%s] SERVER_PIN=%06u *****\n",BLE_NAME,SERVER_PIN);
    #ifdef USE_v3_3_0_SW 
      pSecurity->setStaticPIN(SERVER_PIN);
      pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
      pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);  
      BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
    #else // v3.3.1
      pSecurity->setPassKey(true, SERVER_PIN);
      pSecurity->setAuthenticationMode(true, true, true);
      BLESecurity::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT); 
    #endif
    pSecurity->setCapability(ESP_IO_CAP_OUT);
    #ifdef CONFIG_BLUEDROID_ENABLED
      uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE; // Necessary: stops Clients with No-PIN connecting/authorising
      esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
    #endif
    pAdvertising->start();   
    delay(50); heap_display(2);
  }
}



#if defined(CONFIG_BLUEDROID_ENABLED)

  inline int number_of_bonded_devices() {return esp_ble_get_bond_device_num();}
  char bda_str[18];
  inline char *bda2str(const uint8_t *bda) {
    sprintf(bda_str, "%02x:%02x:%02x:%02x:%02x:%02x", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
    return bda_str;
  }
  void show_bonded_devices() { 
    int dev_num = esp_ble_get_bond_device_num();
    esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
    esp_ble_get_bond_device_list(&dev_num, dev_list);
    Serial.printf("Bonded devices number: %d\n", dev_num);
    for (int i = 0; i < dev_num; i++) {Serial.printf("Found bonded device #%d = %s\n", i+1, bda2str(dev_list[i].bd_addr));}
    free(dev_list);
  }
  void remove_all_bonded_devices() {
    int dev_num = esp_ble_get_bond_device_num();
    if (dev_num<=0) {Serial.println("All bonds NOT deleted"); return;}
    esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
    esp_ble_get_bond_device_list(&dev_num, dev_list);
    for (int i = 0; i < dev_num; i++) esp_ble_remove_bond_device(dev_list[i].bd_addr);
    free(dev_list);
    Serial.println("All bonds deleted");
  }

#elif defined(CONFIG_NIMBLE_ENABLED)

  int number_of_bonded_devices() {
    int num_peers=-1;
    if (BLE_running) {
      ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
      int rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
      if (rc) num_peers=-1; // error
    } else Serial.println("Err: BLE not running");
    return num_peers;
  }
  bool remove_all_bonded_devices() {
    int rc=-1;
    if (BLE_running) {
      int rc = ble_store_clear();
      if (rc) {Serial.printf("Failed to delete all bonds: rc=%i\n", rc);}
      else    Serial.println("All bonds deleted");
    } else Serial.println("Err: BLE not running");
    return (!rc);
  }

#endif

Debug Message

ESP_ARDUINO=v3.3.1
Using BLE stack: Bluedroid
BLE_server_start
Heap1=229036 (diff=-229036)
new MyServerCallbacks()
new MySecurityCallbacks()
new BLESecurity()
***** Server[ESP32-BLE-SECURE] SERVER_PIN=123456 *****
Heap2=135920 (diff=93116)

Serial Commands: d=Display Bonds, e=Erase All-Bonds, x=BLE_server_STOP, y=BLE_server_START

*BLE Device connected
**Authentication OK
*** BLE_security=On ***
*Device Disconnected
*** BLE_security=Off ***

(ie. works ok before "BLEDevice::deinit(false);")

x->BLE_server_stop // do a "BLEDevice::deinit(false);"
del pSecurity
Heap0=227640 (diff=-91720)

y->BLE_server_start
Heap1=227640 (diff=0)
new BLESecurity()
***** Server[ESP32-BLE-SECURE] SERVER_PIN=123456 *****
Heap2=135892 (diff=91748)

(Now even though ""ESP32-BLE-SECURE" is advertising, you can't connect to it, and you don't get any Serial-Messages)

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions