Skip to content

The Nimble BLE_Paired_Device_Info NOT stored in NVS, and forgotton after every reboot. #11834

@Rob58329

Description

@Rob58329

Board

ESP32C3 or ESP32S3

Device Description

Board only

Hardware Configuration

Board only

Version

latest stable Release (if not listed below)

Type

Bug

IDE Name

Arduino IDE v1.8.19 with github.com/espressif/arduino-esp32 as at 14Sep25

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

115200

Description

The Nimble BLE_Paired_Device_Info NOT stored in NVS, and forgotton after every reboot.
This failure to save occurrs on both the ESP32C3 and ESP32S3, so probably on all ESP32-NimBLE devices

The below sketch allows this issue to be tested.

Test-A: pair-your-phone to the ESP32C3/ESP32S3, check its paired by pressing 'd'. Then reboot the ESP32S3, and press 'd' again (or try to re-connect your phone).

Test-B: pair-your-phone to the ESP32C3/ESP32S3, check its paired by pressing 'd'. Then delete NVS by pressing 'z'. Then check 'd' again. (or dis/re-connect your phone)

Sketch

// BLE NimBLE: The Nimble BLE_Paired_Device_Info NOT stored in NVS, and forgotton after every reboot.
// This failure to save occurrs on both the ESP32C3 and  ESP32S3, so probably on all ESP32-NimBLE devices

// Test-A: pair-your-phone to the ESP32C3/ESP32S3, check its paired by pressing 'd'. Then reboot the ESP32S3, and press 'd' again (or try to re-connect your phone).
// Test-B: pair-your-phone to the ESP32C3/ESP32S3, check its paired by pressing 'd'. Then delete NVS by pressing 'z'.  Then check 'd' again. (or dis/re-connect your phone)

#if !defined(CONFIG_NIMBLE_ENABLED)
  #error "This code only works using NimBLE"
#endif

#define BLE_NAME "Secure BLE Server"
#define SERVER_PIN 123456

boolean BLE_running=0;

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

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer)    {Serial.printf("Device connected (ID=%u)\n",pServer->getConnId()); delay(2);}
  void onDisconnect(BLEServer *pServer) {Serial.println("Device Disconnected"); delay(2);}
};

class MySecurityCallbacks : public BLESecurityCallbacks {
    void onPassKeyNotify(uint32_t pass_key) {Serial.println("Requested PassKey from Client");}
    void onAuthenticationComplete(ble_gap_conn_desc *desc ) {
      boolean BLE_security=desc->sec_state.bonded;
      Serial.printf("&&&&& Authentication %s &&&&&\n", BLE_security ? "OK" : "FAIL"); delay(2);
      if((!BLE_security) and (pServer)) pServer->disconnect(pServer->getConnId());
    }
};

void setup() {
  Serial.begin(115200); delay(2999);
  Serial.printf("ESP_ARDUINO=v%s+\n",ESP_ARDUINO_VERSION_STR); // ESP_ARDUINO=v3.3.0+
  Serial.print("Using BLE stack: "); Serial.println(BLEDevice::getBLEStackString());
  BLE_server_start(BLE_NAME);
  Serial.printf("Now you can Connect from your phone (pw=%u)\n",SERVER_PIN);
  Serial.println("[Serial Commands: d=Display Bonds, e=Erase All-Bonds, z=reset_NVS]"); 
}


void loop() { 
  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)
      #error "Use Nimble fot this issue"
    #else
      if (c=='d') {Serial.print("->"); Serial.printf("getNumBonds=%i\n", getNumBonds());}
      if (c=='e') {Serial.println("->deleteAllBonds"); deleteAllBonds();}
      if (c=='z') {Serial.print("->"); reset_NVS();}
   #endif
  }
  delay(100);
}

uint32_t BLE_passkey=SERVER_PIN;
void BLE_server_start(const char* BLE_name) { 
  if (BLE_running) Serial.println("Already Running");
  else {
    BLE_running=true;
    Serial.println("Starting BLE");
    BLEDevice::init(BLE_name); delay(50);
    MySecurityCallbacks *mySecurityCallbacks = new MySecurityCallbacks();
    BLEDevice::setSecurityCallbacks(mySecurityCallbacks);
    BLESecurity *pSecurity = new BLESecurity();
    pSecurity->setCapability(ESP_IO_CAP_OUT);
    pSecurity->setPassKey(true, BLE_passkey);
    pSecurity->setAuthenticationMode(true, true, true);
    pServer = BLEDevice::createServer(); 
    pServer->advertiseOnDisconnect(true);
    BLEServerCallbacks *myServCallbacks=new MyServerCallbacks();
    pServer->setCallbacks(myServCallbacks);
    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
    pAdvertising->setMaxPreferred(0x12);
    BLEDevice::startAdvertising();   
  }
}

#include <nvs_flash.h>
void reset_NVS() {
  Serial.println("Clearing NVS pairing data (but does NOT currently clear THESE bonds)...");
  nvs_flash_erase();
  nvs_flash_init();
}

int getNumBonds() {
  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)); // NOT using ble_store_util_peer_set!
    if (rc) num_peers=-1; // an error has occured
  } else Serial.println("Err: BLE not running");
  return num_peers;
}

bool deleteAllBonds() {
  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);
}

Debug Message

ESP_ARDUINO=v3.3.0+
Using BLE stack: NimBLE
Starting BLE
Now you can Connect from your phone (pw=123456)
[Serial Commands: d=Display Bonds, e=Erase All-Bonds, z=reset_NVS]
Device connected (ID=1)
Requested PassKey from Client
&&&&& Authentication OK &&&&&
d->getNumBonds=1

z->Clearing NVS pairing data (but does NOT currently clear THESE bonds)...

d->getNumBonds=1

// Rebooted Board Here

ESP_ARDUINO=v3.3.0+
Using BLE stack: NimBLE
Starting BLE
Now you can Connect from your phone (pw=123456)
[Serial Commands: d=Display Bonds, e=Erase All-Bonds, z=reset_NVS]
d->getNumBonds=0



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

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions