【BT-SIG】【Core_v6.2】【Vol 3 Host】【Part G: GATT】【2.Profile overview】

GATT Profile Overview - Protocol (逐字精读版)

快速要点 (Key Takeaways)

  1. 全链路架构:GATT 是基于 ATT (Attribute Protocol) 构建的应用层骨架,定义了 Client 和 Server 角色交互的完整生命周期。
  2. 属性的物理本质 :在空中,数据永远被打包为包含 Handle (句柄) , Type (UUID) , Value (特征值) , Permissions (权限) 的四要素结构。
  3. Robust Caching (强健缓存) :现代 BLE 秒连的核心机制。通过 Database Hash (数据库哈希) 和 Service Changed (服务变更) 指示,确保客户端在重连时不会读写错乱的句柄。
  4. 层级结构 (Hierarchy) :构建了 Profile (配置文件) -> Service (服务) -> Characteristic (特性) -> Descriptor (描述符) 的四层抽象,是所有蓝牙应用的基石。
  5. 角色流动性:Client/Server 是按次(Transaction)划分的,与主从机 (Central/Peripheral) 物理状态完全解绑。

SIG 规范逐句深度解析

2. PROFILE OVERVIEW (配置文件概览)

原文:The GATT profile is designed to be used by an application or another profile, so that a client can communicate with a server. The server contains a number of attributes, and the GATT Profile defines how to use the Attribute Protocol to discover, read, write and obtain indications of these attributes, as well as configuring broadcast of attributes.

  • 逐字翻译:GATT 配置文件被设计为供应用程序或其他配置文件使用,以便客户端 (client) 可以与服务器 (server) 通信。服务器包含许多属性 (attributes),GATT 配置文件定义了如何使用属性协议 (Attribute Protocol) 来发现、读取、写入和获取这些属性的指示,以及如何配置属性的广播。
  • 深度技术释义:GATT (Generic Attribute Profile) 本身不是一个具体的应用(如心率计),它是一个"元框架"。它规定了所有其他具体应用 Profile(如 HRP, HID 等)必须遵守的数据存取规则。ATT 提供了底层的 PDU(数据包格式),而 GATT 赋予了这些 PDU 具体的业务语义(比如什么叫"发现服务")。

2.1 Protocol stack (协议栈层级)

原文 :Figure 2.1 shows the peer protocols used by this profile.

(架构图展示:Application -> Attribute Protocol -> L2CAP -> Controller)

  • 逐字翻译:图 2.1 展示了该配置文件使用的对等协议。
  • 深度技术释义:在蓝牙协议栈中,GATT 的数据直接投递给 ATT。ATT 将其组装成 PDU 后,再交给 L2CAP 层。在 L2CAP 层,ATT 数据拥有专用的固定通道(CID = 0x0004)。这意味着 GATT 数据不需要像传统蓝牙 (BR/EDR) 那样先进行复杂的 L2CAP 动态通道协商。

2.2 Configurations and roles (配置与角色)

原文 :The following roles are defined for devices that implement this profile:
Client ---This is the device that initiates commands and requests towards the server and can receive responses, indications and notifications sent by the server.
Server---This is the device that accepts incoming commands and requests from the client and sends responses, indications and notifications to a client.

  • 逐字翻译 :为实现此配置文件的设备定义了以下角色:
    客户端 (Client) ------ 这是向服务器发起命令 (commands) 和请求 (requests),并能接收服务器发送的响应 (responses)、指示 (indications) 和通知 (notifications) 的设备。
    服务器 (Server) ------ 这是接受来自客户端的传入命令和请求,并向客户端发送响应、指示和通知的设备。
  • 重点词汇
    • Initiates (发起):决定了谁是 Client 的唯一标准。
    • Accepts (接受):Server 被动等待请求。
  • 深度技术释义 :在 GATT 层面,拥有数据的一方是 Server,想获取数据的一方是 Client。例如,智能手表(拥有心率数据)是 Server,手机(需要心率数据来画图表)是 Client。

原文:Note: The roles are not fixed to the device. The roles are determined when a device initiates a defined procedure, and they are released when the procedure ends. A device can act in both roles at the same time.

  • 逐字翻译:注意:角色并没有固定在设备上。角色是在设备发起特定程序 (procedure) 时确定的,并在程序结束时释放。一个设备可以同时充当两个角色。
  • 深度技术释义:这是 BLE 最精妙的设计之一。一部手机既可以作为 Client 去读取耳机电量,也可以同时作为 Server 运行"时间服务"供耳机读取当前系统时间。

2.3 User requirements and scenarios (用户需求与场景)

原文 :The following scenarios are covered by this profile:

• Exchanging configuration

• Discovery of services and characteristics on a device

• Reading a characteristic value

• Writing a characteristic value

• Notification of a characteristic value

• Indication of a characteristic value

  • 逐字翻译:本配置文件涵盖以下场景:交换配置、发现设备上的服务和特性、读取特性值、写入特性值、特性值的通知、特性值的指示。
  • 深度技术释义:这六个场景定义了 GATT 的边界。其中"交换配置"通常指 Client 与 Server 交换 MTU(最大传输单元)大小。"通知 (Notification)"是 Server 发出数据后不管 Client 是否收到;"指示 (Indication)"是 Server 发出后,Client 必须回复确认(Confirmation),更可靠但较慢。

2.4 Profile fundamentals (配置文件基础)

原文 :This profile can be used over any physical link, using the Attribute Protocol L2CAP channel, known as the ATT Bearer.

• An ATT bearer is established using "Channel Establishment" as defined in Section 6.

• The profile roles are not tied to the Controller roles (i.e. Central or Peripheral).

  • 逐字翻译 :此配置文件可以在任何物理链路上使用,使用的是属性协议的 L2CAP 通道,称为 ATT 承载 (ATT Bearer)。
    • 配置文件角色不绑定于控制器角色(即中心设备 Central 或外围设备 Peripheral)。
  • 深度技术释义:这重申了角色的解耦。Central (手机) 发起物理连接,但在建立连接后,Central 也可以变成 GATT Server 被 Peripheral 读写。

原文:• On an LE Physical link, use of security features such as authorization, authentication and encryption are optional. On a BR/EDR physical link encryption is mandatory.

  • 逐字翻译:在 LE (低功耗) 物理链路上,使用诸如授权、认证和加密等安全功能是可选的。在 BR/EDR (经典蓝牙) 物理链路上,加密是强制性的。

原文:• Multi-octet fields within the GATT profile shall be sent least significant octet first (little-endian) with the exception of the Characteristic Value field. The Characteristic Value and any fields within it shall be little-endian unless otherwise defined in the specification which defines the characteristic.

  • 逐字翻译:GATT 配置文件中的多字节字段应优先发送最低有效字节(小端序 little-endian),但特性值 (Characteristic Value) 字段除外。特性值及其内部的任何字段都应为小端序,除非在定义该特性的规范中另有规定。
  • 深度技术释义 :这是开发抓包分析时的核心铁律。例如 Handle 是 0x0012,在空中抓包看到的就是 12 00。而具体的业务数据(Value)大端小端由业务协议自己定,但如果没有特别说明,默认也是小端。

2.5 Attribute Protocol (属性协议)

2.5.1 Overview (概述)

原文:The Opcode contains the specific command, request, response, indication, notification or confirmation opcode and a flag for authentication. The Attribute Parameters contain data for the specific command or request or the data returned in a response, indication, or notification.

  • 逐字翻译:操作码 (Opcode) 包含特定的命令、请求、响应、指示、通知或确认操作码,以及一个用于认证的标志。属性参数 (Attribute Parameters) 包含特定命令或请求的数据,或者在响应、指示或通知中返回的数据。
  • 深度技术释义 :任何 ATT 数据包(PDU)结构极为简单:1字节 Opcode + 若干字节 Parameters + 可选的 12字节签名

原文:An Attribute is composed of four parts: Attribute Handle, Attribute Type, Attribute Value, and Attribute Permissions. Figure 2.4 shows a logical representation of an Attribute.

  • 逐字翻译:一个属性由四个部分组成:属性句柄 (Attribute Handle)、属性类型 (Attribute Type)、属性值 (Attribute Value) 和属性权限 (Attribute Permissions)。图 2.4 展示了属性的逻辑表示。
  • 深度技术释义 (属性四大天王):
    1. Handle (2 字节) : 数据库主键,从 0x00010xFFFF
    2. Type (UUID): 说明这个属性是个啥(例如 0x2800 代表这是一个 Primary Service 声明)。
    3. Value: 实际的数据内容。
    4. Permissions : 读写门禁(如:只读、需配对加密后可写等)。注意:Client 无法通过空口读取 Permissions 本身,Client 只能通过尝试读/写然后看是否收到 Error Response 来推断权限。

原文:The Attributes are ordered by increasing Attribute Handle values. Attribute Handle values may begin at any value between 0x0001 and 0xFFFF. Although the Attribute Handle values are in increasing order, following Attribute Handle values may differ by more than one. That is to say there may be gaps between successive Attribute Handles.

  • 逐字翻译:属性按属性句柄值的递增顺序排列。句柄值可能以介于 0x0001 和 0xFFFF 之间的任何值开始。尽管句柄值是递增的,但后续的句柄值差异可能大于一。也就是说,连续的属性句柄之间可能存在间隙 (gaps)。
  • 深度技术释义:间隙 (Gaps) 的存在是为了给未来的固件升级预留空间,插入新的特性而不需要把后面的句柄全部往后推。
2.5.2 Attribute caching (属性缓存)

