
这个蓝牙的使用,主要是在应用层上,也就是需要我们去调用对应的api接口去打开蓝牙,广播或则是扫描,这些都有对应的回调函数(gap事件回调和gatt事件回调,需要注意的是,这些回调函数都是底层事件执行完之后,才会在应用层回调),用来处理对应的蓝牙状态,例如说,我在应用层上打开蓝牙,然后这个指令层层下发,蓝牙打开成功后,就会有一个在应用层上对应的回调函数,进行处理,然后可以将之通过串口打印出来,就可以得知蓝牙打开成功。
理解蓝牙数据结构大致的概念
蓝牙的数据通信的参数类型分为三种:服务、特征、属性;这三个是包含关系:服务包含特征,特征包含属性,属性是一条具体的数据,特征是具有某一种“特征”的属性的集合,而服务则是由多个这种特征构成。例如:一个心率计的设备
服务:心率计
这个设备的主要作用就是用于显示心跳数的,它的服务就是心率计
特征:电池信息、每分钟心跳数
这个特征,也可以说是对应的心率计的功能,一个心率计,至少要包含电池电量的信息,以及主要的功能,统计心跳次数
属性:心率计服务申明、心率计服务的值(名称);电池信息申明、电池电量的值;心跳信息的声明、心跳信息的值
这个属性,就比较多了,因为这个是数据最终存储的形式,以上的服务与特征更像是概念,提供给客户端的一种概念,告诉客户端,这些数据是一个服务,一个特征或者说是功能,就例如下面那张图显示的。

如何让客户端知道这个数据具体是什么,那么肯定是需要通过一个协议来规定双方传输的数据到底是什么,在蓝牙中,这个协议就是ATT协议,正式的说法是:attribute protocol(数据交换协议),属性就是对这个过程中传输的数据的一个称呼。
就例如:要告诉客户端,接下来传输的一串数据是服务,那么至少需要两个数据,即是什么,值是多少。具体举例就是:一个是告诉客户端接下来的一个数据是:“服务”,一个就是就是服务的具体的值,也就是服务名称之类的方便客户端识别。这两条数据都被称为属性。前一条属性(数据)称为服务申明,后一条数据称为服务的值。同理,特征也是这样的,也有一个特征申明和特征的值,除此之外还有一个客户端描述符,这个客户端描述符是用于配置客户端通知的,通俗来说,这个是用于标记客户端是否使用了订阅的这个功能,其本质上也是客户端往服务端写入一个指令,改变一个标志位,让服务端在某些数据发生改变的时候,给客户端发送一条消息。
UUID
这个起始就是一个蓝牙联盟定义好的一个类似头文件的东西,只要是在这个文件中有的,那么只要是用了蓝牙协议,那么客户端就可以直接识别这是一个什么类型的数据,进而进行处理,例如说,它规定了一个UUID表示这是一个服务申明,那么服务端在传输这条数据的时候,客户端识别到这个UUID,那么客户端就可以知道,这条数据是一个服务申明,接下来的一条数据就是服务所对应的值。
像上文中的图里面显示的 Unknow Server 和Unknow Characteristic 的原因就是,这个服务的名称和特征的名称的UUID是我随便写的,所以客户端的蓝牙协议不知道这个服务的名称是什么,特征的名称是什么,当然,如果是自己写的上位机是可以做一个协议的,毕竟这就是一条数据而已,接收到对应的数据,显示某一特定的名称,完全是可以的。
ATT协议
通过上文,就可以知道这个就是一个关于传输的数据的定义,进行互相沟通的基础。它包括的内容是:
句柄:这个就是用来操作这条数据的一个在 属性集合或则说是数据库的一个下标,通过这个句柄(下标)可以知道哪些数据发生了改变。Ps:在回调函数中处理的时候,他的这个值就已经被改变了,除非是预备写,然后再执行写入操作,否则这些回调函数都是执行完毕之后返回的结果。
类型:这个类型,就是UUID,也是蓝牙联盟规定的特定的类型的数据,例如说数据类型是 服务声明,特征申明,这个都是固定的,以便蓝牙客户端能够识别,才能进行沟通
值:这个就是数据的值
权限:这个是对于这条数据的操作权限,读/写。Ps:要区别于特征的权限,特征的权限是用来表示客户端对这个特征的权限,例如 读/写/通知/指示,一般来说,特征申明就是只有一个读的属性权限,他的值可以是读/写的属性权限,对于整个特征来说,就可以有读/写/通知/指示权限
GAP协议
这个协议适用于两台蓝牙设备进行连接时的协议,包括广播、扫描、连接
广播:如何广播,广播类型,广播的格式、广播的间隔等等
扫描:扫描的间隔。。。。
连接:连接
GATT协议
这个协议是用于连接成功之后,设备之间的通讯,定义了两个角色,一个是服务端,一个是客户端,其全称是:generic attribute profile(一般化属性子规范),像这种的就是对传输的数据进行划分,使之变得有意义,通俗来说,就是将一个个的属性按照一定的规则划分,具体来说,就是例如一个37,这个值,可以代表温度,也可以代表湿度,还可能是心率,然后GATT在这里起的作用就是,将数据建成一个数据库,将各种声明和对应的值添加到这个数据库中,方便之后通讯的时候使用,类似如下图所示的,将一条条属性整合到一起。
这个和ATT的区别:在于ATT是将数据进行规范,针对传输的数据的个体,而GATT是将这些散乱的数据整合到一起,使得数据有意义,知道一个数37是温度的值,还是湿度的值

参考链接
https://blog.csdn.net/zhuimeng_ruili/article/details/120493566