/blog/bluetooth_low_energy_esp32
2026-07-03 · 36 min · Embedded · Tutorial · Security · TAGS · ESP32 · BLE · Bluetooth · IoT · Embedded · Security

Bluetooth Low Energy on ESP32: operation, GATT, security, privacy, and real-world parameters

Bluetooth Low Energy, or simply BLE, is a wireless technology designed to exchange data with low power consumption. It works in the 2.4 GHz band and is widely used in sensors, IoT devices, beacons, wearables, smart locks, remote controls, medical systems, app-configurable devices, and Wi-Fi provisioning procedures.

On ESP32, BLE is especially useful because it allows an embedded device to communicate with smartphones, gateways, or other microcontrollers without keeping the radio constantly active like in a continuous connection. The point is not just "having Bluetooth", but being able to design short, intermittent communications that are efficient enough to work well even on battery-powered devices.

The classic ESP32 supports Bluetooth dual-mode 4.2, so both Bluetooth Classic and Bluetooth Low Energy. However, one important detail should be made clear right away: even if some documentation refers to Bluetooth LE 5.0 certification, the classic ESP32 does not support newer BLE 5 features such as 2M PHY, LE Long Range, and advertising extensions. For those features, newer Espressif chips are required, such as ESP32-S3, ESP32-C3, ESP32-C6, or other compatible models.

This article explains how BLE works on ESP32 from a practical point of view: stack architecture, roles, advertising, scanning, connection, GATT, ATT, MTU, Data Length Extension, notifications, indications, pairing, bonding, encryption, privacy, BLE addresses, configuration parameters, and security choices.

1. BLE is not Bluetooth Classic

Bluetooth Classic and Bluetooth Low Energy share the Bluetooth name, but they should not be treated as the same technology.

Bluetooth Classic was designed for more continuous connections: audio, headphones, speakers, keyboards, mice, classic serial profiles, and persistent streams. It is suited for communications that remain active over time, but it usually consumes more power.

BLE, instead, was designed for short communications. A device can sleep, wake up, transmit a few packets, receive a response, and go back to sleep. This behavior is what makes BLE suitable for sensors and battery-powered devices.

On ESP32, the stack choice depends on the project.

RequirementTypical choice
BLE onlyNimBLE
BLE + Bluetooth ClassicBluedroid
Lightweight firmwareNimBLE
Compatibility with older ESP-IDF examplesBluedroid
BLE gateway, sensors, provisioning, mobile appusually NimBLE
Classic profiles such as SPP or A2DPBluedroid

In ESP-IDF, Bluedroid is the historical Bluetooth stack. NimBLE is lighter and is often preferable for BLE-only projects. ESP-IDF exposes separate configuration options for NimBLE roles and profiles, including GATT Client, GATT Server, and SMP security.

2. BLE stack architecture on ESP32

BLE is not a wireless serial port. It is a multilayer stack.

A simple view is this:

LayerWhat it does
Applicationapplication code: sensors, commands, status, product logic
HostGAP, GATT, ATT, SMP, L2CAP
ControllerLink Layer, PHY, radio, channels, packets

The application decides what should happen: read a sensor, turn on an LED, send a notification, receive a configuration. The host organizes communication using standard protocols. The controller manages the radio, channels, synchronization, and physical packets.

The main protocols are:

ProtocolNameRole
GAPGeneric Access Profileadvertising, scanning, connection, roles, privacy
ATTAttribute Protocolaccess to attributes
GATTGeneric Attribute Profileservices, characteristics, descriptors
SMPSecurity Manager Protocolpairing, bonding, keys, encryption
L2CAPLogical Link Control and Adaptation Protocolmultiplexing and logical transport
HCIHost Controller Interfaceinterface between host and controller

ATT is the protocol that allows a client to read, write, notify, or indicate attributes exposed by a server. GATT builds a more readable structure on top of ATT: services, characteristics, and descriptors.

The BLE stack on ESP32 is split between application logic, host protocols, controller behavior, and radio activity.

3. BLE roles: GAP and GATT are two different things

One of the most common mistakes is confusing GAP roles with GATT roles.

GAP roles

GAP is about discovery, advertising, scanning, and connection.

GAP roleMeaning
Advertisertransmits advertising packets
Scannerlistens for advertising packets
Initiatorstarts a connection
Peripheralconnected device that usually exposes data
Centraldevice that starts and manages the connection
Broadcastertransmits data without a connection
Observerlistens to broadcast data without connecting

Typical example: an ESP32 sensor is a peripheral, while the smartphone is a central.

GATT roles

GATT is about the data model.

GATT roleMeaning
GATT Servercontains services, characteristics, and values
GATT Clientdiscovers, reads, writes, and subscribes to server data

In most projects, an ESP32 is a GAP peripheral and a GATT server. The smartphone is a GAP central and a GATT client.

But this is not mandatory. An ESP32 can also work as a central and client, for example when it needs to read external BLE sensors. In some cases, GATT server and GATT client can also coexist.

4. Advertising: how an ESP32 makes itself discoverable

Advertising is the mechanism a BLE device uses to announce its presence.

An ESP32 can transmit advertising packets to say:

  • I am available;
  • I expose this service;
  • this is my name;
  • these are some minimal data;
  • I can accept a connection.

Advertising can serve two purposes:

  • making the device discoverable by a central that will later connect;
  • transmitting small amounts of data without a connection, as a beacon does.

In legacy advertising, space is very limited. Advertising data and scan response can contain up to 31 bytes each. This means you need to choose carefully what goes into the payload.

Advertising channels

BLE uses three main channels for advertising: 37, 38, and 39.

They are distributed across the 2.4 GHz band to reduce the probability that all of them are disturbed by Wi-Fi at the same time.

Advertising interval

The advertising interval defines how often the device sends an advertising event.

IntervalEffect
20-100 msvery fast discovery, high consumption
100-500 msgood compromise
500 ms - 2 ssuitable for many IoT devices
2-10 slow consumption, slow discovery

In ESP-IDF, adv_int_min and adv_int_max are expressed in units of 0.625 ms. So a value of 160 corresponds to 100 ms.

Advertising types

TypeMeaning
Connectablethe device accepts connections
Non-connectabletransmits data but does not accept connections
Scannablecan respond to scan requests
Non-scannabledoes not send scan responses
Directedadvertising addressed to a specific peer
Undirectedgeneric advertising

For an app-controlled sensor, connectable undirected advertising is often used. For a beacon, non-connectable advertising is used instead.

Advertising and privacy

Advertising is visible to anyone nearby. It must be treated as public.

Never put these in advertising data or scan response:

  • passwords;
  • tokens;
  • medical data;
  • unnecessary permanent serial numbers;
  • the user's full name;
  • easily traceable identifiers;
  • sensitive device state;
  • cloud information or credentials.

Using private addresses is useful, but it is not enough if the advertising payload always contains the same identifier. A device using RPA but transmitting fixed manufacturer data can still be tracked.

5. Scanning: how ESP32 finds nearby BLE devices

Scanning is the procedure a device uses to listen for advertising packets transmitted by other devices.

The main parameters are:

ParameterMeaning
Scan intervalhow often scanning starts
Scan windowhow long the device stays listening
Scan typepassive or active
Filter policyaccept all devices or only filtered devices

If scan window is equal to scan interval, the scanner listens almost continuously. It is fast, but it consumes a lot. If the window is small compared to the interval, consumption goes down, but the time required to discover devices increases.

In ESP-IDF, functions such as esp_ble_gap_set_scan_params() and esp_ble_gap_start_scanning() are used. A duration of 0 means continuous scanning until it is explicitly stopped.

Passive scanning

In passive scanning, ESP32 only listens. It receives advertising packets but does not request additional data.

Advantages:

  • lower consumption;
  • less radio traffic;
  • more discreet behavior.

Limitation:

  • it only sees what is contained in the advertising packet.

Active scanning

In active scanning, ESP32 sends a scan request to a scannable advertiser. The device can then respond with a scan response.

Advantages:

  • allows reading additional data;
  • useful for complete names, extra UUIDs, or larger manufacturer data.

Disadvantages:

  • consumes more;
  • creates more radio traffic;
  • reveals the presence of the scanner.

6. BLE connection: connection event, interval, latency, and timeout

When a central connects to a peripheral, communication does not become continuous. The two devices synchronize and communicate during periodic windows called connection events.

Connection interval

The connection interval is the time between two connection events.

The lower it is, the more responsive the communication becomes. But consumption increases.

Use caseIndicative connection interval
remote control or fast input7.5-30 ms
sensor with frequent updates30-100 ms
app-based configuration30-200 ms
low-power sensor250 ms - 1 s or more

Peripheral latency

Peripheral latency allows the peripheral to skip some connection events when it has no data to send.

Example:

  • connection interval: 30 ms;
  • latency: 9.

The peripheral can skip up to 9 events. In practice, it can wake up roughly every 300 ms if it has no data, saving energy without losing the connection.

Supervision timeout

The supervision timeout is the maximum time without valid communication before the connection is considered lost.

In ESP-IDF, it is expressed in units of 10 ms. It must be coherent with connection interval and latency.

Practical rule: do not set it too low, or you may get random disconnections. Do not set it too high either, or the system will take too long to detect that the peer has disappeared.

7. GATT: services, characteristics, descriptors, and attributes

GATT is the BLE data model.

You do not send random bytes. A device exposes an attribute table organized into services, characteristics, and descriptors.

Attribute

An attribute is the basic unit of ATT/GATT.

It has these elements:

FieldMeaning
Handlenumeric identifier of the attribute
UUIDtype of the attribute
Permissionsaccess rules
Valuecontained value
Lengthvalue size

The handle allows the client to refer precisely to that attribute.

Service

A service represents a logical function.

Examples:

ServiceUse
Battery Servicebattery level
Heart Rate Serviceheart rate
Device Information Servicedevice information
Environmental Sensingtemperature, humidity, pressure
Custom serviceproprietary functions

