Read the section on Bluetooth > Profiles, Bluetooth > Services, Bluetooth > Profiles]. These contain general info about profiles/services/characteristics, although they are defined differently for GATT.
Advertising
In order to find devices, they must scan and detect responses
GAP
Generic Access Profile.
It controls connections and advertising in bluetooth. It does more than just advertising,it also handles bonding, encryption, notification/indications, data flow.
Peripheral - small, low power devices connected to a central devices
Central - devices that you connect to with far more processing power and memory
Process
Sending advertising allows for two payloads: Advertising Data and Scan Response. Both are 31 bytes.
Advertising Data - critical data to let central devices know that it exists
Scan Response - (not required), optional secondary payload that central devices request to find device names, etc
Continuously sends out Advertising Data, and if the central devices is interested, it will ask for the Scan Response. This is known as active scanning (vs passive scanning)
Bluetooth Channels
BLE has Adaptive Frequency. It mainly operates on the 2.4 GHz band, but it’s really crowded. It splits it into 40RF channels, with 2 MHz bandwidth (2402-2480 MHz).
| Type | Quantity | Index | Purpose |
|---|---|---|---|
| Advertising Channel | 3 | 37-39 | Used for sending advertising packets and scan response packets |
| Data Channel | 37 | 0-36 | Used for sending data channel packets |
Theres something about Bluetooth 5 adding in extended advertising.
The advertising interval is 20ms to 10.24s, with a step size of 0.625ms. To avoid packet collision, add a random 0-10ms delay.
Packet Structure
| No. | Name | Byte Size | Function |
|---|---|---|---|
| 1 | Preamble | 1 | A special bit sequence used for device clock synchronization |
| 2 | Access Address | 4 | Marks the address of the advertising packet |
| 3 | Protocol Data Unit, PDU | 2-39 | The area where the actual data is stored |
| 4 | Cyclic Redundancy Check, CRC | 3 | Used for cyclic redundancy checking |
| PDU: |
| No. | Name | Byte Size |
|---|---|---|
| 1 | Header | 2 |
| 2 | Payload | 0-37 |
PDU Header:
| No. | Name | Bit Size | Notes |
|---|---|---|---|
| 1 | PDU Type | 4 | Connectable vs Non-connectable Scannable vs Non-scannable |
| 2 | Reserved for Future Use, RFU | 1 | |
| 3 | Channel Selection Bit, ChSel | 1 | Indicates whether the advertiser supports the _LE Channel Selection Algorithm 2_ |
| 4 | TX Address, TxAdd | 1 | 0/1 indicates Public Address/Random Address |
| 5 | Rx Address, RxAdd | 1 | 0/1 indicates Public Address/Random Address |
| 6 | Payload Length | 8 | |
| PDU Payload: |
| No. | Name | Byte Size | Notes |
|---|---|---|---|
| 1 | Advertisement Address, AdvA | 6 | The 48-bit Bluetooth address of the advertiser (Can be globally unique, fixed that manufacturers pay IEEE for, or a random) |
| 2 | Advertisement Data, AdvData | 0-31 | Consists of multiple Advertisement Data Structures |
| No. | Name | Byte Size | Notes |
|---|---|---|---|
| 1 | AD Length | 1 | |
| 2 | AD Type | n | Most types take 1 byte |
| 3 | AD Data | (AD Length - n) |
Addresses
Addresses can either be public (must pay IEEE to reserve) or random. There are random static (fixed in firmware) and random private (periodically changes). For random private addresses to communicate, an (Identity Resolving Key) should be used to generate, which can be used to resolve and obtain the true address.
Connection
The advertiser becomes the peripheral and the connector becomes the central.
Parameters
Supervision Timeout - maximum time allowed between two successful connection events. (or else disconnect)
Peripheral Latency - number of packets the peripheral can skip when thers no data (for example a mouse clocking down from 100Hz to 1 Hz when not in use)
Maximum Transmission Unit - maximize byte size of a single ATT packet
PDU
| No. | Name | Byte Size | Notes |
|---|---|---|---|
| 1 | Header | 2 | |
| 2 | Payload | 0-27 / 0-251 | Before Bluetooth Core Specification 4.2, the maximum payload was 27 bytes; Bluetooth Core Specification 4.2 introduced Data Length Extension (DLE), allowing a maximum payload of 251 bytes. |
| 3 | Message Integrity Check, MIC | 4 | Optional |
| No. | Name | Byte Size | |
|---|---|---|---|
| 1 | L2CAP Header | 4 | |
| 2 | ATT Header + ATT Data | 0-23 / 0-247 |
ATT
A protocol that defines the unit of data Attribute.
An Attribute has:
- Handle: the index
- Type: UUID (16bit by spec or 128 by manufacturer) assigned-numbers
- Value: data
- Permissions: “R, R/W, ” (usually enforced in server, not transmitted)
It is built into an Attribute table, that uses the handle as an index
GATT
Generic ATTribute, is meant as a way to communicate between two BLE devices.
- Client - the one that sends requests to server
- Server - The one that holds the ATT lookup data and service and characteristic (peripheral)