原文:Attribute caching is an optimization that allows the client to discover the Attribute information such as Attribute Handles used by the server once and use the same Attribute information across reconnections without rediscovery. With caching, time is saved and a significant number of packets need not be exchanged between the client and server.

  • 逐字翻译:属性缓存是一种优化,允许客户端仅发现一次服务器使用的属性信息(如属性句柄),并在重新连接时使用相同的属性信息,而无需重新发现。通过缓存,可以节省时间,并避免在客户端和服务器之间交换大量数据包。
  • 深度技术释义 :如果每次连蓝牙耳机都要花 3 秒钟做 Service Discovery(发送一堆 Read By Group Type 请求),体验将极差且极其耗电。缓存让 Client 记录下 Handle 0x001A -> 电池特性,下次连上直接去读 0x001A

原文:Some circumstances may cause servers to change the Attribute Handles used for services, perhaps due to a factory reset or a firmware upgrade procedure being performed... To support caching when a server supports changes in GATT based services, an indication is sent by the server to clients when a service is added, removed, or modified on the server.

  • 逐字翻译:在某些情况下(如出厂重置或固件升级),服务器可能会更改服务所使用的属性句柄... 为了在服务器支持 GATT 服务变更时支持缓存,当服务器上添加、删除或修改服务时,服务器会向客户端发送指示 (indication)。
  • 深度技术释义 :这就是著名的 Service Changed 特性(UUID: 0x2A05)。当 Server 结构变了,它会发送一个 Handle Value Indication,包含受影响的句柄范围。Client 收到后,必须把这段范围内的缓存清空并重新发现。
2.5.2.1 Robust Caching (强健缓存)

原文:Robust Caching is a feature where the server sends an ATT_ERROR_RSP PDU to the client if the server does not consider the client to be aware of a service change. If the Database Hash and Service Changed characteristics are both present on the server, then the server shall support the Robust Caching feature.

  • 逐字翻译:强健缓存 (Robust Caching) 是一项功能,如果服务器认为客户端不知道服务发生了变更,服务器会向客户端发送一个 ATT_ERROR_RSP PDU。如果服务器上同时存在数据库哈希 (Database Hash) 和服务变更 (Service Changed) 特性,那么服务器必须支持强健缓存功能。
  • 深度技术释义:在旧版蓝牙中,如果设备静默升级了固件,原先的 Handle 0x0010 变成了别的功能,Client 直接去写这个 Handle 会导致不可预知的后果。Robust Caching 是蓝牙 5.1 引入的安全网。

原文:From the perspective of a server, each connected client is either "change-aware" or "change-unaware" regarding changes in the database definitions.

  • 逐字翻译:从服务器的角度来看,对于数据库定义的更改,每个连接的客户端要么是"已感知更改 (change-aware)",要么是"未感知更改 (change-unaware)"。

原文:Whenever the server updates the database definitions, all connected clients become change-unaware. A change-unaware connected client becomes change-aware when it reads the Database Hash characteristic and then the server receives another ATT request from the client.

  • 逐字翻译:每当服务器更新数据库定义时,所有连接的客户端都会变成 change-unaware。当 change-unaware 的连接客户端读取 Database Hash 特性,并且服务器随后收到来自该客户端的另一个 ATT 请求时,该客户端就会变成 change-aware。

原文:If a client... is change-unaware then the server shall send an ATT_ERROR_RSP PDU with the Error Code parameter set to Database Out Of Sync (0x12)...

  • 逐字翻译:如果客户端... 是 change-unaware 的,那么当该客户端发送 ATT 请求时,服务器应发送一个错误码参数设置为"数据库不同步 (Database Out Of Sync, 0x12)"的 ATT_ERROR_RSP PDU。
  • 交互逻辑总结
    1. Server 更新固件。
    2. 手机不知情,用旧句柄发请求。
    3. Server 拦截请求,报错 0x12 (Out Of Sync)
    4. 手机意识到不对劲,立刻去读 Database Hash 获取新的数据库特征码,或者进行服务发现。
    5. 此时 Server 将手机标记为 change-aware,放行后续请求。
2.5.3 Attribute grouping (属性分组)

原文:GATT defines the grouping of attributes for three attribute types: <<Primary Service>>, <<Secondary Service>> and <<Characteristic>>.

  • 逐字翻译:GATT 为三种属性类型定义了属性的分组:「主要服务 (Primary Service)」、「次要服务 (Secondary Service)」和「特性 (Characteristic)」。
2.5.4 UUIDs

原文:All 16-bit UUIDs shall be contained in exactly 2 octets. All 128-bit UUIDs shall be contained in exactly 16 octets. All 32-bit UUIDs shall be converted to 128-bit UUIDs when the UUID is contained in an ATT PDU.

  • 逐字翻译:所有 16 位 UUID 必须精确包含在 2 个字节中。所有 128 位 UUID 必须精确包含在 16 个字节中。当 32 位 UUID 包含在 ATT PDU 中时,必须转换为 128 位 UUID。
  • 深度技术释义:SIG 官方定义的服务(如心率 0x180D)为了省空中带宽,可以用 16-bit(2字节)。厂商自定义的服务(如小米、苹果私有服务)必须用 128-bit。32-bit 不允许直接上空口传输,必须通过 Base UUID 补齐为 128-bit。

2.6 GATT Profile hierarchy (GATT 配置文件层级结构)

2.6.1 Overview (概述)

原文:The top level of the hierarchy is a profile. A profile is composed of one or more services necessary to fulfill a use case. A service is composed of characteristics or inclusions of other services. Each characteristic contains a value and may contain information about the value.

  • 逐字翻译:层级的顶层是配置文件 (profile)。一个配置文件由实现特定用例所需的一个或多个服务 (services) 组成。一个服务由特性 (characteristics) 或包含的其他服务组成。每个特性包含一个值 (value),并且可能包含有关该值的信息(即描述符 descriptor)。
  • 核心四层架构
    • Profile (最顶层业务集合):比如"心率监视器"。
    • Service (功能模块):心率监视器内部有"心率测量服务"和"设备信息服务"。
    • Characteristic (数据变量):设备信息服务内部有"制造商名称特性"。
    • Descriptor (变量注释):心率测量特性内部有一个描述符用于控制"是否开启通知"。
2.6.2 Service (服务) & 2.6.3 Included services (包含的服务)

原文:A service is a collection of data and associated behaviors to accomplish a particular function or feature. There are two types of services: primary service and secondary service.

  • 逐字翻译:服务是完成特定功能或特征的数据和相关行为的集合。服务有两种类型:主要服务和次要服务。

原文:An included service is a method to reference another service definition existing on the server into the service being defined.

  • 逐字翻译:包含的服务 (included service) 是一种将服务器上存在的另一个服务定义引用到正在定义的服务中的方法。
  • 深度技术释义 :类似编程语言中的 include 或指针。多个服务可以共享引用同一个通用服务(比如电池服务),避免冗余存储。
2.6.4 Characteristic (特性)

原文:A characteristic is a value used in a service along with properties and configuration information about how the value is accessed and information about how the value is displayed or represented.

  • 逐字翻译:特性 (Characteristic) 是服务中使用的值 (value),连同关于该值如何被访问的属性 (properties) 和配置信息,以及关于该值如何被显示或表示的信息(描述符)。

2.7 Configured Broadcast (配置广播)

原文:For LE physical links, Configured Broadcast is a method for a client to indicate to a server which Characteristic Value shall be broadcast in the advertising data when the server is executing the Broadcast mode procedure.

  • 逐字翻译:对于 LE 物理链路,配置广播 (Configured Broadcast) 是一种方法,供客户端指示服务器在执行广播模式程序时,应将哪个特性值广播在广播数据 (advertising data) 中。
  • 深度技术释义:这允许手机动态告诉传感器:"接下来请把你的温度数据直接塞进你的 BLE 广播包里"。这样周围所有的设备都不需要建立连接,直接扫描广播包就能读到温度。

生活案例 (全景)

超大连锁超市点单系统

  • Profile:整个连锁超市的运营标准。
  • Service:超市里的各个区域(生鲜区、日用品区)。
  • Characteristic:某个区域里的商品(排骨、苹果)。
  • Descriptor:商品的标签(比如"打折中"、"不可退换")。
  • Handle:商品的货架编号。买东西不认名字,只认货架号。
  • Caching (缓存):常客记得货架分布图,进门直奔目标。
  • Robust Caching (强健缓存):超市半夜把排骨和洗发水的货架互换了位置。第二天常客按照记忆去旧货架拿排骨,理货员会立刻拦住(Database Out of Sync 错误),要求常客先扫码看新的地图(Database Hash),然后才允许继续拿货。

有趣的问题

1. ble 设备在没有配对的情况下, 可以拿到 对应gatt 对应的值吗

这是一个非常经典且关键的蓝牙安全问题。答案是:可以,但前提是该属性(Attribute)的"权限(Permissions)"允许"无加密/无认证"访问。

为了让你深度理解这个逻辑,我们需要从 连接(Connection)、配对(Pairing) 和 属性权限(Permissions) 三者的关系拆解:

  1. 核心结论:连接 ≠ 配对
  • 连接 (Connection):只是建立了一条通信链路。只要你知道对方的 MAC 地址并能扫描到它,你就可以连上。连上后,你可以进行"服务发现",看到所有的 Service 和 Characteristic。
  • 配对 (Pairing):是为了加密这条链路。配对后会生成密钥,防止数据被中间人(MITM)窃听。
  1. 关键因素:属性权限 (Attribute Permissions)
    在 GATT 数据库中,每一个属性(比如"电量值"、"心率值")都有自己的 Permissions 字段。这个字段是在设备固件开发时写死的。