A service can be primary or secondary. Primary services are the main ones discovered by the client. Secondary services are auxiliary and are used by other services.

Characteristic

A characteristic represents a value or a command.

Examples:

CharacteristicTypical direction
TemperatureESP32 -> smartphone
LED statusESP32 -> smartphone
LED commandsmartphone -> ESP32
Wi-Fi configurationsmartphone -> ESP32
Battery levelESP32 -> smartphone
Sensor data streamESP32 -> gateway

A characteristic is not just a value. In GATT, it is made of multiple attributes:

  • Characteristic Declaration, with properties and the value handle.
  • Characteristic Value, with UUID and actual value.
  • optional descriptors, such as the CCCD.

Descriptor

A descriptor adds metadata to a characteristic.

DescriptorUUIDUse
CCCD0x2902enables notify/indicate
Characteristic User Description0x2901human-readable description
Presentation Format0x2904format and unit
Client Supported Featuresvariablefeatures supported by the client

The most important descriptor is the CCCD, Client Characteristic Configuration Descriptor.

When a characteristic supports notifications or indications, the client must write to the CCCD to enable or disable them. Without a correctly configured CCCD, notify and indicate often do not work as expected.

8. Properties and permissions: an important distinction

In GATT there are two different concepts: properties and permissions.

Characteristic properties

Properties say what a characteristic can do.

PropertyMeaning
Readcan be read
Writecan be written
Write Without Responsecan receive writes without response
Notifycan send notifications
Indicatecan send indications
Broadcastcan be used in GATT broadcast
Extended Propertiesuses extended properties

Properties are visible to the client during discovery. They say: this characteristic supports these operations.

Attribute permissions

Permissions say who can access the attribute and with what security level.

PermissionMeaning
Readreadable without encryption
Writewritable without encryption
Read Encryptedreadable only with encrypted link
Write Encryptedwritable only with encrypted link
Read MITMreadable only with MITM protection
Write MITMwritable only with MITM protection
Signed Writesigned write

In Bluedroid, ESP-IDF uses flags such as:

  • ESP_GATT_PERM_READ;
  • ESP_GATT_PERM_READ_ENCRYPTED;
  • ESP_GATT_PERM_READ_ENC_MITM;
  • ESP_GATT_PERM_WRITE;
  • ESP_GATT_PERM_WRITE_ENCRYPTED;
  • ESP_GATT_PERM_WRITE_ENC_MITM.

This distinction is fundamental.

A characteristic can have the WRITE property but the WRITE_ENC_MITM permission.

This means:

  • the client sees that the characteristic is writable;
  • if it tries to write without an encrypted and authenticated link, the stack rejects it or requires pairing;
  • the write is accepted only after suitable encryption and authentication.

9. GATT operations: read, write, notify, indicate

The main operations are five.

Read

The client reads the value of a characteristic.

Typical use:

  • temperature;
  • battery level;
  • firmware version;
  • current configuration.

Read is simple, but it is not ideal for data that changes often. In that case, the client would need to constantly poll the server.

Write

The client writes a value and the server responds.

Typical use:

  • turning an LED on or off;
  • setting a threshold;
  • sending a configuration;
  • changing device mode.

Write is reliable at GATT level because it expects a response.

Write Without Response

The client writes without waiting for a GATT response.

Typical use:

  • data streams;
  • fast packets;
  • application protocols that handle ACK at a higher level.

It is faster, but buffers, congestion, and packet loss must be handled if the application requires reliability.

Notify

The server sends data to the client without GATT confirmation.

Typical use:

  • sensor updates;
  • logs;
  • data streams;
  • periodic status.

Notifications avoid continuous polling and are widely used when data changes over time.

Indicate

The server sends data to the client and the client must confirm it.

Typical use:

  • important events;
  • alarms;
  • critical state changes;
  • messages that should not be lost.

Indications are safer at GATT level, but slower than notifications.

10. Service discovery and GATT cache

When a client connects to a GATT server, it must discover which services, characteristics, and descriptors exist. This process is called service discovery.

The client retrieves:

  • start and end handles of services;
  • service UUIDs;
  • available characteristics;
  • properties;
  • descriptors;
  • value handles.

Many operating systems, especially smartphones, cache the GATT table. This can create confusion during development.

If you change UUIDs, handles, or server structure, the phone may continue to see the old structure.

Good practices:

  • do not constantly change the GATT layout;
  • keep UUIDs stable;
  • keep handles stable when possible;
  • use Service Changed indication if the database changes;
  • during development, remove bonding and cache from the phone if services look outdated.

ESP-IDF includes APIs to send a service change indication from the GATT server.

11. MTU, useful payload, and fragmentation

The ATT MTU defines the maximum size of a single ATT/GATT operation.

The minimum and often default value is 23 bytes. With MTU 23, the typical useful payload of a notification is around 20 bytes, because 3 bytes are used by the ATT header.

On ESP32, the MTU can be configured up to 517 bytes, but the effective MTU is the one negotiated between the two peers. The smallest value supported by both is always used.

