CC2640R2F BLE5.0 蓝牙协议栈通用属性配置文件(GATT)

来源:互联网 发布:对银行业的看法 知乎 编辑:程序博客网 时间:2024/05/22 14:39
公司主页文档归类淘宝

通用属性配置文件(GATT)

正如GAP层负责连接相关的功能,GATT主要是负责在两个已经连接的设备交互数据,GAP层把BLE设备区分为主机Master(Central)和从机Slave(Perpherial),在GATT层则区分为Server和Client。客户端读取和写入存储在服务端的特征值(Characteristics )。

Server
该设备包含由GATT客户端读取或写入的characteristic。

Client
从GATT服务器读取或写入数据的蓝牙设备。

注意:对于GATT分层的Server/Client角色和GAP分层的Master(Central)/Slave(Perpherial)并没有直接关系。如上图,手机作为Central/Client,CC2640R2开发板作为 Peripheral/Server。

GATT的Profile、Service、Characteristics、Attributes

对于GATT层的Profile、Service、Characteristics、Attributes概念,我们一定要深入理解,因为一旦建立连接后,不管是嵌入式端还是应用端进行数据交互的都是这些概念。为了帮助理解,我们抽象以下包含关系:

一个或者多个Characteristic组成一个Service,一个多个Service组成Profile,Characteristic又由多个Attributes组成,每个Attribute由包含 Handle、Type、Permissions三个属性。
以下我们着重理解Characteristic,也是我们数据交互的最终实体,每个特征包含以下4个Attributes。

  • Characteristic Value(特征值)
    用于characteristic的值

  • Characteristic Declaration(特征声明)
    存储特征值的属性,位置和类型的描述符

  • Client Characteristic Configuration(客户端特征配置)
    允许GATT服务器配置要通知的特性(异步发送消息)或指示的配置(与确认异步发送消息)

  • Characteristic User Description(特征用户描述)
    描述特征的ASCII字符串
    这些属性存储在属性表中的GATT服务器中。除了该值之外,以下属性与每个属性相关联。

以上的每个Attributes 又由以下元素组成。

  • Handle(句柄)
    表中属性的索引(每个属性都有一个唯一的句柄)

  • Type(类型)
    指示属性数据表示什么(称为UUID [通用唯一标识符],其中一些是蓝牙SIG定义的,一些是自定义的)

  • Permissions(权限)
    强制GATT客户端设备如何以及如何访问属性的值

GATT客户端抽象层

下图所示,在GATT客户端应用程序大部分是直接使用GATT的API(少部分直接使用ATT层API),没有profile文件,因为GATT客户是得到数据,不需要建立属性表和配置文件。

GATT服务端抽象层

如图所示,在GATT服务端,GATT层的大部分功能由独立的profiles处理,然后可以看见perfiles又使用GAttservApp模块(一个可配置的模块,用于储存和管理属性表,详见BLE Stack API Reference)处理。

所以在建立GATT服务端的时候首先需要配置profiles文件,profiles文件调用GattServAppApp模块并使用其API与GATT层接口。在这种情况下应用程序不需要直接调用GATT层API,应用程序和Profiles文件接口。

GATT Services 和 Profile

在概述部分讲过,GATT service是characteristic的集合,多个service可以组合在一起形成一个profile,许多profile仅实现一个service,所以profile和service可以互换。

在simple_peripheral示例应用程序项目中定义了四个GATT服务。

  • GAP GATT服务(GGS)
    此服务包含设备和访问信息,例如设备名称,供应商标识和产品标识。
    为此服务定义了以下特征:

    设备名称
    表现(Appearance)
    外围首选连接参数

  • 通用属性服务
    该服务包含有关GATT服务器的信息,是蓝牙低功耗协议栈的一部分,每个GATT服务器设备都需要根据蓝牙5.0版本核心规范。

  • 设备信息服务
    此服务公开了有关设备的信息,如硬件,软件版本,固件版本,规范信息,合规性信息和制造商名称。设备信息服务是蓝牙低功耗协议栈的一部分,由应用程序配置。

  • simple_gatt_profile服务
    此服务是用于测试和演示的示例配置文件。完整的源代码在simple_gatt_profile.c和simple_gatt_profile.h文件中提供。

  // Initialize GATT attributes  GGS_AddService(GATT_ALL_SERVICES);           // GAP GATT Service  GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT Service  DevInfo_AddService();                        // Device Information Service  SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile

下图显示了simple_peripheral项目中的属性表,这些属性的设置都是通过上面4个服务函数。可以逐一打开查看修改。

使用BTool获取的简单GATT配置文件特性表。红色表示Profile声明,黄色表示字符声明,White表示与特定声明相关的属性。

simple_gatt_profile包含以下特性:

  • SIMPLEPROFILE_CHAR1
    可以从GATT客户端设备读取或写入的1字节值
  • SIMPLEPROFILE_CHAR2
    可以从GATT客户端设备读取但不能写入的1字节值
  • SIMPLEPROFILE_CHAR3
    可以从GATT客户端设备写入但不能读取的1字节值
  • SIMPLEPROFILE_CHAR4
    不能从GATT客户端设备直接读取或写入的1字节值(该值是通知属性)
  • SIMPLEPROFILE_CHAR5
    可从GATT客户端设备读取(但不写入)的5字节值

0x001C是simple_gatt_profile服务声明。
此声明的UUID为0x2800(蓝牙定义 GATT_PRIMARY_SERVICE_UUID)。该声明的值是simple_gatt_profile(自定义)的UUID。

0x001D是SimpleProfileChar1特征声明。
该声明可以被认为是指向SimpleProfileChar1值的指针。该声明的UUID为0x2803(蓝牙定义GATT_CHARACTER_UUID)。下面解释characteristic声明值的含义(MSB到LSB):

  • 字节0是蓝牙核心规范版本5.0中定义的SimpleProfileChar1的属性 (以下是某些相关属性)。
    0x02:允许读取特征值
    0x04:允许写入特征值(无响应)
    0x08:允许写入特征值(带响应)
    0x10:允许通知特征值(无确认)
    0x20:允许通知特征值(带确认)
    characteristic1 0x0A的意义是该特性可读可写(0x02|0x08)

  • 字节1-2:SimpleProfileChar1的值的句柄(句柄0x001E)

  • 字节3-4:SimpleProfileChar1值的UUID(自定义0xFFF1)

  • 0x001E是SimpleProfileChar1特征值
    该值的UUID为0xFFF1(自定义)。该值是characteristic的实际有效载荷数据。如其SimpleProfileChar1声明(句柄0x01D)所示,该值是可读写的。

  • 0x001F是SimpleProfileChar1特征用户描述
    该描述的UUID为0x2901(蓝牙定义)。该描述的值是描述特征的用户可读字符串。

  • 0x0020 - 0x002C
    剩下的四个特征描述具有和simpleProfileChar1相同结构的属性。唯一不同的属性是处理0x0028时,描述如下。

    0x0028是SimpleProfileChar4客户端特征配置。此配置的UUID为0x2902(蓝牙定义)。通过写入此属性,GATT服务器可以将SimpleProfileChar4配置为通知(写入0x0001)或指示(写入0x0002)。将0x0000写入此属性将禁用通知和指示。

GATT安全

如GATT 服务端抽象所述,GATT服务器可以为每个特性独立定义权限。服务器可能允许任何客户端访问某些characteristic,同时将访问其他characteristic仅限于认证或授权的客户端。这些权限通常被定义为更高级别的配置文件规范的一部分。对于自定义配置文件,用户可以选择他们认为合适的权限。有关GATT安全性的更多信息,请参阅蓝牙核心规范版本5.0的安全注意事项部分([第3卷,第G部分,第8部分])。

认证(Authentication)

在客户端通过认证配对方法之前,无法访问需要身份验证的特性。此验证在堆栈内执行,无需应用程序处理。唯一的要求是使GATT服务端正确注册该特性。
例如,simple_gatt_profile的characteristic5设置需要认证的读取。

//characteristic 5 {    {  ATT_BT_UUID_SIZE , simpleProfilechar5UUID  },   GATT_PERMIT_AUTHEN_READ ,   0 ,   simpleProfileChar5 },

当未经身份验证的客户端尝试读取此值时,GATT服务器将自动拒绝它,而不调用simpleProfile_ReadAttrCB()。只有当认证成功之后,读写的请求才会转发到profiles的读写回调,请参阅一下代码,该代码在simple_gatt_profile.c中simpleProfile_ReadAttrCB()函数里面。

  case SIMPLEPROFILE_CHAR1_UUID:  case SIMPLEPROFILE_CHAR2_UUID:  case SIMPLEPROFILE_CHAR4_UUID:    *pLen = 1;    pValue[0] = *pAttr->pValue;    break;  case SIMPLEPROFILE_CHAR5_UUID:    *pLen = SIMPLEPROFILE_CHAR5_LEN;    VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN );    break;      default:    // Should never get here! (characteristics 3 和 4没有读权限)    *pLen = 0;    status = ATT_ERR_ATTR_NOT_FOUND;    break;

授权(Authorization)

授权是发生在认证之后对一些文档的访问权限更改删除,需要授权。授权是BLE已经实现的一个安全层。由于应用程序需要定义自己的授权要求,所以协议栈将这些特性的读/写请求转发到配置文件的应用程序层。

要从profile文件注册GATT服务器的授权信息,它必须使用堆栈定义一个授权回调。如下面伪代码(例程中没有使用授权)。

  1. 注册授权回调