权限通常分为以下几类:

  • Readable / Writable:没有任何安全要求。(不配对也能拿到值)
  • Authentication Required:需要认证(即配对时输入过 PIN 码或确认过数字)。
  • Encryption Required:需要链路加密(必须配对并生成密钥)。
  • Authorization Required:需要授权(通常需要用户在手机弹窗点"允许")。
  1. 如果没配对,去读"加密属性"会发生什么?

    这是协议栈最精彩的部分(对应 Vol 3, Part G, Section 2.5.1):

    1. Client(手机):发送一个 ATT_READ_REQ(读请求)给 Server(设备)。
    2. Server:检查该 Handle 对应的 Permissions。如果权限要求 Encryption,但当前链路未配对,Server 绝对不会返回具体数值。
    3. Server:返回一个 ATT_ERROR_RSP,错误码通常是:
      0x05 (GATT_INSUF_AUTHENTICATION):认证不足。
      0x0F (GATT_INSUF_ENCRYPTION):加密不足。
    4. 手机系统(Android/iOS):当蓝牙栈收到这两个特定错误码时,会自动触发系统的配对流程(弹出配对对话框)。
  2. 常见的"免配对"数据

    为了方便快速识别,很多基础信息通常设置为"公开读":

  • Device Name (设备名称):通常在 GAP Service 中,公开。
  • Appearance (设备外观):公开。
  • Model Number (型号):在 Device Information Service 中,大部分也是公开的。
  1. 源码证据 (AOSP)
    在 Android 蓝牙栈 system/stack/gatt/gatt_sr.cc 中,处理读请求时会调用权限检查:
c 复制代码
// 伪代码逻辑
tGATT_STATUS gatt_sr_process_read_req(...) {
    // 1. 获取属性的权限
    uint16_t permissions = p_attr->permissions;

    // 2. 检查当前链路的安全状态 (tGATT_TCB)
    bool is_encrypted = p_tcb->is_encrypted;
    
    // 3. 权限判定
    if ((permissions & GATT_READ_ALLOWED) && !(permissions & GATT_READ_AUTH_REQUIRED)) {
        return GATT_SUCCESS; // 允许读取,不配对也能拿
    }
    
    if (permissions & GATT_READ_ENCRYPT_REQUIRED && !is_encrypted) {
        return GATT_INSUF_ENCRYPTION; // 拦截请求,报错触发配对
    }
}

总结

  • 公开数据:不配对也能拿。
  • 隐私数据:开发者会设置权限限制,不配对只能拿到"错误码",拿不到"真实值"。

安全提示:如果你在开发一款智能锁,如果把"开锁特性"的权限设为普通的 Writable,那么任何人只要连上你的蓝牙就能开锁,非常危险。必须设置为 Writable with Authentication & Encryption。

2. 同一个设备中, 可以有多个profile , 多个 service 多个 characteristices 吗, 他们的关系是什么样子?

这是一个非常核心的问题。简单来说:一个蓝牙设备就是一个"大商场(Profile 集合)",里面有多个"专柜(Service)",每个专柜里有多种"商品(Characteristics)"。

以下是它们之间的层级关系和 Mermaid 逻辑图:

  1. 层级关系拆解
  • Profile (配置文件/用例):
    • 定义:它是针对某个具体功能的"完整解决方案"。
    • 数量:一个设备可以运行多个 Profile。例如:一个蓝牙耳机可以同时支持 HFP (通话)、A2DP (音乐) 和 Battery Profile (电量显示)。
  • Service (服务):
    • 定义:它是 Profile 的组成部分,代表一个逻辑功能块。
    • 数量:一个 Profile 可以包含一个或多个 Service。一个设备的总数据库里会有很多个 Service 顺序排列。
  • Characteristic (特性/数据点):
    • 定义:它是 Service 里的最小逻辑数据单元。
    • 数量:一个 Service 通常包含多个 Characteristic。例如"电池服务"里有"当前电量百分比"和"电池状态"。
  • Descriptor (描述符/属性说明):
    • 定义:它是特性的"附件",用来描述特性。例如"开启/关闭通知的开关 (CCCD)"。

蓝牙设备 - GATT Server
Battery Profile - 电量显示用例
HID Profile - 蓝牙键盘用例
Battery Service
Characteristic: Battery Level
Characteristic: Battery Status
Value: 85%
Descriptor: CCCD - 开启/关闭电量通知开关
Human Interface Device Service
Characteristic: Key Report
Characteristic: Protocol Mode
Device Information Service
Device Information Service - 厂商/型号信息

  1. 核心要点总结

    复制代码
    1. 一对多关系:
        - 1 Device : N Profiles
        - 1 Profile : N Services
        - 1 Service : N Characteristics
    2. Service 的唯一性:
        - 在设备内部,所有的 Service 都是平铺在 Attribute Database 里的。
        - 每个 Service 都有一个唯一的 Handle Range (句柄范围)。比如:电池服务占用句柄 0x0010 到 0x0015。
    3. Service 的共享 (Inclusion):
        - 不同的 Profile 可能会共用同一个 Service。比如"设备信息服务 (DIS)"几乎在每个 Profile 里都会被用到。
    4. UUID 的作用:
        - Service UUID:告诉手机"我是电池服务"(0x180F)。
        - Characteristic UUID:告诉手机"这是电量百分比数据"(0x2A19)。
  2. 生活案例模拟

