属性和数据层次
根据之前说的这些所有的属性概念,来构建属性的数据层次。
属性在服务器上被分成了组,一个就叫一个服务,每个而服务有0个或者多个特征。一个特征包含0或者多个描述符。属性会被分到不同的特种中,没有野生的属性,属性都是被管理起来的。只有这样,才能有效的在设备之间交换数据。
对于大部分类型的数据来说,区别声明declaration和定义definition是很重要的。
声明是一个单独的属性,放在前面的位置,用来介绍后面跟着的属性的定义和对这些属性数据的一些说明。声明属性都是只读的,并且没有安全要求,因为声明属性不含有任何敏感信息。声明属性只是为了让客户端找到这些属性的位置。
服务
GATT的服务与属性相关。服务的属性连接着服务的定义。服务的声明总是服务的第一个属性值。
也可以把GATT考虑成一个面向对象的语言,因为GATT可以被多次初始化。
在一个服务定义的内部,用户可以添加更多对其他服务的引用。引用也是一个单独的属性,类似于创建了一个快捷方式。
引用可以避免在GATT中有重复的数据,如果一个服务被其他服务所引用,对应的内存就可以被节省下来。也可以认为引用就是一个指针。
特性
特性就是用户数据的一个容器。总是包含了2个属性,特性的属性和特性的值。
而且,特性的值之后有一个说明符,会进一步的描述包含的数据。声明,数据和描述符一起构成了特性。
这个图中,第一个特性是声明属性,第二个是真实的用户数据。
特性声明属性
客户端只可以读取特性描述属性的值,但是不可以修改这个值。
特性属性
占8个位,再加上另外2个位作为拓展位。
客户端可以读取这些属性来识别哪些操作是可以执行的。对于Notify和Indicate属性来说,这是很重要的。
特性值句柄
使用2个字节来标识特性值的句柄。
特性UUID
特性值属性
特性值属性包含了真实的用户数据,客户端可以读取或者写入。特性值属性可以包含任意的数据。
特性描述符
GATT特性描述符是最被广泛使用的元数据,它会提供给客户端。描述符总是放在特性定义中并且紧跟着特性值属性。描述符放在了特性描述声明中。
有2中不同的特性描述符
- GATT定义的描述符
- 规格或者是厂家定义的描述符
一些被GATT定义好的的描述符
- Extended Properties Descriptor
- Characteristic User Description Descriptor
- Client Characteristic Configuration Descriptor,简称CCCD
最重要并且使用最广泛,对于大部分的规格来说,这个描述符都是必要的。它的功能也很简单,作为一个交换器,打开或者关闭服务器初始化更新的功能。
CCCD的值只有2个字节,一个字节代表通知,一个代表只是。客户端可以设置或者清除这个位,当值有变化的时候,服务器端都会检查这个位来判断要不要更新。
客户端想要设置这个值的时候,会发送一个写入请求的ATT包Write Request ATT packet来把这个位设置为1. 服务器会发回一个响应包并且发送合适的包给客户端。
CCCD还有2个特别的属性
- 在每个链接中,他们的值都是唯一的。
- 他们的值保存在已经绑定设备之间的连接中。
特性存在格式描述符
描述符的类型包含了真是的特性数据的格式。占了7个字节的位置。格式可以是布尔型,字符串,整型,浮点数,甚至可以是没有类型的缓存。