Each white box is an Atrribute
The include allows em to share data such as manufacturer specific spec.
GATT Characteristic
Read more here about the layout: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/ble/get-started/ble-data-exchange.html
These are all Atrributes
| No. | Type | Function | Notes |
|---|---|---|---|
| 1 | Characteristic Declaration | Contains properties, handle, and UUID info for the characteristic value | UUID is 0x2803, read-only |
| 2 | Characteristic Value | user data | UUID identifies the characteristic type |
| 3 | Characteristic Descriptor | Additional description for the characteristic data | Optional attribute |
The Characteristic Declaration has the metadata such as the handle (the index of the attribute that points to data)
Characteristic Descriptors provide supplementary info about the Declaration. The most common is CCCD, which is usually fo subscribing to unsubscribing (notification / indication) status. UUID is 0x2902, and its attribute value only has 2 bits (notif enable & indication enabled)
GATT Service
Each service is stored into two parts:
| No. | Name |
|---|---|
| 1 | Service Declaration Attribute |
| 2 | Characteristic Definition Attributes (GATT Characteristic) |
| BLE treats the start of a service declaration to the next one as the entire “service”. No pointers are involved |
GATT Server Example
Why not an example to show how this all works?
Once again, a list of Attributes
| Handle | UUID | Permissions | Value | Attribute Type |
|---|---|---|---|---|
| 0 | 0x2800 | Read-only | UUID = 0x180D | Service Declaration |
| 1 | 0x2803 | Read-only | Properties = Read/Indicate Handle = 2 UUID = 0x2A37 | Characteristic Declaration |
| 2 | 0x2A37 | Read/Indicate | Flags Measurement value | Characteristic Value |
| 3 | 0x2902 | Read/Write | Notification status Indication status | Characteristic Descriptor |
| 4 | 0x2800 | Read-only | UUID = 0x1815 | Service Declaration |
| 5 | 0x2803 | Read-only | Properties = Write-only Handle = 6 UUID = 0x00001525-1212-EFDE-1523-785FEABCD123 | Characteristic Declaration |
| 6 | 0x00001525-1212-EFDE- 1523-785FE ABCD123 | Write-only | LED status | Characteristic Value |
| This is showing a Heart Rate Service (0x180D) and an Automation IO Service (0x1815). |
Heart rate service contains one characteristic: the Heart Rate Measurement characteristic (0x2803), which points to the data that stores measurement value. It also has an optional descriptor for people to subscribe to notifications and indications ^08ce4c
Client-initiated
Some operations the BLE Client (usually the phone) can initiate is;
- Read: Read the value of a characteristic
- Write: Write operation that needs confirmation from server upon receiving data
- Write without response: Write operation without confirmation1
Server Initiated
- Notify: Send data without confirmation response from client
- Indicate: Send data, client must ACK
Special GATT Services
0x1800 - GAP. Stored names, connection parameters
0x1801 - Cache invalidator. Notifies when the internal table has been changed