想象你买了一个 智能运动手表:

  • 设备 (Device):这块手表。
  • Profile 1 (心率监测):包含了 Heart Rate Service。
    • Characteristic:心率数值(每秒更新一次)。
  • Profile 2 (消息推送):包含了 Apple Notification Center Service (ANCS)。
    • Characteristic:通知内容、通知源。
  • Profile 3 (电量管理):包含了 Battery Service。
    • Characteristic:剩余电量。

总结:正是因为这种"套娃"式的层级结构,蓝牙协议才能够如此灵活地支持千变万化的应用场景。你可以随意组合 Service 来创造一个全新的 Profile。

3. 为何要定义 主要服务和次要服务, 服务和 特性不是两个不同的概念吗,怎么都可以归类到 the grouping of attributes 中?

怎么理解 下面的话:

c 复制代码
 GATT defines the grouping of attributes for three attribute types: <<Primary Service>>, <<Secondary Service>> and <<Characteristic>>.

这是一个非常深刻的问题,触及了 GATT 设计的最底层逻辑。要理解这段话,你需要从"物理存储(Attribute)"和"逻辑组织(Grouping)"两个维度来看。

核心结论 (Key Takeaways)

  1. 原子性:在 GATT 的底层数据库里,一切皆为属性 (Attribute)。服务声明是属性,特性声明是属性,数据值也是属性。
  2. 边界感:因为底层是平铺的列表,所以需要"带头大哥(Grouping Attribute)"来划定地盘。
  3. 主次之分:Primary Service 是对外可见的"大门",Secondary Service 是被引用的"暗门",目的是为了模块化复用。

  1. 为什么"服务"和"特性"都叫 Grouping of Attributes?

在 GATT 数据库里,并没有真正的"文件夹"或"对象"。数据库就是一个从 0x0001 到 0xFFFF 的线性列表。

  • 没有分组时:数据库就像一堆散落的零件。
  • 定义分组后:
    • Service Grouping:当一个属性的类型(UUID)是 0x2800 (Primary Service) 时,它就成了一个"地标"。从这个 Handle 开始,直到下一个 Service 声明出现之前,所有的内容都属于这个 Service。它把一堆相关的特性"圈"在了一起。
    • Characteristic Grouping:特性虽然在服务内部,但它也是一个小团体。一个特性包含:特性声明、数值属性、描述符属性。它把数据和数据的"说明书"圈在了一起。

线性数据库 - Handle 0x0001...N
包含
包含
包含
包含
包含
Handle 0x0001: UUID 0x2800 (Primary Service)
[组 1 起始]
Handle 0x0002: UUID 0x2803 (Characteristic)
[组 2 起始]
Handle 0x0003: UUID 0x2A19 (Battery Level Value)
Handle 0x0004: UUID 0x2902 (CCCD Descriptor)
Handle 0x0005: UUID 0x2800 (Next Service)
[组 1 结束 / 组 3 起始]


  1. 为何要区分主要服务 (Primary) 和次要服务 (Secondary)?

这是为了性能和逻辑复用。

主要服务 (Primary Service)

  • 地位:它是设备的主打功能(如:心率服务、电池服务)。
  • 可见性:当手机(Client)发起"发现所有服务"的请求时,Server 只会返回 Primary Service。
  • 作用:作为 App 接入的入口。

次要服务 (Secondary Service)

  • 地位:它是"辅助工具"或"模块化插件"。
  • 可见性:它是不可被直接扫描发现的。它必须被某个 Primary Service 通过 Include (引用) 机制拉进来。
  • 为什么要这么设计?
    • 模块化复用:假设你设计了一个极其复杂的"加密算法服务"。你可以把它写成 Secondary Service。然后你的"支付服务(Primary)"和"门禁服务(Primary)"都可以 Include 它。
    • 节省能耗:手机在扫描时,如果设备有 50 个辅助服务,手机不需要全部扫描一遍,只需扫描 3 个主要的 Primary Service 即可,大大缩短了服务发现的时间。

  1. 如何通俗理解这个结构?

我们可以用 "酒店" 来类比:

  1. Attribute (属性):酒店里所有的东西(一张床、一张纸、一个门牌号)都是属性。
  2. Primary Service (主要服务/套房):酒店里的"总统套房"。你在前台(手机扫描)能直接查到有这个房间。
  3. Grouping (分组):虽然总统套房里面有主卧、次卧、卫生间,但在前台看来,从 801 号房门开始,到 805 号房门结束,这 5 个房间号都属于"总统套房"这个组。
  4. Characteristic (特性/家具):房间里的"冰箱"。冰箱也是一个小组,它包含"冷藏层(数据值)"和"温度调节旋钮(描述符)"。
  5. Secondary Service (次要服务/客房清洁模块):这是一个通用的"清洁服务包"。它不单独对外售卖(前台搜不到),但"总统套房"和"标准间"的合同里都 Include 了这个清洁服务。

