How to Customize Bluetooth® LE Services
This document describes how to customize Bluetooth LE services on your ESP32 with the Bluetooth LE service source file provided by ESP-AT.
The Bluetooth LE services are defined as a multivariate array of GATT structures, and the array contains at least one primary service whose attribute type is defined as 0x2800. Each service always consists of a service definition and several characteristics. Each characteristic always consists of a value and optional descriptors. Please refer to Part Generic Attribute Profile (GATT) of Bluetooth Core Specification for more information.
ESP-AT uses the same gatts_data.csv format on all chips that support Bluetooth LE. The rules below describe which fields take effect on ESP32.
Bluetooth LE Service Source File
The ESP-AT project creates Bluetooth LE services based on its Bluetooth LE service source file. It is located in customized_partitions/raw_data/ble_data/gatts_data.csv. The table below shows the default source file.
index |
uuid_len |
uuid |
perm |
val_max_len |
val_cur_len |
value |
|---|---|---|---|---|---|---|
0 |
16 |
0x2800 |
0x01 |
2 |
2 |
A002 |
1 |
16 |
0x2803 |
0x01 |
1 |
1 |
02 |
2 |
16 |
0xC300 |
0x01 |
1 |
1 |
30 |
3 |
16 |
0x2901 |
0x11 |
1 |
1 |
30 |
… |
… |
… |
… |
… |
… |
… |
Below are descriptions of the table above.
permdescribes attribute permissions. When a row’spermtakes effect (see the rules below), its definition in the ESP-AT project is as follows:/* relate to BTA_GATT_PERM_xxx in bta/bta_gatt_api.h */ /** * @brief Attribute permissions */ #define ESP_GATT_PERM_READ (1 << 0) /* bit 0 - 0x0001 */ /* relate to BTA_GATT_PERM_READ in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_READ_ENCRYPTED (1 << 1) /* bit 1 - 0x0002 */ /* relate to BTA_GATT_PERM_READ_ENCRYPTED in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_READ_ENC_MITM (1 << 2) /* bit 2 - 0x0004 */ /* relate to BTA_GATT_PERM_READ_ENC_MITM in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE (1 << 4) /* bit 4 - 0x0010 */ /* relate to BTA_GATT_PERM_WRITE in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_ENCRYPTED (1 << 5) /* bit 5 - 0x0020 */ /* relate to BTA_GATT_PERM_WRITE_ENCRYPTED in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 - 0x0040 */ /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 - 0x0080 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 - 0x0100 */ /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */ #define ESP_GATT_PERM_READ_AUTHORIZATION (1 << 9) /* bit 9 - 0x0200 */ #define ESP_GATT_PERM_WRITE_AUTHORIZATION (1 << 10) /* bit 10 - 0x0400 */
The first line of the table is the service definition. Its attribute type is
0x2800(primary service), and itsvalueA002is the 16-bit service UUID0xA002.The second line is the characteristic declaration. UUID
0x2803identifies this row as a characteristic declaration.value: characteristic properties of the next characteristic value attribute (the following row). It is one byte (8 bits). Each bit indicates whether a property is supported (1) or not (0).
For example,
value02means the following characteristic has the READ property.Bit
Characteristic Property
0
BROADCAST
1
READ
2
WRITE WITHOUT RESPONSE
3
WRITE
4
NOTIFY
5
INDICATE
6
AUTHENTICATION SIGNED WRITES
7
EXTENDED PROPERTIES
The third line defines the characteristic value attribute of that characteristic. The
uuidof this line is the characteristic UUID, andvalueis the characteristic’s initial value.The fourth line defines a descriptor of the characteristic (optional).
The
valuefield is optional. If it is left empty, ESP-AT fills the attribute with all zeros during initialization. For example, in the default table, the characteristic0xC301row leavesvalueempty, so the characteristic is initialized to all zeros.
Field Rules
For the
0x2803row, bothpermandvaluetake effect:permis the permission of the declaration attribute itself (usually0x01, readable), andvalueis the properties of the next characteristic.For the characteristic value row,
permtakes effect. It must not conflict with the properties in the previous0x2803row. Properties advertise which operations the characteristic supports;permcontrols whether the stack actually allows those operations. If properties claim READ-only but the value-rowpermis WRITE-only, clients will fail when they try to read.Typical mapping (encrypted or signed permission variants may be used when security is required):
If properties include
Characteristic value
permshould include at leastREAD
READ (
0x01), or a read-related encrypted/authorized variantWRITE
WRITE (
0x10), or a write-related encrypted/authorized/signed variantWRITE WITHOUT RESPONSE
WRITE (
0x10), or a write-related encrypted/authorized/signed variantNOTIFY or INDICATE
Usually READ on the characteristic value; you must add the CCCD (
0x2902) yourself. Itspermis typically READ | WRITE (0x11).You can combine properties. For example,
0A(READ | WRITE) should be paired with characteristic valueperm0x11(READ | WRITE).If the characteristic supports NOTIFY or INDICATE, add a
0x2902row in the table. Other descriptors (such as0x2901) are also added as defined, and each descriptor row’spermtakes effect.
For more information about UUID, please refer to Bluetooth Special Interest Group (SIG) Assigned Numbers.
If you use the default source file on your ESP32 without any modification and establish a Bluetooth LE connection, you will get the following result after querying the server service on the client side.
Customize Bluetooth LE Services during Compilation
If you want to customize the Bluetooth LE services, follow the steps below.
Modify the Bluetooth LE Service Source File
You can define more than one service. For example, if you want to define three services (Server_A, Server_B and Server_C), these three services need to be arranged in order. Since the definition of each service is similar, here we define one service as an example, and then you can define others one by one accordingly.
Add the service definition.
In this example, we define a primary service with a value of 0xFF01.
index
uuid_len
uuid
perm
val_max_len
val_cur_len
value
31
16
0x2800
0x01
2
2
FF01
Add the characteristic declaration and characteristic value.
In this example, we define a readable and writable characteristic with UUID 0xC300, and set its value to 0x30.
The declaration-row
permis0x01. The characteristic-value-rowpermis0x11(required to match READ | WRITE properties).index
uuid_len
uuid
perm
val_max_len
val_cur_len
value
32
16
0x2803
0x01
1
1
0A
33
16
0xC300
0x11
1
1
30
Add the characteristic descriptor (optional).
The characteristic in step 2 uses properties
0A(READ | WRITE) and does not require a CCCD. The content below is a separate optional illustration for characteristics that support NOTIFY or INDICATE; it is not tied to the0Aexample above. If you need NOTIFY, set the0x2803properties accordingly (for example1Afor READ | WRITE | NOTIFY).If the characteristic supports NOTIFY or INDICATE, add client characteristic configuration (
0x2902) yourself. The example below setsvalueto0000(notifications and indications disabled).Example of a CCCD row:
index
uuid_len
uuid
perm
val_max_len
val_cur_len
value
34
16
0x2902
0x11
2
2
0000
After the above steps, the customized Bluetooth LE service can be defined as follows. The table combines the service and characteristic from steps 1–2 with the optional CCCD illustration from step 3. For the
0A(READ | WRITE) characteristic alone, omit the0x2902row.index
uuid_len
uuid
perm
val_max_len
val_cur_len
value
31
16
0x2800
0x01
2
2
FF01
32
16
0x2803
0x01
1
1
0A
33
16
0xC300
0x11
1
1
30
34
16
0x2902
0x11
2
2
0000
Please modify the GATTS configurations according to your own needs and generate mfg_nvs.bin file.
Generate mfg_nvs.bin
Please refer to Generate mfg_nvs.bin document to generate the mfg_nvs.bin file with the Low Energy Bluetooth services.
Download mfg_nvs.bin
Please refer to Download mfg_nvs.bin document.
After the download is complete, re-establish the Bluetooth LE connection. Query the server service on the client side as follows: