Bluetooth LE Reference
Free reference guide: Bluetooth LE Reference
About Bluetooth LE Reference
The Bluetooth LE Reference is a searchable quick reference for Bluetooth Low Energy protocol development, covering the two core layers that every BLE developer works with daily. The GAP (Generic Access Profile) section covers device roles — Broadcaster, Observer, Peripheral, and Central — along with advertising packet construction, scanning callbacks, connection establishment via bt_conn_le_create(), and fine-tuning connection parameters such as interval, latency, and supervision timeout. Code examples are given in C using the Zephyr RTOS BLE API, which is the most widely deployed open-source BLE stack for embedded targets.
The GATT (Generic Attribute Profile) section details the full attribute hierarchy: Profile, Service, Characteristic, and Descriptor. It covers static service definition with BT_GATT_SERVICE_DEFINE(), reading and writing characteristic values, sending server-initiated notifications and indications, and using CCCD (Client Characteristic Configuration Descriptor) to let the client toggle notifications. Both standard SIG-defined 16-bit service UUIDs (Heart Rate 0x180D, Battery 0x180F, Device Information 0x180A) and custom 128-bit UUIDs are included.
The Advertising section explains fast vs. slow advertising intervals, scan response data, manufacturer-specific data, and beacon formats including iBeacon and Eddystone. The Security section covers the complete BLE security model: pairing with passkey authentication, persistent bonding via CONFIG_BT_SETTINGS, LE Secure Connections using ECDH P-256 key exchange (BLE 4.2+), and all four security levels from no encryption up to authenticated LE SC. This reference is aimed at embedded firmware engineers, IoT developers, and anyone studying for Bluetooth SIG certification exams.
Key Features
- GAP device roles: Broadcaster, Observer, Peripheral, Central with role-specific API calls
- Advertising packet construction using BT_DATA_BYTES, BT_DATA_FLAGS, and bt_le_adv_start()
- GATT service definition with BT_GATT_SERVICE_DEFINE() including characteristics and CCCD
- Standard SIG 16-bit UUIDs (Heart Rate, Battery, Device Information) and custom 128-bit UUIDs
- Characteristic property flags: BT_GATT_CHRC_READ, WRITE, NOTIFY, INDICATE
- BLE security levels 1–4, pairing callbacks, and persistent bonding with flash storage
- LE Secure Connections using ECDH P-256 via CONFIG_BT_SMP_SC_ONLY
- iBeacon and Eddystone beacon advertising data format with field offsets
Frequently Asked Questions
What is the difference between GAP and GATT in BLE?
GAP (Generic Access Profile) governs device discovery and connection establishment — it defines roles like Peripheral and Central, controls advertising and scanning, and manages connection parameters. GATT (Generic Attribute Profile) is the data layer that runs on top of an established connection; it defines how services, characteristics, and descriptors are structured and how clients read, write, or subscribe to data on the server.
What is the difference between BLE Notify and Indicate?
Both allow the GATT server to push data to the client without the client polling. The difference is acknowledgment: Notify (BT_GATT_CHRC_NOTIFY) sends data and does not wait for confirmation, while Indicate (BT_GATT_CHRC_INDICATE) requires the client to send a confirmation before the server can send the next indication. Use Indicate when delivery must be guaranteed; use Notify for high-frequency streaming where dropped frames are acceptable.
How do I enable notifications from the client side?
The client must write the value 0x0001 (BT_GATT_CCC_NOTIFY) to the CCCD descriptor of the characteristic. On the server side, you register a ccc_cfg_changed callback in BT_GATT_CCC() that fires when the client enables or disables notifications. Only then will bt_gatt_notify() actually transmit data to that client.
What is the difference between BLE pairing and bonding?
Pairing is the one-time process of exchanging cryptographic keys to establish a secure, encrypted link. Bonding extends pairing by persisting those keys to non-volatile storage so that future reconnections can skip the full pairing handshake and immediately re-establish encryption. In Zephyr, bonding requires CONFIG_BT_SETTINGS=y and CONFIG_FLASH=y, and keys are restored automatically via settings_load().
What are the BLE connection parameter constraints?
The connection interval must be between 7.5 ms and 4 seconds in multiples of 1.25 ms. The latency (peripheral latency) specifies how many connection events the peripheral may skip while staying connected, reducing power consumption at the cost of latency. The supervision timeout must be greater than (1 + latency) * interval * 2. These three values form the bt_le_conn_param struct.
What is LE Secure Connections and when should I use it?
LE Secure Connections (LESC), introduced in BLE 4.2, uses ECDH P-256 key exchange instead of the older TK-based pairing, making it resistant to passive eavesdropping and man-in-the-middle attacks even when a numeric comparison or passkey is used. Enable it with CONFIG_BT_SMP_SC_ONLY=y in Zephyr. It is required for applications that must meet FIPS or NIST compliance, and strongly recommended for healthcare and industrial IoT.
How do fast and slow advertising intervals differ?
Fast advertising (20–100 ms, BT_GAP_ADV_FAST_INT_MIN_2 / _MAX_2) maximizes the chance of a central discovering and connecting quickly, at the cost of higher power consumption. Slow advertising (1–10.24 s) is used after an initial fast window expires, or for beacon use cases where connection is not expected. The tradeoff is discovery latency vs. battery life; most connectable peripherals advertise fast for ~30 seconds and then switch to slow.
What is the maximum payload in a BLE advertising packet?
In BLE 4.x, a standard advertising packet (PDU) carries up to 31 bytes of AD structures. An additional 31 bytes can be sent in the scan response (returned when an active scanner sends a SCAN_REQ). BLE 5.0 introduced Extended Advertising, which can carry up to 255 bytes in a single ADV_EXT_IND PDU and up to 1650 bytes across chained packets using the AUX chain mechanism.