Skip to content

feat(NimBLE): Add support for NimBLE #11424

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

Merged
merged 3 commits into from
Jun 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cores/esp32/esp32-hal-bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "esp32-hal-bt.h"

#if SOC_BT_SUPPORTED
#if defined(CONFIG_BT_BLUEDROID_ENABLED) && __has_include("esp_bt.h")
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && __has_include("esp_bt.h")

#if CONFIG_IDF_TARGET_ESP32
bool btInUse() {
Expand Down Expand Up @@ -116,7 +116,7 @@ bool btStop() {
return false;
}

#else // CONFIG_BT_ENABLED
#else // !__has_include("esp_bt.h") || !(defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED))
bool btStarted() {
return false;
}
Expand All @@ -129,6 +129,6 @@ bool btStop() {
return false;
}

#endif /* CONFIG_BT_ENABLED */
#endif /* !__has_include("esp_bt.h") || !(defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) */

#endif /* SOC_BT_SUPPORTED */
11 changes: 6 additions & 5 deletions cores/esp32/esp32-hal-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
#include "esp_ota_ops.h"
#endif //CONFIG_APP_ROLLBACK_ENABLE
#include "esp_private/startup_internal.h"
#if defined(CONFIG_BT_BLUEDROID_ENABLED) && SOC_BT_SUPPORTED && __has_include("esp_bt.h")
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && SOC_BT_SUPPORTED && __has_include("esp_bt.h")
#include "esp_bt.h"
#endif //CONFIG_BT_BLUEDROID_ENABLED
#endif
#include <sys/time.h>
#include "soc/rtc.h"
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32C5)
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) \
&& !defined(CONFIG_IDF_TARGET_ESP32C5)
#include "soc/rtc_cntl_reg.h"
#include "soc/syscon_reg.h"
#endif
Expand Down Expand Up @@ -245,7 +246,7 @@ bool verifyRollbackLater() {
}
#endif

