![【GATT】规范精讲[3]: 拆开一个 Service 看内脏——从声明三件套到 CCCD 每个客户端一份的订阅机制](http://pic.xiahunao.cn/yaotu/【GATT】规范精讲[3]: 拆开一个 Service 看内脏——从声明三件套到 CCCD 每个客户端一份的订阅机制)
上一篇我们把 GATT 的角色、属性模型、缓存机制跑通了一遍,知道了一个特征定义由声明、值、描述符组成。但光有概念还写不了代码——声明句柄里的值到底怎么编码?Properties 那一个字节的 8 个位分别管什么?CCCD 为什么每个客户端独立一份?这一篇我们把 GATT 的服务和特征彻底拆开,看到每一个字节。这次不玩虚的,直接对着一个 Heart Rate Service 的属性表实例,逐行把规范里 0x2800 到 0x2905 这九种属性的长相、顺序、权限、语义全部讲透。目录一、服务定义的边界:从哪里开始,到哪里结束1.1 服务声明的四个字段二、Include 定义:一行指针,引用整个服务2.1 循环引用:必须主动防御三、特征定义:声明 + 值 + 描述符的三明治3.1 聚合特征:把多个值打包读四、特征声明:三件套定身份五、Properties 位域:一个字节管住八种能力5.1 实战:BlueZ 风格的服务注册代码六、特征值声明:数据本体与权限的自由地七、描述符总览:六种标准形态,顺序无关八、0x2900 扩展性质:Properties 的溢出位九、0x2901 用户描述:给值起个人类可读的名字十、0x2902 CCCD:订阅机制的核心,每个客户端一份10.1 每客户端独立的实例池10.2 位定义与默认值10.3 订阅的客户端代码十一、0x2903 SCCD:服务器全局开关,与 CCCD 镜像十二、0x2904 呈现格式:告诉对方这个字节流怎么解读12.1 Exponent:定点数的换算公式12.2 Description:同一特征的多个实例怎么区分十三、0x2905 聚合格式:多段值的解码说明书十四、一张表收拢:GATT 属性类型全图鉴十五、把解剖结果装回去:一个特征定义的全貌十六、测验一、服务定义的边界:从哪里开始,到哪里结束一个服务定义在属性表里占据一段连续的句柄区间,规范对它的边界定得很死:A service definition shall contain a service declaration and may contain include definitions and characteristic definitions. The service definition ends before the next service declaration or after the maximum Attribute Handle is reached.服务定义必须以一条服