Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1102055
  • 博文数量: 113
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3944
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-02 14:36
文章分类
文章存档

2019年(2)

2018年(10)

2017年(1)

2016年(50)

2015年(12)

2014年(9)

2013年(29)

分类: 嵌入式

2019-01-10 11:05:25

基础为  属性数据库

具体分析之前 还需要介绍 属性值访问权限的一点概念。

在属性数据库中介绍了 属性条目的组成为如下形式

句柄

UUID

属性值


上面的 形式是在 属性协议(ATT)中定义的

实际使用时,我们访问的就是 这个属性条目中的属性值,实际应用中有时候我们需要 设置一些访问权限,比如只有在链路加密时才能访问其中的属性值。

这就引入了一个访问权限的性质。

句柄

UUID

属性值

访问权限

比如将 访问权限 设置为写需要加密,而读不需要加密, 那么读这个属性值的操作随时可以进行,但是 写这个属性值的 操作只有在链路加密的情况下才可以,如果未加密的情况下写这个属性值,就会返回权限不足的错误。

这个访问权限的具体如何操作和定义是由厂商自己实现,并未有严格限定。只要行为上符合规范的要求即可(规范只定义了什么情况下返回什么样的安全错误,至于逻辑怎么做厂商自己决定)

 
属性数据库文档中 说过,我们通常说创建一个特性值,就是一个属性条目,我们利用的是其中的 属性值。

但是特性值 属性条目不是单独存在的, 它是属于特性 的一部分。

特性由几条属性条目组成, 包括一条 特性声明属性条目, 一条特性值属性条目, 几条描述符属性条目。

如下所示例的一个特性组成,包括一个 声明,一个特性值,两个描述符。

特性声明条目

特性值条目

描述符条目

描述符条目


Nordic sdk中提供的API就是创建特性api, 根据我们填入的参数协议栈会自动创建 声明,特性值,以及描述符, 并且API会返回 特性值以及一些存在的描述符的句柄,如下图。



API的第一个参数 service_handle为 服务句柄,即添加的特性是添加到哪个服务中的,所以首先要创建在服务后才能再服务下面添加特性,sdk中调用创建服务API函数后,会返回被创建的服务的句柄,如下图


之后第二个参数p_char_md定义了 特性中的 特性值 支持哪些操作,读,些,notify等。以及所需要的描述符的读写权限等信息。

第三个参数p_attr_char_value 定义了 特性值 的UUID,长度等信息。

第四个参数p_handles 为协议栈返回的 创建的特性 中的一些句柄,包括特性值句柄,以及存在的描述符句柄。


在ble_app_uart例子中 创建了一个nus的服务,其中存在一个rx特征值,就以该创建函数来详细分析一下创建过程中的参数设置

static uint32_t rx_char_add(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)

{

 

//这个变量中包含了特性值的支持的读,些,notify等操作,也定义了存在的描述符的一些访问权限等信息

ble_gatts_char_md_t char_md;

 

//rx特性值是用来将数据发给手机的,所以具有notify功能,所以需要CCCD描述符,这个cccd_md定义了CCCD描述符的访问权限等信息

ble_gatts_attr_md_t cccd_md;

//这个变量定义了我们最终要使用的RX特性值的UUID,大小等信息

ble_gatts_attr_t    attr_char_value;

//RX的UUID

ble_uuid_t          ble_uuid;

//这个变量会被赋值给 上面的attr_char_value,主要定义了特性值的访问权限,以及存在的位置等信息。

    ble_gatts_attr_md_t attr_md;

 

    memset(&cccd_md, 0, sizeof(cccd_md));

//设置CCCD描述符的读写访问权限为可访问,OPEN即为任意访问

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

 

   //设置CCCD描述符存在于协议栈中,这样协议栈就会自动在协议栈的内存中创建一块ram存放CCCD描述符

        cccd_md.vloc = BLE_GATTS_VLOC_STACK;

 

    memset(&char_md, 0, sizeof(char_md));

 

//工程中通过RX特性值发送数据给手机所以 以下定义了RX特性值 具有notify功能,其他参数赋值为NULL表示不需要或者使用默认值,主要就是一些没有使用的描述符的性质。 因为支持notify性质就需要有CCCD描述符,所以CCCD描述符的性质这里设置了。

    char_md.char_props.notify = 1;

    char_md.p_char_user_desc  = NULL;

    char_md.p_char_pf         = NULL;

    char_md.p_user_desc_md    = NULL;

    char_md.p_cccd_md         = &cccd_md;

    char_md.p_sccd_md         = NULL;

 

//设置  RX特性值的UUID

    ble_uuid.type = p_nus->uuid_type;

    ble_uuid.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;

 

    memset(&attr_md, 0, sizeof(attr_md));

 

//设置RX特性值的读写可以随便访问,不需要加密等保护

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);

//设置RX特性值存在于协议栈中,并且为变长,这样我们就不要自己定义一个全局变量,然后让RX特性值buff指向它了,而是协议栈自动在内部创建一个。

同时定义了读写不需要授权,nordic中定义的授权的意思是每次手机发来读写时,协议栈会先报告上层有读写,用户会同意给协议栈,协议栈才正真执行读写。

    attr_md.vloc    = BLE_GATTS_VLOC_STACK;

    attr_md.rd_auth = 0;

    attr_md.wr_auth = 0;

    attr_md.vlen    = 1;

 

    memset(&attr_char_value, 0, sizeof(attr_char_value));

 

//将上面定义的UUID,特性值的读写权限等参数赋值。

//设置了特性值的初始值的长度,偏移等,以及最大长度(特性值的存放是在协议栈中的,因为上面定义了其是在协议栈中的)

    attr_char_value.p_uuid    = &ble_uuid;

    attr_char_value.p_attr_md = &attr_md;

    attr_char_value.init_len  = sizeof(uint8_t);

    attr_char_value.init_offs = 0;

    attr_char_value.max_len   = BLE_NUS_MAX_RX_CHAR_LEN;

      

//最终调用添加特性API,最后一个参数就是常见成功后返回的特性值句柄,以及可能存在的描述符的句柄

    return sd_ble_gatts_characteristic_add(p_nus->service_handle,&char_md,&attr_char_value &p_nus->rx_handles);

}



阅读(1988) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~