#ifdef CONFIG_BT_BLUEDROID_ENABLED
#if defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)
#if CONFIG_IDF_TARGET_ESP32
//overwritten in esp32-hal-bt.c
bool btInUse() __attribute__((weak));
Expand Down Expand Up @@ -307,7 +308,7 @@ void initArduino() {
if (err) {
log_e("Failed to initialize NVS! Error: %u", err);
}
#if defined(CONFIG_BT_BLUEDROID_ENABLED) && SOC_BT_SUPPORTED
#if (defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)) && SOC_BT_SUPPORTED
if (!btInUse()) {
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
}
Expand Down
8 changes: 6 additions & 2 deletions libraries/BLE/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# ESP32 BLE for Arduino
The Arduino IDE provides an excellent library package manager where versions of libraries can be downloaded and installed. This Github project provides the repository for the ESP32 BLE support for Arduino.

The original source of the project, **which is not maintained anymore**, can be found here: https://github.com/nkolban/esp32-snippets
The original source of the Bluedroid project, **which is not maintained anymore**, can be found here: https://github.com/nkolban/esp32-snippets

Issues and questions should be raised here: https://github.com/espressif/arduino-esp32/issues <br> (please don't use https://github.com/nkolban/esp32-snippets/issues!)
Some parts of the NimBLE implementation are based on the work of h2zero, which can be found here: https://github.com/h2zero/NimBLE-Arduino

Issues and questions should be raised here: https://github.com/espressif/arduino-esp32/issues <br> (please don't use https://github.com/nkolban/esp32-snippets/issues or https://github.com/h2zero/NimBLE-Arduino/issues!)

Documentation for using the library can be found here: https://github.com/nkolban/esp32-snippets/tree/master/Documentation

For a more customizable and feature-rich implementation of the NimBLE stack, you can use the [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino) library.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
author: chegewara
*/
#ifndef SOC_BLE_50_SUPPORTED
#warning "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#ifndef CONFIG_BLUEDROID_ENABLED
#error "NimBLE does not support extended scan yet. Try using Bluedroid."
#elif !defined(SOC_BLE_50_SUPPORTED)
#error "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#else

#include <BLEDevice.h>
Expand Down
3 changes: 2 additions & 1 deletion libraries/BLE/examples/BLE5_extended_scan/ci.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"fqbn_append": "PartitionScheme=huge_app",
"requires": [
"CONFIG_SOC_BLE_50_SUPPORTED=y"
"CONFIG_SOC_BLE_50_SUPPORTED=y",
"CONFIG_BLUEDROID_ENABLED=y"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
author: chegewara
*/

#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#ifndef CONFIG_BLUEDROID_ENABLED
#error "NimBLE does not support multi advertising yet. Try using Bluedroid."
#elif !defined(CONFIG_BT_BLE_50_FEATURES_SUPPORTED)
#error "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#else

Expand Down
3 changes: 2 additions & 1 deletion libraries/BLE/examples/BLE5_multi_advertising/ci.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"fqbn_append": "PartitionScheme=huge_app",
"requires": [
"CONFIG_SOC_BLE_50_SUPPORTED=y"
"CONFIG_SOC_BLE_50_SUPPORTED=y",
"CONFIG_BLUEDROID_ENABLED=y"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
author: chegewara
*/

#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#ifndef CONFIG_BLUEDROID_ENABLED
#error "NimBLE does not support periodic advertising yet. Try using Bluedroid."
#elif !defined(CONFIG_BT_BLE_50_FEATURES_SUPPORTED)
#error "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#else
#include <BLEDevice.h>
Expand Down
3 changes: 2 additions & 1 deletion libraries/BLE/examples/BLE5_periodic_advertising/ci.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"fqbn_append": "PartitionScheme=huge_app",
"requires": [
"CONFIG_SOC_BLE_50_SUPPORTED=y"
"CONFIG_SOC_BLE_50_SUPPORTED=y",
"CONFIG_BLUEDROID_ENABLED=y"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
author: chegewara
*/
#ifndef SOC_BLE_50_SUPPORTED
#warning "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#ifndef CONFIG_BLUEDROID_ENABLED
#error "NimBLE does not support periodic sync yet. Try using Bluedroid."
#elif !defined(SOC_BLE_50_SUPPORTED)
#error "This SoC does not support BLE5. Try using ESP32-C3, or ESP32-S3"
#else
#include <BLEDevice.h>
#include <BLEUtils.h>
Expand Down
3 changes: 2 additions & 1 deletion libraries/BLE/examples/BLE5_periodic_sync/ci.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"fqbn_append": "PartitionScheme=huge_app",
"requires": [
"CONFIG_SOC_BLE_50_SUPPORTED=y"
"CONFIG_SOC_BLE_50_SUPPORTED=y",
"CONFIG_BLUEDROID_ENABLED=y"
]
}
42 changes: 25 additions & 17 deletions libraries/BLE/examples/Beacon_Scanner/Beacon_Scanner.ino
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,33 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
if (advertisedDevice.haveManufacturerData() == true) {
String strManufacturerData = advertisedDevice.getManufacturerData();

uint8_t cManufacturerData[100];
memcpy(cManufacturerData, strManufacturerData.c_str(), strManufacturerData.length());
// Buffer to store manufacturer data (BLE max is 255 bytes)
uint8_t cManufacturerData[255];
size_t dataLength = strManufacturerData.length();

if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) {
Serial.println("Found an iBeacon!");
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData);
Serial.printf("iBeacon Frame\n");
Serial.printf(
"ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()),
ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower()
);
} else {
Serial.println("Found another manufacturers beacon!");
Serial.printf("strManufacturerData: %d ", strManufacturerData.length());
for (int i = 0; i < strManufacturerData.length(); i++) {
Serial.printf("[%X]", cManufacturerData[i]);
// Bounds checking to prevent buffer overflow
if (dataLength <= sizeof(cManufacturerData)) {
memcpy(cManufacturerData, strManufacturerData.c_str(), dataLength);

if (dataLength == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) {
Serial.println("Found an iBeacon!");
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData);
Serial.printf("iBeacon Frame\n");
Serial.printf(
"ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()),
ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower()
);
} else {
Serial.println("Found another manufacturers beacon!");
Serial.printf("strManufacturerData: %d ", dataLength);
for (int i = 0; i < dataLength; i++) {
Serial.printf("[%X]", cManufacturerData[i]);
}
Serial.printf("\n");
}
Serial.printf("\n");
} else {
Serial.printf("Manufacturer data too large (%d bytes), skipping\n", dataLength);
}
}

Expand Down
2 changes: 2 additions & 0 deletions libraries/BLE/examples/Client/Client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ static boolean doScan = false;
static BLERemoteCharacteristic *pRemoteCharacteristic;
static BLEAdvertisedDevice *myDevice;

// Callback function to handle notifications
static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Expand Down Expand Up @@ -80,6 +81,7 @@ bool connectToServer() {
}

if (pRemoteCharacteristic->canNotify()) {
// Register/Subscribe for notifications
pRemoteCharacteristic->registerForNotify(notifyCallback);
}

Expand Down
1 change: 1 addition & 0 deletions libraries/BLE/examples/Notify/Notify.ino
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void setup() {
);

// Creates BLE Descriptor 0x2902: Client Characteristic Configuration Descriptor (CCCD)
// Descriptor 2902 is not required when using NimBLE as it is automatically added based on the characteristic properties
pCharacteristic->addDescriptor(new BLE2902());
// Adds also the Characteristic User Description - 0x2901 descriptor
descriptor_2901 = new BLE2901();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
The server will continue advertising for more connections after the first one and will notify
the value of a counter to all connected clients.
The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
Expand All @@ -26,8 +29,8 @@

BLEServer *pServer = NULL;
BLECharacteristic *pCharacteristic = NULL;
int connectedClients = 0;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;

// See the following for generating UUIDs:
Expand All @@ -38,12 +41,17 @@ uint32_t value = 0;

class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
deviceConnected = true;
connectedClients++;
Serial.print("Client connected. Total clients: ");
Serial.println(connectedClients);
// Continue advertising for more connections
BLEDevice::startAdvertising();
};

void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
connectedClients--;
Serial.print("Client disconnected. Total clients: ");
Serial.println(connectedClients);
}
};

Expand All @@ -66,8 +74,7 @@ void setup() {
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE
);

// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
// Descriptor 2902 is not required when using NimBLE as it is automatically added based on the characteristic properties
pCharacteristic->addDescriptor(new BLE2902());

// Start the service
Expand All @@ -79,27 +86,38 @@ void setup() {
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
Serial.println("Waiting for client connections to notify...");
}

void loop() {
// notify changed value
if (deviceConnected) {
// Notify changed value to all connected clients
if (connectedClients > 0) {
Serial.print("Notifying value: ");
Serial.print(value);
Serial.print(" to ");
Serial.print(connectedClients);
Serial.println(" client(s)");
pCharacteristic->setValue((uint8_t *)&value, 4);
pCharacteristic->notify();
value++;
delay(10); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
// Bluetooth stack will go into congestion, if too many packets are sent.
// In 6 hours of testing, I was able to go as low as 3ms.
// When using core debug level "debug" or "verbose", the delay can be increased in
// order to reduce the number of debug messages in the serial monitor.
delay(100);
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {

// Disconnecting - restart advertising when no clients are connected
if (connectedClients == 0 && deviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
Serial.println("No clients connected, restarting advertising");
deviceConnected = false;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;

// Connecting - update state when first client connects
if (connectedClients > 0 && !deviceConnected) {
// do stuff here on first connecting
deviceConnected = true;
}
}
13 changes: 9 additions & 4 deletions libraries/BLE/examples/UART/UART.ino
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ uint8_t txValue = 0;
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
deviceConnected = true;
Serial.println("Device connected");
};

void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
Serial.println("Device disconnected");
}
};

Expand Down Expand Up @@ -80,6 +82,7 @@ void setup() {
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);

// Descriptor 2902 is not required when using NimBLE as it is automatically added based on the characteristic properties
pTxCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
Expand All @@ -97,22 +100,24 @@ void setup() {
void loop() {

if (deviceConnected) {
Serial.print("Notifying Value: ");
Serial.println(txValue);
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
delay(1000); // Notifying every 1 second
}

// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
Serial.println("Started advertising again...");
oldDeviceConnected = false;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
oldDeviceConnected = true;
}
}
2 changes: 1 addition & 1 deletion libraries/BLE/library.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name=BLE
version=3.2.0
author=Neil Kolban <[email protected]>
maintainer=Dariusz Krempa <[email protected]>
maintainer=lucasssvaz
sentence=BLE functions for ESP32
paragraph=This library provides an implementation Bluetooth Low Energy support for the ESP32 using the Arduino platform.
category=Communication
Expand Down
Loading
Loading