MTU does not automatically mean throughput

Increasing MTU helps, but it is not enough.

Throughput also depends on:

  • connection interval;
  • Data Length Extension;
  • number of packets per connection event;
  • PHY;
  • radio quality;
  • congestion;
  • BLE stack;
  • smartphone or peer used;
  • application logic.

MTU in ESP-IDF

In the Bluedroid client, esp_ble_gattc_send_mtu_req() sends an MTU request and generates ESP_GATTC_CFG_MTU_EVT.

The local MTU can also be set with esp_ble_gatt_set_local_mtu(). If this is not done, the default MTU remains 23 bytes.

Practical values

MTUIndicative useful payloadUse
23~20 bytesmaximum compatibility
100~97 bytesgood compromise
247~244 byteswidely used for throughput
517~514 bytesESP32 maximum, if supported by peer

Not all smartphones accept 517. In practice, values such as 185, 247, or similar are often more realistic.

12. Data Length Extension, PHY, and throughput

Data Length Extension, or DLE, is different from MTU.

MTU belongs to ATT/GATT. DLE belongs to the Link Layer packet size.

ESP32 supports Bluetooth 4.2 DLE and allows setting the maximum LE data packet size with APIs such as esp_ble_gap_set_pkt_data_len().

ConceptLayerWhat it controls
MTUATT/GATTGATT operation size
DLELink Layerradio data packet size
PHYphysicalradio speed/modulation
Connection intervallink schedulingevent frequency
Notification/write modeGATToverhead and confirmations

Realistic throughput

BLE throughput on ESP32 depends on interference, connection interval, MTU, DLE, and peer performance.

In good conditions, between two ESP32 devices, values in the range of hundreds of Kbps can be achieved. Devices with 2M PHY can go further, but the classic ESP32 does not support 2M PHY.

Available PHYs

PHYCharacteristic
LE 1Mmaximum compatibility
LE 2Mhigher speed, if supported
LE Codedlonger range, lower throughput

The classic ESP32 does not support 2M PHY and LE Long Range. ESP32-S3 and other newer chips can support BLE 5 features such as 2 Mbps PHY, Coded PHY, and advertising extension.

Pay attention to Wi-Fi/BLE coexistence: Coded PHY keeps the radio busy for longer and can reduce performance when Wi-Fi and Bluetooth need to share the same band.

13. BLE security: what it actually protects

BLE security is not automatic.

A connection can be:

  • completely open;
  • encrypted but not authenticated;
  • encrypted and authenticated;
  • protected against man-in-the-middle attacks.

The protocol that handles this part is SMP, Security Manager Protocol. SMP manages pairing, bonding, key distribution, encryption, and identity.

Pairing, bonding, encryption

These three terms are often confused.

TermMeaning
Pairinggeneration and authentication of keys
Bondingsaving keys for future connections
Encryptionencrypting the BLE link using valid keys

Pairing can generate keys. Bonding saves those keys. Encryption uses those keys to protect the link.

A protected GATT operation normally forces the connection through pairing, key distribution, and link encryption before access is granted.

Pairing does not always mean strong security

Pairing can be weak or strong. It depends on the method.

MethodMITM protectionNotes
Just Worksnosimple, but does not authenticate the peer
Passkey Entryyes, if implemented correctlyrequires entering a code
Numeric Comparisonyesrequires display and confirmation
OOByes, if the external channel is secureNFC, QR code, or another channel

MITM means Man-In-The-Middle. Without MITM protection, a nearby attacker could intercept the pairing process in some scenarios.

Security Mode 1

BLE Security Mode 1 has four main levels.

LevelMeaning
Level 1no security
Level 2encryption with unauthenticated pairing
Level 3encryption with authenticated pairing
Level 4authenticated LE Secure Connections with encryption

Every connection starts from the lowest level and can be upgraded depending on the pairing method used.

LE Legacy Pairing and LE Secure Connections

BLE initially used LE Legacy Pairing, based on Temporary Key and Short Term Key.

With Bluetooth 4.2, LE Secure Connections was introduced, based on Elliptic-Curve Diffie-Hellman. It is much more robust.

In practice:

MethodSecurity
Legacy Just Worksweak
Legacy Passkeybetter, but not modern
LE Secure Connections Just Worksencrypted but not authenticated
LE Secure Connections + Passkey/Numeric Comparisonmuch better
LE Secure Connections + secure OOBvery strong

On real products, Secure Connections should be used whenever possible, especially to avoid issues related to legacy pairing.

14. Security on ESP32: important APIs and parameters

In ESP-IDF Bluedroid, BLE security is configured mainly through GAP/SMP.

Main APIs

APIUse
esp_ble_gap_set_security_param()sets SMP parameters
esp_ble_set_encryption()requests encryption on the link
esp_ble_gap_security_rsp()accepts or rejects a security request
esp_ble_passkey_reply()replies with passkey
esp_ble_confirm_reply()confirms numeric comparison
esp_ble_remove_bond_device()removes a bonded device
esp_ble_get_bond_device_num()counts bonded devices
esp_ble_gap_get_local_irk()gets local IRK

Important SMP parameters

ParameterMeaning
ESP_BLE_SM_AUTHEN_REQ_MODEauthentication requirements
ESP_BLE_SM_IOCAP_MODEinput/output capabilities
ESP_BLE_SM_SET_INIT_KEYkeys distributed by the initiator
ESP_BLE_SM_SET_RSP_KEYkeys distributed by the responder
ESP_BLE_SM_MAX_KEY_SIZEmaximum key size
ESP_BLE_SM_MIN_KEY_SIZEminimum key size
ESP_BLE_SM_SET_STATIC_PASSKEYstatic passkey
ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTHaccepts only specified requirements
ESP_BLE_SM_OOB_SUPPORTOut-of-Band support

To accept only Secure Connections, use the ESP_LE_AUTH_REQ_SC_ONLY bit in ESP_BLE_SM_AUTHEN_REQ_MODE and enable ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE through ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH.

If bonding and MITM protection are required, ESP_LE_AUTH_BOND and ESP_LE_AUTH_REQ_MITM should also be added.

Security events to handle

In the GAP callback, events such as these must be handled:

EventMeaning
ESP_GAP_BLE_SEC_REQ_EVTthe peer requests security
ESP_GAP_BLE_PASSKEY_NOTIF_EVTshow passkey
ESP_GAP_BLE_NC_REQ_EVTnumeric comparison
ESP_GAP_BLE_KEY_EVTkey exchange
ESP_GAP_BLE_AUTH_CMPL_EVTauthentication completed
ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVTbond removed
ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVTlocal privacy configured

Espressif's gatt_security_server example is a good starting point because it shows passkey, numeric comparison, security request, key exchange, authentication complete, and local privacy.

15. BLE privacy: addresses, tracking, and IRK

BLE privacy is used to reduce the possibility of tracking a device over time through its radio address.

BLE address types

TypeDescription
Public Device Addresspublic address assigned to the device
Random Static Addressrandom but stable address until changed
Resolvable Private Address, RPAaddress that changes and can be resolved by authorized peers
Non-Resolvable Private Address, NRPArandom non-resolvable address

A bonded device can resolve an RPA using the IRK, Identity Resolving Key.

IRK

IRK means Identity Resolving Key.

It is a key distributed during bonding. It is used to recognize a device even if it changes its RPA address.

In practice:

  1. the device periodically changes address;
  2. the bonded peer receives the new address;
  3. it uses the saved IRK to understand that it is the same device;
  4. an unauthorized observer should not be able to make this association.

RPA is not enough if the payload identifies the device

Wrong example:

Address: changes every 15 minutesAdvertising name: "Marco_Glucometer_SN123456"Manufacturer data: fixed ID 0xA1B2C3D4

The address changes, but the device is still recognizable.

Better example:

Address: RPAAdvertising name: generic or absentManufacturer data: no permanent IDConnection: sensitive data only after encryption

BLE privacy must be designed around the whole packet, not only around the address.

16. BLE encryption: what is encrypted and what is not

BLE encryption protects the link after the devices have established valid keys.

Advertising is not a secret channel

In normal cases, advertising and scan response must be considered public.

DataWhere to put it
generic device nameadvertising, if needed
service UUIDadvertising
non-sensitive stateadvertising, if acceptable
Wi-Fi passwordnever in advertising
cloud tokenonly after secure connection
personal dataonly after encryption and access control
critical commandsprotected characteristic

Encryption protects connection data, not normal legacy advertising packets.

Encryption does not replace application checks

Even with an encrypted link, you still need to:

  • check who can write a characteristic;
  • validate lengths and formats;
  • avoid overflows;
  • use timeouts;
  • avoid trusting received values blindly;
  • distinguish pairing mode from operating mode;
  • protect critical commands with application logic.

Encrypted GATT permissions

To protect a characteristic, permissions must be configured.

CharacteristicPropertyPermission
public temperatureRead/NotifyRead
threshold configurationRead/WriteRead Encrypted / Write Encrypted
lock commandWriteWrite Encrypted + MITM
cloud tokenWriteWrite Encrypted + MITM
medical dataRead/NotifyRead Encrypted + MITM

On ESP-IDF Bluedroid, the flags ESP_GATT_PERM_READ_ENCRYPTED, ESP_GATT_PERM_WRITE_ENCRYPTED, ESP_GATT_PERM_READ_ENC_MITM, and ESP_GATT_PERM_WRITE_ENC_MITM are used exactly to define these requirements.

17. Filter Accept List and pairing mode

In a real product, it is not a good idea to remain in pairing mode all the time.

A more robust strategy is:

  1. during normal startup, accept only already bonded devices;
  2. enter pairing mode only through a local action;
  3. keep pairing mode active for a limited time;
  4. save the bond after pairing;
  5. use a Filter Accept List or application logic to limit connections and scan requests;
  6. allow pairing reset only through a controlled procedure.

Why a physical action matters

Without a physical action, anyone near the device could attempt pairing whenever the device is available.