总结:

  • Service 定义的是"大功能块"的边界。
  • Characteristic 定义的是"具体数据点"的边界。
  • 它们都被归类为 Grouping,是因为在底层协议(ATT)中,手机是使用 Read By Group Type 这种指令来一次性拉取整个范围的数据的。如果没有这个 Grouping 定义,手机就得一个一个 Handle 去盲猜,效率极低。

4. 如何理解 Configured Broadcast

1. Configured Broadcast 广播的流程是什么 ?安全吗?

Configured Broadcast(配置广播) 的流程:它是先通过安全的点对点连接下达指令,然后开启公开的广播。

关于安全性,------原生广播包确实是明文的。但在车机等高安全场景下,协议栈和应用层有一套完整的组合拳来保证安全。

  1. Configured Broadcast 交互流程图

这个流程展示了从"加密配置"到"公开广播"的转换过程:
空中 监听者 (恶意第三方) 服务端 (如: 胎压传感器) 客户端 (如: 车机/手机) 空中 监听者 (恶意第三方) 服务端 (如: 胎压传感器) 客户端 (如: 车机/手机) 1. 建立安全通道 2. 配置广播参数 (在加密链路中进行) 告知 Server:请广播 Handle 0x0012 的值 3. 断开或维持连接,开启广播 载荷包含 Service Data: [UUID + 数据值] loop [每 100ms 一次] 发起 BLE 连接 (Connect) 启动配对/绑定 (Pairing/Bonding) 链路加密完成 (Encryption On) 发现 GATT 服务与特性 Write Descriptor (设置 Broadcast Bit = 1) 写入成功响应 (Write Response) 断开连接 (Optional) 发送 ADV_NONCONN_IND (广播包) 扫描并解析广播数据 抓取到广播包内容 (Raw Data)


  1. 关于安全性的深度分析:它安全吗?

结论:原生不安全,但"带锁"的载荷很安全。

如果你只是简单地把"门锁状态:开启"这几个字放在广播包里,任何拿手机装个 nRF Connect 的人都能看到。但在车机环境下,工程师会采取以下三重保护:

A. 载荷加密 (Payload Encryption)

虽然广播包本身是公开的(就像一个没封口的信封),但信封里的信件(数据)是加密的。

  • 在第一步"建立加密连接"时,车机和传感器已经通过配对交换了长期密钥 (LTK) 或 会话密钥。
  • 传感器在广播数据时,会使用这个密钥对 Characteristic Value 进行加密(如 AES-CCM)。
  • 结果:黑客抓到了包,看到的是一串乱码 0xAF 32 D1...,只有拥有密钥的车机才能解开。

B. 防重放攻击 (Anti-Replay / Counter)

黑客可能会想:我虽然解不开你的包,但我把你开锁时的广播信号录下来,等你走后再原样放一遍(重放攻击),车不就开了吗?

  • 对策:广播包里会带一个 Rolling Counter (滚动计数器) 或 Timestamp (时间戳)。
  • 结果:车机收到广播后会检查:"这个计数器是 101,但我上次收到的已经是 105 了,这个包是过期的",从而拒绝执行。

C. 可变地址 (Private Resolvable Address)

  • 为了防止黑客长期跟踪某个传感器的 MAC 地址来判断车主位置,设备会开启 Privacy 机制。
  • 结果:传感器的 MAC 地址每隔 15 分钟变一次,只有配过对的车机才能通过特定的算法(IRK)算出这个设备到底是谁。

  1. AOSP 源码中的实现线索

在 Android 蓝牙栈中,当你尝试配置广播属性时,底层 gatt_sr.cc 会检查该特性的 properties:

c 复制代码
// system/stack/gatt/gatt_sr.cc 中的逻辑逻辑
if (p_attr->properties & GATT_CHAR_PROP_BIT_BROADCAST) {
    // 允许客户端通过修改 Client Characteristic Configuration 
    // 来触发 Server 切换到广播模式
    // 最终会调用到 Controller 层的 HCI_LE_Set_Advertising_Data
}

总结建议

Configured Broadcast 的安全性不在于"别人看不看得见",而在于:

  1. 谁能配置它(必须是加密连接后的合法客户端)。
  2. 谁能看懂它(必须拥有提前交换的密钥)。

在车机开发中,如果你要使用这个功能,绝对不能发原始明文数据,必须在应用层(App Layer)手动加上一层加密和校验。

2. 车机平台都有哪些使用场景

Configured Broadcast(配置广播) 在车机(Automotive)环境下是一个非常强大但常被忽视的功能。它的核心逻辑是:"Client(如车机)告诉 Server(如传感器):请把你当前的某个数据直接塞进你的广播包里发出来,不要等我连你。"

