如何自定义低功耗蓝牙服务
本文档介绍了如何利用 ESP-AT 提供的低功耗蓝牙服务源文件在 ESP32-C2 设备上自定义低功耗蓝牙服务。
低功耗蓝牙服务被定义为 GATT 结构的多元数组,该数组至少包含一个属性类型 (attribute type) 为 0x2800 的首要服务 (primary service)。每个服务总是由一个服务定义和几个特征组成。每个特征总是由一个值和可选的描述符组成。更多相关信息请参阅 《蓝牙核心规范》 中的 Generic Attribute Profile (GATT) 一节。
所有支持低功耗蓝牙的芯片共用同一份 gatts_data.csv 格式。下文说明在 ESP32-C2 上各字段是否生效。
低功耗蓝牙服务源文件介绍
低功耗蓝牙服务源文件是 ESP-AT 工程创建低功耗蓝牙服务所依据的文件,文件位于 customized_partitions/raw_data/ble_data/gatts_data.csv,内容如下表所示。
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 |
… |
… |
… |
… |
… |
… |
… |
以下内容是对上表的说明。
perm字段描述属性权限。当某行的perm生效时(见下文规则),它在 ESP-AT 工程中的定义如下所示:/* 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 */
上表第一行是服务定义。该行的属性类型为
0x2800(首要服务),其valueA002表示 16 位服务 UUID0xA002。第二行是特征声明。UUID
0x2803表示该行是特征声明。value:表示下一行特征值属性的特征属性 (characteristic properties)。该字段为 1 字节(8 位),每一位表示是否支持对应属性,1表示支持,0表示不支持。
在 ESP32-C2 上,ESP-AT 会在内部自动转换该属性值,无需处理其中的差异。
例如,
value为02表示下一行特征具备 READ 属性。位
特征属性
0
BROADCAST
1
READ
2
WRITE WITHOUT RESPONSE
3
WRITE
4
NOTIFY
5
INDICATE
6
AUTHENTICATION SIGNED WRITES
7
EXTENDED PROPERTIES
第三行定义该特征的特征值属性。该行的
uuid是特征 UUID,value是特征的初始值。第四行定义了特征的描述符(可选)。
value字段可以缺省。若缺省(留空),ESP-AT 在初始化时会将该属性自动填充为全0。例如,默认表中特征0xC301一行的value为空,则该特征会初始化为全0。
字段规则
对于
0x2803行,只看value(下一行特征的属性)。本行的perm会被忽略、不生效。对于特征值行,本行的
perm会被忽略、不生效。若未提供下文所述的第 8 个可选字段,特征能力只来自上一行0x2803的value(特征属性)。若特征属性包含 NOTIFY 或 INDICATE,会自动添加 CCCD(
0x2902)。gatts_data.csv中的0x2902行会被跳过、不处理(为兼容 CSV 仍可保留这些行;在 ESP32-C2 上它们只是不生效)。其他描述符(如
0x2901)仍会被添加。若未提供下文所述的第 8 个可选字段,这些描述符行以本行的perm为准。
可选第 8 字段
在 ESP32-C2 上,特征值行和描述符行还可以在 value 之后追加一个可选字段。前缀 0x / 0X 可写可不写。服务定义行(0x2800)、特征声明行(0x2803)等其他行即使填写该字段,也不会生效。
特征值行:第 8 字段为 32 位十六进制串,表示该特征的完整属性标志。若填写了该字段,则上一行
0x2803的value(特征属性)会被忽略、不生效,以本字段为准。例如,原来的:
2,16,0xC300,0x01,1,1,30
也可以写成:
2,16,0xC300,0x01,1,1,30,0x00020000
或:
2,16,0xC300,0x01,1,1,30,00020000
该字段定义如下(可按位或组合):
#define BLE_GATT_CHR_F_BROADCAST 0x00000001 #define BLE_GATT_CHR_F_READ 0x00000002 #define BLE_GATT_CHR_F_WRITE_NO_RSP 0x00000004 #define BLE_GATT_CHR_F_WRITE 0x00000008 #define BLE_GATT_CHR_F_NOTIFY 0x00000010 #define BLE_GATT_CHR_F_INDICATE 0x00000020 #define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x00000040 #define BLE_GATT_CHR_F_RELIABLE_WRITE 0x00000080 #define BLE_GATT_CHR_F_AUX_WRITE 0x00000100 #define BLE_GATT_CHR_F_READ_ENC 0x00000200 #define BLE_GATT_CHR_F_READ_AUTHEN 0x00000400 #define BLE_GATT_CHR_F_READ_AUTHOR 0x00000800 #define BLE_GATT_CHR_F_WRITE_ENC 0x00001000 #define BLE_GATT_CHR_F_WRITE_AUTHEN 0x00002000 #define BLE_GATT_CHR_F_WRITE_AUTHOR 0x00004000 #define BLE_GATT_CHR_F_NOTIFY_INDICATE_ENC 0x00008000 #define BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHEN 0x00010000 #define BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHOR 0x00020000
描述符行:第 8 字段为 8 位十六进制串,表示该描述符的权限。若填写了该字段,则本行的
perm会被忽略、不生效,以本字段为准。例如,原来的:
3,16,0x2901,0x11,1,1,30
也可以写成:
3,16,0x2901,0x11,1,1,30,0x80
或:
3,16,0x2901,0x11,1,1,30,80
该字段定义如下(可按位或组合):
#define BLE_ATT_F_READ 0x01 #define BLE_ATT_F_WRITE 0x02 #define BLE_ATT_F_READ_ENC 0x04 #define BLE_ATT_F_READ_AUTHEN 0x08 #define BLE_ATT_F_READ_AUTHOR 0x10 #define BLE_ATT_F_WRITE_ENC 0x20 #define BLE_ATT_F_WRITE_AUTHEN 0x40 #define BLE_ATT_F_WRITE_AUTHOR 0x80
有关 UUID 的更多信息请参考 蓝牙技术联盟分配符。
如果直接在 ESP32-C2 设备上使用默认源文件,不做任何修改,并建立低功耗蓝牙连接,那么在客户端查询服务器服务后,会得到如下结果。
编译时自定义低功耗蓝牙服务
请根据以下步骤自定义低功耗蓝牙服务。
修改低功耗蓝牙服务源文件
可定义多个服务,例如,若要定义三个服务(Server_A、Server_B 和 Server_C),则需要将这三个服务按顺序排列。由于定义每个服务的操作大同小异,这里我们以定义一个服务为例,其他服务你可以按照此例进行定义。
添加服务定义。
本例定义了一个值为 0xFF01 的主要服务。
index
uuid_len
uuid
perm
val_max_len
val_cur_len
value
31
16
0x2800
0x01
2
2
FF01
添加特征说明和特征值。
本例定义了一个 UUID 为 0xC300 的可读可写特征,并将其值设置为 0x30。
声明行
perm与特征值行perm会被忽略、不生效。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
添加特征描述符(可选)。
步骤 2 中的特征属性为
0A(表示 READ | WRITE),不需要 CCCD。下方内容是针对支持 NOTIFY 或 INDICATE 的特征的 独立可选示例,与上面的0A示例无关。若需要 NOTIFY,请相应设置0x2803的属性(例如1A表示 READ | WRITE | NOTIFY)。若属性包含 NOTIFY 或 INDICATE,CCCD 会自动添加。无需再添加
0x2902行;若 CSV 中已有该行,会被跳过、不生效。其他非0x2902的描述符仍会添加,且该行的perm生效。完成以上步骤后,自定义的低功耗蓝牙服务可如下定义(
0A的 READ | WRITE 示例;无需0x2902行):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
请根据自己的需求修改 GATTS 配置,然后生成 mfg_nvs.bin 文件。
生成 mfg_nvs.bin 文件
请参考 生成 mfg_nvs.bin 文档生成带有低功耗蓝牙的服务配置的 mfg_nvs.bin。
下载 mfg_nvs.bin 文件
请参考 下载 mfg_nvs.bin 文档。
下载完成后,重新建立低功耗蓝牙连接,在客户端查询的服务器服务如下所示。