ESP32 BLE Server Tutorial: Custom GATT & Notifications

The ESP32’s built-in BLE capabilities make it ideal for creating low-power IoT devices that communicate with smartphones, sensors, or other peripherals. In this guide, we’ll build a BLE server (GATT server) with custom services, characteristics, and notifications, focusing on real-world use casesZigbee Green Power: Ultra-Low-Power Energy Harvesting SolutionsZigbee Green Power: Ultra-Low-Power Energy Harvesting SolutionsDiscover how ZGP enables battery-free IoT devices through energy harvesting with ESP32 integrations, supporting smart home and industrial applications. like sensor data transmission and remote control.

Table of Contents

Understanding GATT Services and Characteristics🔗

BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. uses the Generic Attribute ProfileNative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. (GATT) to structure data into hierarchical elements:

  • Services: Containers for related functionalities (e.g., a Battery Service or Environmental Sensing Service).
  • Characteristics: Data fields within a service (e.g., Temperature or Humidity).
  • Descriptors: Metadata for characteristics (e.g., units, formats).

UUIDs uniquely identify services and characteristics. For custom profilesEnabling Bluetooth Classic on ESP32: Pairing, Profiles, and Data TransferEnabling Bluetooth Classic on ESP32: Pairing, Profiles, and Data TransferExplore our comprehensive guide to enabling Bluetooth Classic on ESP32, covering pairing, SPP, A2DP, and reliable data transfer techniques., use UUIDs in the format 0000XXXX-0000-1000-8000-00805F9B34FB, replacing XXXX with a 16-bit value.

Example:

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLEService customService(SERVICE_UUID);
BLECharacteristic customChar(CHARACTERISTIC_UUID, BLENotify | BLERead | BLEWrite, 20);
  • Here, customChar supports read/write operations and notifications.

Setting Up the BLE Server🔗

Step 1: Initialize BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects.

#include <BLEDevice.h>
void setup() {
  BLEDevice::init("ESP32_BLE_Server");
  BLEServer *server = BLEDevice::createServer();
  server->setCallbacks(new ServerCallbacks()); // Handle connection events
}

Step 2: Create Services and Characteristics

BLEService *batteryService = server->createService(BLEUUID((uint16_t)0x180F)); // Battery Service
BLECharacteristic *batteryLevelChar = batteryService->createCharacteristic(
  BLEUUID((uint16_t)0x2A19),
  BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
batteryLevelChar->addDescriptor(new BLE2902()); // Enable notifications

Step 3: Start Services

batteryService->start();
BLEAdvertising *advertising = server->getAdvertising();
advertising->start();

Implementing Notifications🔗

Notifications allow the server to push data to clients without polling.

Example: Sending battery level updates every 5 seconds:

void loop() {
  uint8_t batteryLevel = readBatteryLevel(); // Custom function
  batteryLevelChar->setValue(&batteryLevel, 1);
  batteryLevelChar->notify();
  delay(5000);
}

Key Points:

  • Use BLE2902 descriptor to enable notifications.
  • Notifications are unacknowledged; use indications (acknowledged) for critical data.

Security Best Practices🔗

Secure your BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. server to prevent eavesdropping:

1. Enable EncryptionConnecting ESP32 to Cloud Services via Wi-FiConnecting ESP32 to Cloud Services via Wi-FiDiscover how to connect your ESP32 to AWS, Azure, and Google Cloud using secure Wi-Fi. This guide covers setup, error handling, and low power strategies.:

BLESecurity *security = new BLESecurity();
security->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);

2. Require Pairing:

batteryLevelChar->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

Power Consumption Optimization🔗

  • Adjust Connection Intervals:
BLEDevice::setPower(ESP_PWR_LVL_N12); // Lowest transmit power
esp_ble_conn_update_params_t conn_params = {
  .min_interval = 80,  // 100 ms
  .max_interval = 800, // 1 s
  .latency = 0,
  .timeout = 400       // 4 s
};
server->updateConnParams(&conn_params);

Troubleshooting Common Issues🔗

IssueSolution
Client can’t discover servicesVerify UUIDs and service initialization order.
Notifications not workingCheck if BLE2902 descriptor is added.
Intermittent disconnectsIncrease connection timeout or reduce RF interference.

Practical Applications🔗

1. Wireless Sensor Node:

BLECharacteristic tempChar("TEMPERATURE_UUID", BLENotify | BLERead, 4);
float temperature = readSensor();
tempChar.setValue(temperature);
tempChar.notify();

2. Smart Lock Controller:

BLECharacteristic lockCmdChar("LOCK_CMD_UUID", BLEWrite);
lockCmdChar.setWriteCallback([](BLECharacteristic* chr) {
  uint8_t* cmd = chr->getData();
  if (cmd[0] == 0x01) unlockDoor();
});

Understanding BLE Servers🔗

A BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. server, also known as a GATTNative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. server, is a device that hosts data and provides services to BLE clientsSetting Up BLE Client Communication on ESP32Setting Up BLE Client Communication on ESP32Learn how to configure the ESP32 as a BLE client. This guide explains scanning, connecting, and interacting with a variety of IoT devices effortlessly.. In the BLE architecture, the server exposes services and characteristics that clients can read, write, or subscribe to. For example:

  • A heart rate monitor exposes a heart rate service with a characteristic for the current heart rate value.
  • A smart lock exposes a lock service with a characteristic for the lock state.

The server is responsible for:

  • Defining services and characteristics.
  • Handling client requests (e.g., read, write, notify).
  • Sending notifications or indications to subscribed clients.

Defining GATT Services and Characteristics🔗

GATT (Generic Attribute ProfileNative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects.) is the backbone of BLE communication. Here’s how to define custom services and characteristics:

1. UUIDs:

2. Properties:

  • READ: Clients can read the characteristic value.
  • WRITE: Clients can write to the characteristic.
  • NOTIFY: Server can send updates to clients without acknowledgment.
  • INDICATE: Server sends updates, and clients must acknowledge receipt.

3. Descriptors:

  • Descriptors provide additional metadata about characteristics.
  • Example: The BLE2902 descriptor enables notifications/indications.

Practical Example: IoT Sensor Data Transmission🔗

Let’s build a practical example where the ESP32Setting Up ESP32 as a Wi-Fi Access PointSetting Up ESP32 as a Wi-Fi Access PointMaster ESP32 AP configuration with our step-by-step guide. Set up a secure, local IoT network using practical code examples and optimization tips. acts as a BLE server transmitting sensor data (e.g., temperature):

1. Define a Temperature Service:

BLEService *pTempService = server->createService("00001809-0000-1000-8000-00805f9b34fb");
BLECharacteristic *pTempCharacteristic = pTempService->createCharacteristic(
    "00002a1c-0000-1000-8000-00805f9b34fb",
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_NOTIFY
);
pTempCharacteristic->addDescriptor(new BLE2902());

2. Update Sensor DataSigfox Message Encoding: Packing Sensor Data into 12-byte PayloadsSigfox Message Encoding: Packing Sensor Data into 12-byte PayloadsLearn efficient data encoding techniques for Sigfox's constrained 12-byte payloads. Discover bitwise operations, structured encoding & CBOR strategies.:

Simulate temperature readings and notify clients.

float temperature = readTemperatureSensor();
pTempCharacteristic->setValue(temperature);
pTempCharacteristic->notify();

Security Considerations🔗

BLE communicationSetting Up BLE Client Communication on ESP32Setting Up BLE Client Communication on ESP32Learn how to configure the ESP32 as a BLE client. This guide explains scanning, connecting, and interacting with a variety of IoT devices effortlessly. can be vulnerable to eavesdropping and unauthorized access. Secure your BLE server with:

Optimizing Power Consumption🔗

BLE is designed for low powerConnecting ESP32 to Cloud Services via Wi-FiConnecting ESP32 to Cloud Services via Wi-FiDiscover how to connect your ESP32 to AWS, Azure, and Google Cloud using secure Wi-Fi. This guide covers setup, error handling, and low power strategies., but you can further optimize:

Conclusion🔗

Creating a BLE server on the ESP32 opens up a world of possibilities for IoT applicationsConnecting ESP32 to Cloud Services via Wi-FiConnecting ESP32 to Cloud Services via Wi-FiDiscover how to connect your ESP32 to AWS, Azure, and Google Cloud using secure Wi-Fi. This guide covers setup, error handling, and low power strategies.. By defining custom services and characteristics, implementing notifications, and optimizing for power and security, you can build robust, low-power BLE solutions. Whether you're transmitting sensor data or controlling smart home devices, the ESP32’s BLE capabilities make it a versatile choice for your next project.

Enjoy integrating BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLENative Protocols: Wi-Fi (2.4 GHz), Bluetooth Classic, and BLEExplore ESP32 connectivity with Wi-Fi, Bluetooth Classic, and BLE. Learn implementation tips and best practices for IoT projects. into your projects and explore further enhancements such as secure pairing and multi-device mesh configurations in your next steps!

Author: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

References🔗

Share article

Related Articles