A local button reduces the risk because it requires physical presence.

Example:

  1. press button for 5 seconds;
  2. LED starts blinking;
  3. connectable advertising opens for 60 seconds;
  4. pairing with passkey or numeric comparison;
  5. bond is saved;
  6. pairing mode exits automatically.

18. Designing a secure ESP32 GATT server

A good GATT server does not expose everything without control.

You need to separate:

  • public data;
  • protected data;
  • critical commands;
  • functions available only during provisioning;
  • functions available only with physical confirmation.

Example custom service: Device Control Service.

CharacteristicOperationsSecurity
Device StatusRead/NotifyRead encrypted
Device NameRead/WriteWrite encrypted
LED CommandWriteWrite encrypted
Factory ResetWriteWrite encrypted + MITM + physical confirmation
Firmware VersionReadpublic or encrypted
Diagnostic LogNotifyencrypted
Wi-Fi CredentialsWriteencrypted + MITM, only in provisioning mode

Custom UUIDs are not passwords

A 128-bit UUID is not a secret.

A client can perform service discovery and find services and characteristics. Security should not be designed around the idea that "nobody knows the UUID".

Security must be based on:

  • correct pairing;
  • encryption;
  • MITM when needed;
  • GATT permissions;
  • application checks;
  • limited pairing mode;
  • no secrets in advertising.

Always validate writes

Every write must be checked.

At minimum:

  • length;
  • format;
  • value range;
  • current device state;
  • authorization;
  • rate limit;
  • checksum or framing, if needed;
  • replay protection, if the command is critical.

For example, a characteristic receiving a motor command should not accept any random byte. It must check command, parameters, security state, operating mode, and timeout.

19. Application privacy: beyond the BLE standard

Privacy is not only about the radio address.

It is about everything that can identify a user, a device, or a behavior.

Data to minimize

Avoid exposing:

  • real user name;
  • email;
  • fixed serial number;
  • location;
  • Wi-Fi MAC;
  • SSIDs of known networks;
  • medical data;
  • usage patterns;
  • permanent cloud identifiers.

Temporary identifiers

If you need to transmit an identifier in advertising, consider temporary identifiers:

  • generated by the server;
  • rotated periodically;
  • not directly linked to the user;
  • valid only for a time window;
  • useless without backend or key.

Data exposure phases

A good model can look like this:

PhaseExposed data
Advertisingminimal data only
Unencrypted connectionalmost nothing
After pairing/encryptionconfiguration and status
After application authenticationvery sensitive data
Maintenance modeonly with physical action

20. Power consumption: what really matters

BLE consumes little only if it is configured correctly.

Parameters that increase consumption include:

ParameterEffect
very low advertising intervalradio active more often
continuous scanningvery high consumption
low connection intervalfrequent events
peripheral latency zeroperipheral always present
high TX powerhigher consumption
notifications too frequentmore traffic
heavy logs and callbacksCPU active for longer

Indicative configurations

ScenarioAdvertisingConnection intervalLatencyNotes
fast pairing20-100 ms30-50 ms0only for a short window
battery sensor1-5 s250 ms - 1 shighmaximum saving
beacon500 ms - 5 sno connectionnot usednon-connectable
streaming100-500 ms7.5-30 ms0high throughput
configuration app100-500 ms30-100 ms0-4good compromise

There is no absolute best value. It depends on latency, consumption, user experience, and product type.

21. BLE and Wi-Fi together on ESP32

ESP32 uses the 2.4 GHz band for both Wi-Fi and Bluetooth. The two radios must coexist.

Common problems:

ProblemPossible cause
BLE disconnectionsvery active Wi-Fi, low timeout
unstable BLE throughputradio coexistence
scanning misses devicessmall scan window or intense Wi-Fi
high latencyshared radio scheduling
high consumptionWi-Fi and BLE always active

Good practices:

  • avoid continuous BLE scanning if Wi-Fi is heavily used;
  • use realistic connection intervals;
  • increase supervision timeout in noisy environments;
  • reduce unnecessary logs and traffic;
  • use BLE for provisioning and turn it off when no longer needed;
  • avoid Coded PHY unless long range is really required.

Coded PHY can make coexistence worse because it keeps the radio busy for longer than 1M or 2M PHY.

22. Secure BLE server firmware flow on ESP32

A robust BLE server firmware can follow this flow:

  1. initialize NVS;
  2. initialize the Bluetooth controller;
  3. enable Bluedroid or NimBLE;
  4. configure a non-identifying device name;
  5. configure local privacy, if used;
  6. configure SMP parameters;
  7. create the GATT table;
  8. set correct permissions for each attribute;
  9. configure minimal advertising data;
  10. start advertising;
  11. on connection, update parameters if needed;
  12. request encryption if the service requires it;
  13. handle pairing and bonding;
  14. handle read, write, notify, and indicate;
  15. on disconnection, restart advertising if appropriate;
  16. exit pairing mode after timeout.

Pseudocode:

app_main(){    init_nvs();    init_ble_controller();    init_ble_host(); // NimBLE or Bluedroid    configure_device_name("ESP32-Device");    configure_privacy_if_needed();    configure_smp_security();    create_gatt_database_with_secure_permissions();    configure_advertising_payload_minimal();    start_advertising();    // From here on: GAP/GATT callbacks}

Keep callbacks light

BLE callbacks must be fast.

In practice:

  • do not write to flash inside callbacks unless necessary;
  • do not perform heavy parsing;
  • do not run HTTP or MQTT directly;
  • use queues and separate tasks;
  • copy the data and return quickly.

A BLE callback should not become the place where all application logic lives.

23. ESP32 BLE client flow

An ESP32 can also work as a BLE client or gateway.

Typical flow:

  1. configure scanning;
  2. start scanning;
  3. filter by service UUID, name, or manufacturer data;
  4. stop scanning when the target is found;
  5. open the connection;
  6. perform MTU exchange;
  7. run service discovery;
  8. find characteristic and CCCD;
  9. read values or enable notifications;
  10. handle reconnection and cache.

Filter properly

Do not filter only by name. The name can change, be missing, or be non-unique.

Better options:

  • service UUID;
  • manufacturer data;
  • address only if bonded and privacy is handled;
  • non-sensitive application data;
  • Filter Accept List, when applicable.

24. Common mistakes

Putting secrets in advertising

Advertising is visible. Do not use it for passwords, tokens, credentials, or personal data.

Thinking Just Works protects against MITM

Just Works encrypts the link, but it does not truly authenticate the peer. It is not enough for sensitive commands.

Confusing encryption and authorization

Encryption protects the link. It does not decide by itself whether a command is allowed. That decision must be handled by the stack, GATT permissions, and application logic.

Using custom UUIDs as passwords

UUIDs can be discovered. They are not secrets.

Assuming MTU is always 517

The final MTU is negotiated. Do not assume that the peer accepts 517 bytes.

Forgetting the CCCD

For notify and indicate, the client must enable the characteristic by writing to the CCCD. Without a correctly configured CCCD, notifications may not arrive.

Leaving pairing always open

Pairing mode should be temporary and, ideally, activated through a physical action.

Changing the GATT table without handling cache

Smartphones can keep an old GATT cache. Use Service Changed or clear bond/cache during development.

25. Checklist for an ESP32 BLE project

Architecture

  • I chose NimBLE if I only need BLE.
  • I chose Bluedroid if I also need Bluetooth Classic.
  • I checked the features supported by the specific chip.
  • I am not assuming BLE 5 features on the classic ESP32.

Advertising

  • Advertising data is below 31 bytes if using legacy advertising.
  • No sensitive data is in advertising.
  • The device name is generic.
  • Advertising interval is coherent with power consumption and UX.
  • Pairing advertising is time-limited.

Connection

  • Connection interval is realistic.
  • Peripheral latency is used if the device is battery-powered.
  • Supervision timeout is not too aggressive.
  • Parameters have been tested with real smartphones.

GATT

  • Services and characteristics are organized logically.
  • Custom 128-bit UUIDs are used for proprietary services.
  • Properties and permissions are configured correctly.
  • CCCD is present for notify/indicate.
  • Writes are validated on the application side.
  • Service Changed is handled if the GATT database changes.

Security

  • SMP is configured.
  • LE Secure Connections is used where possible.
  • MITM is required for sensitive commands.
  • Bonding is used for personal devices.
  • Pairing mode can only be activated locally.
  • Bond can be removed through a controlled procedure.
  • Encrypted/MITM GATT permissions are used for sensitive data.

Privacy

  • RPA is used if anti-tracking is needed.
  • IRK is handled through bonding.
  • Advertising does not contain permanent identifiers.
  • Device name is not linked to the user.
  • Sensitive data is sent only after encryption.

Performance

  • MTU is negotiated and checked.
  • DLE is enabled if throughput is needed.
  • Notifications are used for streams.
  • Indications are used only for critical events.
  • Callbacks are light.
  • Wi-Fi coexistence is tested.

26. Essential BLE glossary

  • ACL: Asynchronous Connection-Less link. In the BLE context, it refers to the data link between connected devices.
  • Advertising: periodic transmission of BLE packets to be discovered or to send small data.
  • Advertising Data: payload contained in the advertising packet.
  • Advertising Extension: BLE 5 feature that allows more flexible advertising and larger payloads compared to legacy advertising, if supported by the chip.
  • Advertising Interval: time between two advertising events.
  • ATT: Attribute Protocol. Defines attributes, handles, reads, writes, notifications, and indications.
  • Attribute: basic data unit in ATT/GATT. It has handle, UUID, permissions, and value.
  • Authentication: verification of the identity or legitimacy of the peer during pairing.
  • Authorization: application-level or stack-level decision that determines whether a peer can access a resource.
  • Bonding: saving the keys generated during pairing for future reconnections.
  • Broadcaster: device that sends advertising without accepting connections.
  • CCCD: Client Characteristic Configuration Descriptor. Descriptor UUID 0x2902 used by the client to enable notify or indicate.
  • Central: GAP device that starts and manages the connection. Often a smartphone or gateway.
  • Characteristic: GATT element that represents a value or a command.
  • Characteristic Declaration: attribute that describes the properties and value handle of a characteristic.
  • Characteristic Value: attribute that contains the actual value of the characteristic.
  • Coded PHY: BLE PHY for long range. It uses redundant coding, increases range, but reduces throughput.
  • Connection Event: time window in which central and peripheral exchange packets.
  • Connection Interval: time between two connection events.
  • CSRK: Connection Signature Resolving Key. Key used for data signing in some BLE scenarios.
  • Data Length Extension, DLE: feature that increases payload size at Link Layer level.
  • Descriptor: attribute that adds metadata to a characteristic.
  • Encryption: encryption of the BLE link.
  • Filter Accept List: list of devices accepted for scanning, advertising, or connection.
  • GAP: Generic Access Profile. Manages discovery, advertising, scanning, roles, connection, and privacy.
  • GATT: Generic Attribute Profile. Organizes attributes into services, characteristics, and descriptors.
  • GATT Client: device that discovers, reads, writes, and subscribes to data from a GATT server.
  • GATT Server: device that exposes an attribute table.
  • Handle: numeric identifier of a GATT attribute.
  • HCI: Host Controller Interface. Interface between Bluetooth host and controller.
  • Indication: server-to-client message that requires confirmation.
  • Initiator: GAP device that starts a connection.
  • IRK: Identity Resolving Key. Key used to resolve Resolvable Private Addresses.
  • Just Works: simple pairing method without MITM protection.
  • LE Secure Connections: modern BLE pairing method based on ECDH, introduced with Bluetooth 4.2.
  • L2CAP: adaptation and multiplexing layer between upper protocols and the BLE link.
  • LTK: Long Term Key. Key used to encrypt future reconnections.
  • MITM: Man-In-The-Middle. Attack where a third party sits between two devices.
  • MTU: Maximum Transmission Unit. In ATT/GATT, it indicates the maximum size of a GATT procedure.
  • NimBLE: lightweight BLE stack available in ESP-IDF.
  • Notification: server-to-client message without GATT confirmation.
  • NRPA: Non-Resolvable Private Address. Non-resolvable private address.
  • OOB: Out-of-Band. Pairing through an external channel, such as NFC or QR code.
  • Pairing: process of generating and authenticating security keys.
  • Passkey Entry: pairing method using a numeric code.
  • Peripheral: GAP device that accepts a connection from a central.
  • PHY: physical radio layer: LE 1M, LE 2M, LE Coded.
  • Privacy: mechanisms used to reduce device tracking and identification.
  • Properties: operations supported by a characteristic: read, write, notify, indicate.
  • Permissions: access and security rules for GATT attributes.
  • Resolvable Private Address, RPA: private address that changes and can be resolved by authorized peers through IRK.
  • RSSI: Received Signal Strength Indicator. Indicator of received signal strength.
  • Scan Request: request sent by an active scanner to a scannable advertiser.
  • Scan Response: response containing additional data to advertising.
  • Scanning: listening for advertising packets.
  • Security Manager Protocol, SMP: BLE protocol for pairing, bonding, keys, and encryption.
  • Service: GATT grouping of related characteristics.
  • Service Changed Indication: indication used to inform the client that the GATT table has changed.
  • Supervision Timeout: maximum time without valid communication before the connection is considered lost.
  • UUID: identifier for services, characteristics, and descriptors. It can be a standard 16-bit UUID or a custom 128-bit UUID.
  • Whitelist: older term often used to refer to Filter Accept List.
  • Write Without Response: GATT write without a server response. Useful for throughput, but less controlled.

27. Conclusion

BLE on ESP32 is very useful, but it must be designed carefully.

It is not a wireless serial port and it is not automatically secure. GAP manages advertising, scanning, roles, and connection. ATT and GATT organize data into attributes, services, characteristics, and descriptors. SMP manages pairing, bonding, keys, privacy, and encryption.

In a real project, you need to define precisely:

  • which data is public;
  • which data requires encryption;
  • which commands require MITM;
  • when the device enters pairing mode;
  • which characteristics are readable or writable;
  • how RPA, bonding, and IRK are handled;
  • how MTU, DLE, interval, latency, and timeout are configured;
  • how BLE coexists with Wi-Fi.

The best configuration is not always the fastest one. It is the one that balances consumption, latency, throughput, compatibility, security, and privacy.

On the classic ESP32, the BLE 4.2 hardware limits must be kept in mind. For BLE 5 features such as 2M PHY, Coded PHY, and advertising extensions, a newer Espressif chip is required.

Main sources consulted

Last updated 2026-07-03.
Article source content/blog/bluetooth_low_energy_esp32.

Author

Nicolò is a software architect based in Bergamo. He works on ESP32 firmware, HMI, native Android apps, backends, software libraries and system integrations.

Next entry

2026-06-27
Scope guard in C++

How to use RAII to keep rollback close to the state it protects.