CONST  gattServiceCBs_t  simpleProfileCBs  = {    simpleProfile_ReadAttrCB ,      //读回调函数指针   simpleProfile_WriteAttrCB ,     //写回调函数指针   simpleProfile_authorizationCB   //授权回调函数指针};
  1. 实现授权回调代码
static  bStatus_t  simpleProfile_authorizationCB ( uint16  connHandle , gattAttribute_t  * pAttr , uint8  opcode  ){    //这只是一个示例实现,正常的用例将需要   更复杂的逻辑来确定设备是否被授权   if (clientIsAuthorized )      return SUCCESS ;    else      return ATT_ERR_INSUFFICIENT_AUTHOR ; }

授权回调在协议栈上下文中执行,因此在这个函数中不应该执行太复杂的处理。具体实现由开发人员决定;上述回调应该被视为一个shell。如果客户端有权访问该特征返回SUCCESS,如果没有返回ATT_ERR_INSUFFICIENT_AUTHOR,授权需要事先通过连接进行身份验证,否则ATT_ERR_INSUFFICIENT_AUTHEN将作为错误响应发送。

如果需要授权的特性并注册了授权回调,但没有定义应用级授权回调,那么协议栈将返回ATT_ERR_UNLIKELY。因为这个错误并不明确,所以TI建议使用授权回调。

直接使用GATT层

上面客户端抽象说过,应用程序也可以直接使用GATT层API,本节就介绍如何在应用程序中使用GATT层,GATT层的功能在库中实现,但头文件功能可在gatt.h中找到。BLE Stack API Reference中有完整的API参考。作为GATT客户端(在simple_central项目中)使用GATT层的一般过程如下:

图中可以看出,GATT客户端发送命令之后,通过ICALL给协议栈发送ATT命令,然后协议栈处理之后返回响应,再由ICALL以ATT事件通知应用程序,应用程序得到ATT事件之后异步处理。注意:除了收到对自己的命令的响应外,GATT客户端还可以从GATT服务器接收异步数据作为指示或通知。使用GATT_RegisterForInd(selfEntity)注册接收这些ATT通知和指示。这些通知和指示也作为ATT事件(ATT_HANDLE_VALUE_NOTI& ATT_HANDLE_VALUE_INDG)发送到应用程序。这些事件必须按照GATT Services和Profile中的说明进行处理。

GAP GATT 服务(GGS)

在前面GATT服务和简介中说过,GGS服务包含设备和访问信息,例如设备名称,Appearance,外围首选连接参数。GGS的目的是在设备发现和连接启动过程中进行辅助。有关GGS的更多信息,请参阅蓝牙核心规范版本5.0的“GAT service”和“Characteristics for GATT Server”部分([Vol 3],C部分,第12节)。

  1. 包含标题
#include  “gapgattserver.h”
  1. 初始化GGS参数
// GAP GATT Attributes static  uint8_t  attDeviceName [ GAP_DEVICE_NAME_LEN ]  =  “This is a text” ;GGS_SetParameter (GGS_DEVICE_NAME_ATT , GAP_DEVICE_NAME_LEN , attDeviceName );
  1. 使用GGS初始化应用程序回调(可选)。当GGS中的任何特征发生变化时,都会通知应用程序。
GGS_RegisterAppCB (&appGGSCBs );
  1. 将GGS添加到GATT服务器。
bStatus_t  GGS_AddService (GATT_ALL_SERVICES );

经过上面4个步骤的配置,就成功设置了GGS的参数,在central设备连接外围设备的时候就能获取这些参数,使用我们公司提供的XXX.apk可以在手机界面直接查看我们设置的参数值。

加入我们

文章所有代码、工具、文档开源。加入我们QQ群 591679055获取更多支持,共同研究CC2640R2F&BLE5.0。

CC2640R2F&BLE5.0-乐控畅联© Copyright 2017, 成都乐控畅联科技有限公司.

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 台式电脑玩lol卡怎么办 配置充足玩lol卡怎么办 电脑买贵了应该怎么办 微信红包收不了钱怎么办 mac版excel卡死怎么办 锐捷网卡为空怎么办 淘宝上买东西卖家不发货怎么办 快递员没给单号怎么办 淘宝物流把货弄丢了怎么办 刚买的卡没激活怎么办 腾讯王卡40g用完怎么办 手机欠费不知道电话号码怎么办 手机欠费了不用了怎么办 闲鱼恶意差评怎么办 淘宝买家账户体检中心违规怎么办 淘宝卖家账户体检中心违规怎么办 淘宝好评被删除评价怎么办 淘宝没收到货确认收货了怎么办 美团评论被删怎么办 拼多多恶意差评怎么办 淘宝评论被删了怎么办 淘宝买东西错怪店家了怎么办 淘宝骗删除差评怎么办 淘宝买家号虚假交易违规怎么办 淘宝商家一直不发货怎么办 淘宝商家不发货也不退款怎么办 淘宝买家恶意差评怎么办 淘宝评价完了忘截图了怎么办 12306app登录不上怎么办 淘宝换绑支付宝失败怎么办 淘宝和手机不兼容怎么办 换号之后微信怎么办 手机不兼容的应用程序怎么办 微信版本低登录不了怎么办 软件与系统不兼容怎么办 软件与手机系统不兼容怎么办 qq和手机不兼容怎么办 来个软件不兼容怎么办 安卓8.0不兼容app怎么办 两条内存不兼容怎么办 王者荣耀软件不兼容怎么办