接着上一篇。
通用属性配置文件(Generic Attribute Profile)
1.GATT简介
通用属性配置文件Generic Attribute Profile简称GATT。
GATT定义了属性类型并规定了如何使用,包括了一个数据传输和存储的框架和一些基本操作。中间包含了一些概念如特性characteristics,服务services等,在后面介绍。同时还定义了发现服务,特性和服务间的连接的处理过程,也包括读写特性值。
1.1.GATT的角色
GATT中定义了2种角色:服务器server和客户端client.
GATT的服务器是指提供数据的设备,而GATT的客户端是指通过GATT的服务器获取数据的设备。
1.2.GATT的层次
GATT服务器通过一个属性表来组织发送的数据。这里的关系大概是这样:
一个Profile中可包含一个或者多个服务;一个服务可包含一个或者多个特性(逻辑上的集合);一个特性至少包含两个属性:一个用于声明,其他用于存储属性值。
2.属性(Attribute)
一个属性包括句柄,UUID,值。
句柄是属性在GATT表中的索引,在一个设备中每个属性的句柄是唯一的。UUID包括属性表中的数据类型信息,它是理解属性表中值的每一个字节的关键信息。GATT表中可能有多个属性拥有相同的UUID值。
属性相关的数据结构:
/**@brief 属性元数据. */
typedef struct
{
ble_gap_conn_sec_mode_t read_perm; /**< 读权限 */
ble_gap_conn_sec_mode_t write_perm; /**< 写权限 */
uint8_t vlen :1; /**< 属性长度. */
uint8_t vloc :2; /**< 值存放的位置, 详情参照BLE_GATTS_VLOCS.*/
uint8_t rd_auth :1; /**< 读许可,该值会在每次读操作后向应用重新发起请求*/
uint8_t wr_auth :1; /**< 写许可会在每次读操作后向应用重新发起请求(但不写命令). */
} ble_gatts_attr_md_t;
/**@brief GATT 属性. */
typedef struct
{
ble_uuid_t* p_uuid; /**< 指向属性的UUID */
ble_gatts_attr_md_t* p_attr_md; /**< 指向属性元数据的数据结构*/
uint16_t init_len; /**< 初始化属性长度 */
uint16_t init_offs; /**< 初始化属性偏移 */
uint16_t max_len; /**< 最大属性长度,参照BLE_GATTS_ATTR_LENS_MAX*/
uint8_t* p_value; /**< 指向属性数据。请注意如果 BLE_GATTS_VLOC_USER值的位置被选在attribute metadata结构体中,则需指向有效生命周期缓冲区。协议栈可能在没有得到应用程序许可的情况下直接操作 */
} ble_gatts_attr_t;
/**@brief GATT 属性内容. */
typedef struct
{
ble_uuid_t srvc_uuid; /**< 服务UUID */
ble_uuid_t char_uuid; /**< 特性的UUID(BLE_UUID_TYPE_UNKNOWN无效). */
ble_uuid_t desc_uuid; /**< 描述UUID(BLE_UUID_TYPE_UNKNOWN无效). */
uint16_t srvc_handle; /**< 服务句柄 */
uint16_t value_handle; /**< 特性的处理句柄(BLE_GATT_HANDLE_INVALID 无效). */
uint8_t type; /**< 属性类型, 参照BLE_GATTS_ATTR_TYPES. */
} ble_gatts_attr_context_t;
描述符:
在任何特性中的属性不是定义为属性值就是描述符。描述符是一个额外的属性,以提供更多特性的信息。这里有个特殊的描述符:客户端特性配置描述符cccd。这个描述符是给任意支持通知或指示功能的特性额外添加的。在cccd中写入1为使能通知功能,写入2使能指示功能,写0禁止通知和指示功能。
UUID:
在GATT规范中定义所有的属性都必须要有一个UUID值,UUID是全球唯一的128位的数据,用来识别不同的特性。
蓝牙核心规范制定了两种不同的UUID,一种是基本的UUID,一种是代替基本UUID的16为UUID。
我们协议栈的后面那里使用的就是代替基本UUID的16为UUID:先增加一个特定的基本UUID,在定义一个十六位的UUID。加载到基本UUID之上。源码中UUID如下:
#define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}
#define LBS_UUID_SERVICE 0x1523
#define LBS_UUID_LED_CHAR 0x1525
#define LBS_UUID_BUTTON_CHAR 0x1524
//添加一个特定的基本UUID
ble_uuid128_t base_uuid = {LBS_UUID_BASE};
err_code = sd_ble_uuid_vs_add(&base_uuid, &p_lbs->uuid_type);