Creating a GATT Server With ESP-IDF’s Latest Bluetooth LE Stack: NimBLE

Creating a GATT Server With ESP-IDF’s Latest Bluetooth LE Stack: NimBLE

At the end of 2019, the ESP32 became Bluetooth LE 5.0-certified. This certification demonstrates Espressif’s commitment to staying compatible with the latest devices on the market. Luckily for us, this makes it easy for new and existing products to use the 5.0 standard.

Another way Espressif is improving their Bluetooth capabilities is by porting a new BLE-only stack called NimBLE into their ESP-IDF. ESP-IDF is Espressif’s software development kit (SDK) for the ESP32. Previously, the only option for Bluetooth on the ESP was BlueDroid, which implemented classic Bluetooth and Bluetooth LE. BlueDroid is large in terms of both code size and runtime memory—even if the application only uses Bluetooth LE. I recently implemented a GATT server using NimBLE on the ESP32 and in this blog, I’ll share some of the things I learned.

NimBLE Functionalities 

NimBLE is the BLE stack used for Mynewt OS, a cross-platform OS targeted at IoT devices. Mynewt contains a variety of lower-level functions and structures that are used across their higher-level communication protocol stacks (NimBLE included). Espressif therefore had to port over some of these lower-level functions and structures along with the NimBLE stack, such as the ble_hs_mbuf_to_flat() function.

Data in NimBLE is passed around via memory buffers named mbufs. Mbufs are a linked list containing data needed for any type of packet in Mynewt OS. Data coming to my application from the NimBLE stack would be in an mbuf, and the data I want to send to the NimBLE stack needed to be in an mbuf. There are a few functions ported into ESP-IDF to encode or decode mbufs to a Uint8Array, but the ones I primarily used were:



I used these when I needed to create an mbuf to be passed into NimBLE, or when I needed to access the raw data from an mbuf passed to my application from NimBLE.


With NimBLE, creating custom services and characteristics is surprisingly easy. For background, all BLE services and characteristics have universally unique identifiers (UUIDs). Some generic UUIDs are reserved by the Bluetooth SIG and should only be used by specific metrics. For example, the device name should always be at UUID 00002A00-0000-1000-8000-00805F9B34FB. Some applications require data to be sent that does not fall into any of these generic UUIDs, and therefore require a custom service or characteristic. Doing so is as easy as passing a ble_gatt_svc_def structure to the NimBLE stack. Part of the ble_gatt_svc_def structure requires a user callback. This user callback will be called to handle BLE events like writes or reads of any characteristic. I found this easy to set up and clean if you need to expand and customize BLE services or characteristics.

You can check out some examples of the NimBLE port inside ESP-IDF. There are examples showing GATT servers/clients, and one for creating a BLE mesh. I hope this can help in creating your next BLE project with the ESP32!

Read more about DMC’s embedded development and programming expertise and contact us to get started on your next project. 


There are currently no comments, be the first to post one.

Post a comment

Name (required)

Email (required)

Enter the code shown above:

Related Blog Posts