BLE standard defines two ways to transfer data for the server to the client: notification and indication. Notifications and indications are initiated by the Server but enabled by the Client. Notification doesn’t need to be acknowledged, so they are faster and an efficient way to read data continuously. Hence, a server does not know if the message reaches to the client. Indication needs to be acknowledged for communicating. The client sent a confirmation message back to the server, this way server knows that message reached the client. Notification process similar to the reading of data.


The server is not able to send indications or notifications at the beginning of the communication. First, the client must enable notifications and indications permissions on the server side, so, the server is allowed to send indications or notifications. This procedure involves the client to write the Client Characteristic Configuration Descriptor (CCCD) of the characteristic that will be notified/indicated.

Code snippet

The libraries used here are

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

Define service UUID and characteristics UUID.

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

All this does is set the “deviceConnected” flag true or false when you connect or disconnect from the ESP32. The callback function that handles receiving data being sent from the client(phone) and Bluetooth connection status.

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;

Initialize the ESP32 as a BLE device and set its name.


Create BLE server

 BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

Create BLE service using the service UUID.

BLEService *pService = pServer->createService(SERVICE_UUID);

And add characteristics.PROPERTY_READ, PROPERTY_WRITE, PROPERTY_NOTIFY, PROPERTY_INDICATE are the properties of the characteristics.

pCharacteristic = pService->createCharacteristic(
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
  pCharacteristic->addDescriptor(new BLE2902());

Start BLE service. Starting a service also means that we can create the corresponding characteristics. Characteristics have various attributes such as UUID, properties, permissions, and values. Properties describe what can be done with characteristics, such as read, write, notify and indicate. Permission describe what value can be allowed eg: read and write.


Start advertising


The assigned value of descriptor for client characteristics configuration is 0x2902.

The Client Characteristic Configuration descriptor defines how the characteristic may be configured by a specific client. The client characteristics configuration descriptor is unique for each client. A client may read and write this descriptor to determine and set the configuration for that client. Authentication and authorization may be required by the server to write this descriptor. The default value for the Client Characteristic Configuration descriptor is 0x00.
Sent the notification in every second after the device connected.

if (deviceConnected) { 
Serial.printf("*** NOTIFY: %d ***\n", value);
pCharacteristic->setValue(&value, 1); 




Spread the love, share this