在车机这种追求低延迟、多端监听、抗干扰的复杂场景下,它的使用价值极高。以下是四个典型的车机使用场景:


  1. TPMS(胎压监测系统)的"多端共享"
    这是最经典的使用场景。
  • 痛点:传统的 BLE 胎压计通常需要与车机建立连接(Connection)才能读取数据。但连接是"一对一"的,如果胎压计连了车机,司机的手机 App 就连不上了。
  • Configured Broadcast 方案:
    • 车机作为 Client,配置 4 个轮胎传感器(Server):"请持续广播你们的压力值和温度值。"
    • 效果:轮胎传感器开始疯狂发送包含胎压数据的广播包。此时,车机主机可以实时看到胎压,站在车外的司机打开手机 App 也能同时看到胎压,甚至路边的维修设备也能抓到数据。不需要任何建立连接的握手时间,也不受连接数量限制。
  1. 迎宾系统与数字钥匙的"快速响应"
  • 痛点:当你靠近汽车时,汽车需要判断你的位置并自动开启迎宾灯或解锁。如果依靠"连接 -> 发现服务 -> 读取 RSSI -> 解锁",整个流程可能有 1-2 秒的延迟,用户会感到"卡顿"。
  • Configured Broadcast 方案:
    • 车机的主控模块(BCM)配置车门把手或后备箱的 BLE 模块:"当检测到特定授权特征时,立即广播'允许进入'的加密挑战码。"
    • 效果:手机端不需要发起连接请求(Connect Request),只需要监听广播包。一旦在广播包中解析出加密的挑战码,立即通过广播回复。这种"无连接交互"能将响应速度提升到毫秒级,实现真正的"无感进入"。
  1. 后排娱乐与多乘客状态同步
  • 痛点:现在的车机通常支持多屏互动。如果后排两个屏幕、三个乘客的手机都要实时同步空调温度、音乐进度,车机的蓝牙芯片很难同时维持 5-6 个稳定的连接(连接越多,带宽越低,稳定性越差)。
  • Configured Broadcast 方案:
    • 空调控制模块或媒体中心作为 Server,被配置为:"每 100ms 广播一次当前的温度设定和播放进度。"
    • 效果:车内所有的平板电脑、手机、后排屏幕只需要处于"扫描(Scanning)"模式。它们像听收音机一样,同时接收这条广播。这种"一对多"的下发方式极大地节省了蓝牙芯片的功耗和带宽资源。
  1. 活体检测与紧急预警(儿童遗留提醒)
  • 痛点:车内生命体征监测(如毫米波雷达或压力传感器)在检测到后排有儿童遗留时,必须第一时间发出警报。如果此时车机系统已经休眠或正在建立连接,可能会耽误时间。
  • Configured Broadcast 方案:
    • 传感器被预设为:一旦触发报警状态,立即切换到广播模式,将"报警代码"写入广播包。
    • 效果:即便司机的手机还没连上车,只要在蓝牙覆盖范围内,手机系统就能通过监听特定的 Service Data 直接触发报警弹窗。

总结:为什么车机需要它?

特性 传统连接 (GATT Connection) 配置广播 (Configured Broadcast) 车机价值
时延 高 (需 3 步握手 + 服务发现) 极低 (扫到即读到) 紧急报警、数字钥匙秒开
终端数量 有限 (通常 7 个以内) 无限 全家手机同时看胎压、看视频进度
功耗 中 (需维持链路心跳) 极低 (发完就睡) 传感器电池可用 5-10 年
鲁棒性 弱 (易受车内金属电磁干扰掉线) (包丢了等下一个,不影响状态) 在复杂电磁环境下更稳定
技术本质分析:
Configured Broadcast 实际上是把 GATT 的灵活性(由 Client 动态决定看什么数据)和 Advertising 的高效性(一对多、无连接)结合在了一起。在 AOSP 源码中,这通常对应于 btgatt_db_element_t 中对广播属性的配置。
相关推荐
嵌入式小企鹅2 天前
蓝牙学习系列(八):BLE L2CAP 协议详解
网络·学习·蓝牙·ble·协议栈·l2cap
Vis-Lin3 天前
BLE 协议栈:L2CAP 信道详解
网络·物联网·网络协议·蓝牙·iot·ble
林政硕(Cohen0415)3 天前
V821 内置蓝牙 BLE 适配
蓝牙·ble·v821
墨染倾城殇4 天前
Nordic nRF54115 + BLE 蓝牙6.0:物联网多协议互联
物联网·蓝牙模块·ble·nordic·蓝牙6.0·nrf54115
嵌入式小企鹅9 天前
蓝牙学习系列(七):BLE GATT 数据模型详解
学习·蓝牙·ble·蓝牙协议栈·蓝牙开发·gatt
飞易通11 天前
Realtek RTL8761CTV 集成蓝牙5.3 LE Audio 双模音频方案覆盖多场景无线应用
音视频·ble·le audio·蓝牙5.3·realtek
Vis-Lin13 天前
BLE 协议栈:HCI ACL 数据详解
网络·物联网·网络协议·蓝牙·iot·ble
墨染倾城殇19 天前
BLE为蓝牙Mesh网络筑基:全屋智能家居怎样同时省电又连片可控?
智能家居·ble·蓝牙mesh组网
deepwater_zone24 天前
实测BLE的最小连接间隔
ble