- 导语
该篇文章,主要讲述BLE中的GATT profile。
1、什么是GATT
GATT是generic attribute的简称,顾名思义,其描述的是BLE的属性应用规范。所谓的属性,我们可以理解为数据库中的一张表,是一个可以被查找的数据;在BLE中,我们使用handle句柄来进行寻址,handle句柄值是唯一的。
在实际应用场景中,需要多个service来支持 ,每个service下面同时有多个特性(character),每个特性要有较为详细的描述,如这个特性的值和一些简单的说明等。无论是服务、特性,都要进行区分,BLE中使用UUID进行了区分。除此之外,作为数据,我们肯定是要对其进行访问的,这就要提供相应的访问权限,如可读、可写等。
属性
属性由属性句柄、属性类型、属性值等组成。
属性句柄就是我们来进行数据查找的依据;
属性类型使用UUID来进行区分,SIG对属性类型进行了分类:
0x1800 ~ 0x26FF 用作服务类通用唯一识别码
0x2700 ~ 0x27FF 用于标识计量单位
0x2800 ~ 0x28FF 用于区分属性类型
0x2900 ~ 0x29FF 用作特性描述
0x2A00 ~ 0x2AFF 用于区分特性类型
特性
在BLE规范中,特性一般包括声明、数值和描述三个部分,其中前两者是强制实现的。
2、GATT能干啥
简单来讲,BLE利用GATT来进行数据的传输。
3、 怎么来分析GATT
GATT中的service or characteristic,本质上都是attribute,为了使用的方便,BLE对这些又进行了逻辑上的抽象。
以电池服务为例:
一个电池服务(service)包含一个电池电量特性(characteristic),其一般包含以下几个属性:primary service 电池服务、当前电量的特性定义、当前电量的特性值。由于用户通常会希望能够进行低电量提醒,所以在设计的时候,这个电量特性值不仅是可读的,而且是可以通知的。
以下是battery service在Android中的实现。
/*******************************************************************************
**
** Function Battery_Instantiate
**
** Description Instantiate a Battery service
**
*******************************************************************************/
UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info)
{
tBT_UUID uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
UINT16 srvc_hdl;
tGATT_STATUS status = GATT_ERROR;
tBA_INST *p_inst;
tGATT_CHAR_PROP prop = GATT_CHAR_PROP_BIT_READ;
if (battery_cb.inst_id == BA_MAX_INT_NUM)
{
GATT_TRACE_ERROR("MAX battery service has been reached");
return 0;
}
p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
srvc_hdl = GATTS_CreateService (srvc_eng_cb.gatt_if ,
&uuid,
battery_cb.inst_id ,
BA_MAX_ATTR_NUM,
p_reg_info->is_pri);
if (srvc_hdl == 0)
{
GATT_TRACE_ERROR("Can not create service, Battery_Instantiate() failed!");
return 0;
}
battery_cb.inst_id ++;
p_inst->app_id = app_id;
p_inst->p_cback = p_reg_info->p_cback;
/* add battery level
*/
uuid.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
prop |= GATT_CHAR_PROP_BIT_NOTIFY;
if ((p_inst->ba_level_hdl = GATTS_AddCharacteristic(srvc_hdl,
&uuid,
BATTER_LEVEL_PERM,
prop)) == 0)
{
GATT_TRACE_ERROR("Can not add Battery Level, Battery_Instantiate() failed!");
status = GATT_ERROR;
}
else
{
if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
{
uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
p_inst->clt_cfg_hdl = GATTS_AddCharDescriptor(srvc_hdl,
(GATT_PERM_READ|GATT_PERM_WRITE),
&uuid);
if (p_inst->clt_cfg_hdl == 0)
{
GATT_TRACE_ERROR("Add battery level client notification FAILED!");
}
}
/* need presentation format descriptor? */
if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT)
{
uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
if ( (p_inst->pres_fmt_hdl = GATTS_AddCharDescriptor(srvc_hdl,
GATT_PERM_READ,
&uuid))
== 0)
{
GATT_TRACE_ERROR("Add battery level presentation format descriptor FAILED!");
}
}
/* need presentation format descriptor? */
if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF)
{
uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
if ( (p_inst->rpt_ref_hdl = GATTS_AddCharDescriptor(srvc_hdl,
GATT_PERM_READ,
&uuid))
== 0)
{
GATT_TRACE_ERROR("Add battery level report reference descriptor FAILED!");
}
}
/* start service
*/
status = GATTS_StartService (srvc_eng_cb.gatt_if, srvc_hdl, p_reg_info->transport);
}
if (status != GATT_SUCCESS)
{
battery_cb.inst_id --;
uuid.uu.uuid16 = UUID_SERVCLASS_BATTERY;
GATTS_DeleteService(srvc_eng_cb.gatt_if, &uuid, battery_cb.inst_id);
srvc_hdl = 0;
}
return srvc_hdl;
}
- 总结
本篇文章旨在简明的讲述GATT是什么,能干什么,怎么去使用GATT,读者有什么疑惑,可以一起讨论。
网友评论