GATT中属性的权限是根据不同的服务来定义的,我可以这么理解吗 ?用蓝牙手表来举例,蓝牙手表中什么服务对应上图中不同的属性权限,请一一列举
一、先纠正你的核心理解
你的理解不完全准确:权限不是按「服务」定义,而是按「服务下的每个特征值(Characteristic)」单独定义的。
- 一个服务(Service)可以包含多个特征值(Characteristic),每个特征值有自己独立的 perm 权限位,同一个服务下的不同特征值权限可以完全不同。
- 举个例子:电池服务(
0x180F)里,「电池电量」特征值是只读,但「电池状态」特征值可能是只读+加密,权限完全独立。
二、蓝牙手表中典型服务 & 对应特征值的权限配置(完全匹配你图中的 perm 宏)
我以主流智能手表(如小米/华米/Amazfit 手表,基于 NuttX/Zephyr BLE 协议栈)的真实实现为例,按服务分类,一一对应你图中的权限:
1. 通用访问服务 GAP(0x1800)
| 特征值名称 |
特征值UUID |
权限配置(对应图中宏) |
权限说明 |
| 设备名称(Device Name) |
0x2A00 |
BT_GATT_PERM_READ |
允许客户端(手机)直接读取,无需加密 |
| 外观(Appearance) |
0x2A01 |
BT_GATT_PERM_READ |
只读,公开设备类型(手表/手环) |
| 外围设备首选连接参数 |
0x2A04 |
BT_GATT_PERM_READ |
只读,公开连接参数 |
2. 通用属性服务 GATT(0x1801)
| 特征值名称 |
特征值UUID |
权限配置 |
权限说明 |
| 服务变更(Service Changed) |
0x2A05 |
BT_GATT_PERM_INDICATE(协议栈内置) |
仅用于指示,无读写权限 |
3. 电池服务 Battery Service(0x180F)
| 特征值名称 |
特征值UUID |
权限配置 |
权限说明 |
| 电池电量(Battery Level) |
0x2A19 |
BT_GATT_PERM_READ |
手机可直接读取电量,无需加密 |
| 电池状态(Battery Status,自定义) |
0x2A1A(标准)/ 自定义UUID |
BT_GATT_PERM_READ |
只读,公开充电状态 |
| 特征值名称 |
特征值UUID |
权限配置 |
权限说明 |
| 制造商名称(Manufacturer Name String) |
0x2A29 |
BT_GATT_PERM_READ |
只读,公开厂商信息 |
| 型号字符串(Model Number String) |
0x2A24 |
BT_GATT_PERM_READ |
只读,公开型号 |
| 固件版本(Firmware Revision String) |
0x2A26 |
BT_GATT_PERM_READ |
只读,公开固件版本 |
| 硬件版本(Hardware Revision String) |
0x2A27 |
BT_GATT_PERM_READ |
只读,公开硬件版本 |
| 序列号(Serial Number String) |
0x2A25 |
BT_GATT_PERM_READ_ENCRYPT |
必须加密连接才能读取,保护设备唯一标识 |
5. 心率服务 Heart Rate(0x180D)
| 特征值名称 |
特征值UUID |
权限配置 |
权限说明 |
| 心率测量(Heart Rate Measurement) |
0x2A37 |
BT_GATT_PERM_NOTIFY(协议栈内置) |
仅通知,无读写权限 |
| 身体传感器位置(Body Sensor Location) |
0x2A38 |
BT_GATT_PERM_READ |
只读,公开传感器位置(手腕) |
| 心率控制点(Heart Rate Control Point) |
0x2A39 |
BT_GATT_PERM_WRITE |
允许手机写入命令(如重置能量消耗) |
6. 健康监测类服务(手表核心功能)
6.1 血氧服务(自定义/标准 0x1822)
| 特征值名称 |
权限配置 |
权限说明 |
| 血氧测量值 |
BT_GATT_PERM_NOTIFY |
仅通知,无读写 |
| 血氧配置 |
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT |
读取公开,写入必须加密(防止恶意修改配置) |
6.2 步数/运动服务(自定义UUID)
| 特征值名称 |
权限配置 |
权限说明 |
| 实时步数 |
BT_GATT_PERM_NOTIFY |
仅通知 |
| 步数历史数据 |
BT_GATT_PERM_READ_ENCRYPT |
必须加密才能读取,保护用户隐私 |
| 运动目标配置 |
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT |
读取公开,写入加密 |
7. 系统控制类服务(手表核心安全服务)
7.1 时间同步服务(自定义UUID)
| 特征值名称 |
权限配置 |
权限说明 |
| 当前时间 |
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT |
读取公开,写入必须加密(防止恶意篡改时间) |
| 时区配置 |
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT |
同上 |
7.2 通知/消息服务(自定义UUID)
| 特征值名称 |
权限配置 |
权限说明 |
| 来电通知 |
BT_GATT_PERM_WRITE_ENCRYPT |
仅允许配对加密的手机写入,防止恶意推送 |
| 短信/APP通知 |
BT_GATT_PERM_WRITE_ENCRYPT |
同上 |
| 通知控制(已读/忽略) |
BT_GATT_PERM_WRITE_ENCRYPT |
同上 |
7.3 固件升级 DFU 服务(自定义/标准 0xFE59)
| 特征值名称 |
权限配置 |
权限说明 |
| DFU 控制点 |
BT_GATT_PERM_WRITE_ENCRYPT |
必须加密才能写入,防止恶意刷机 |
| DFU 数据包 |
BT_GATT_PERM_WRITE_ENCRYPT |
同上 |
| DFU 状态 |
BT_GATT_PERM_READ_ENCRYPT |
必须加密才能读取升级状态 |
8. 安全与配对相关服务
8.1 安全服务(Security Service)
| 特征值名称 |
权限配置 |
权限说明 |
| 配对密钥 |
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT |
读写都必须加密,最高安全等级 |
| 身份验证 |
BT_GATT_PERM_WRITE_ENCRYPT |
仅加密写入 |
三、权限配置的核心设计原则(手表开发必看)
| 权限宏 |
适用场景(手表中) |
设计逻辑 |
BT_GATT_PERM_READ |
公开信息:设备名、电量、型号、心率位置 |
无需隐私保护,手机可直接获取 |
BT_GATT_PERM_WRITE |
低风险控制:心率重置、简单配置 |
无敏感操作,允许直接写入 |
BT_GATT_PERM_READ_ENCRYPT |
隐私数据:序列号、步数历史、用户信息 |
防止未配对设备窃取用户隐私 |
BT_GATT_PERM_WRITE_ENCRYPT |
高风险操作:时间修改、固件升级、消息推送 |
防止未授权设备恶意控制手表 |
四、补充:权限的组合使用(真实代码示例)
在 NuttX/Zephyr 协议栈中,权限是按位或组合的,比如手表中「时间同步」特征值的权限配置:
// 允许读取(公开)+ 必须加密才能写入(安全)
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT
再比如「序列号」特征值:
// 必须加密才能读取,禁止写入
BT_GATT_PERM_READ_ENCRYPT
五、一句话总结
- 权限是「特征值级」的,不是「服务级」的,同一个服务下的不同特征值可以有完全不同的权限。
- 蓝牙手表中:公开信息用无加密权限,隐私/控制类数据用加密权限,是保障安全的核心设计。
要不要我给你一份完整的手表GATT服务+特征值+权限的C语言代码示例,可以直接在NuttX/Zephyr协议栈中使用?