Service UUID — 是一个唯一的16位或128位蓝牙低功耗(BLE)标识符,用于明确定义设备上的功能性服务。Bluetooth SIG为常见服务分配了标准16位UUID,例如Battery Service(0x180F)、Device Information(0x180A)和Heart Rate(0x180D),这简化了跨平台兼容性。根据Bluetooth Core Specification 5.4(2023),第三方开发者的自定义服务必须使用128位UUID,其格式无需中央注册表即可保证全局唯一性。正确声明Service UUID是外设设备上GATT服务器正常工作的第一步。
要点
Service UUID — 是分配给蓝牙低功耗GATT服务以使其能够被其他设备唯一识别的标识符。在BLE架构中,每个服务代表一组由共同功能连接起来的逻辑特征组。例如,Battery Service服务包含Battery Level特征,用于传输当前电池电量水平。
Bluetooth SIG(特别兴趣小组)管理分配给最常见服务的标准16位UUID注册表。这使得不同制造商的设备无需预先配置即可相互识别服务。任何品牌的健身追踪器都可以声明UUID为0x180D的Heart Rate Service,任何智能手机都会理解这是心率服务。
根据Bluetooth Core Specification 5.4(2023),16位UUID范围(0x0000–0xFFFF)分为两部分:0x0001至0xFFFE — Bluetooth SIG标准服务,0xFFFF为保留。如果开发者需要SIG注册表中不存在的唯一服务,则使用128位UUID。
标准UUID和自定义UUID之间的区别不仅在于长度:16位UUID节省广播包的无线时间,因为它们以2字节而非16字节传输。对于广播包大小有严格限制(最多31字节)的设备来说,这一点至关重要。
标准16位UUID涵盖BLE设备的主要类别:医疗传感器、健身追踪器、可穿戴电子设备和配件。如果设备实现标准功能 — 建议开发者使用Bluetooth SIG注册表中相应的UUID以获得最大兼容性。
以下是一些标准服务UUID的示例:
| UUID(十六进制) | 服务名称 | 用途 |
|---|---|---|
| 0x1800 | Generic Access | 访问管理、设备名称、外观 |
| 0x180A | Device Information | 制造商、型号、序列号、软件版本 |
| 0x180D | Heart Rate | 脉搏测量、传感器位置、电池电量 |
| 0x180F | Battery Service | 电池电量百分比 |
| 0x181A | Environmental Sensing | 温度、湿度、压力、光照 |
| 0x181C | User Data | 年龄、体重、身高、性别、静息脉搏 |
自定义128位UUID在设备提供独特功能时是必需的。例如,智能锁制造商创建自己的Lock Control服务,UUID格式为XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX。这样的UUID保证不会与其他服务冲突,因为128位值的空间几乎是无穷无尽的。
128位UUID以标准UUID RFC 4122格式编写:八个十六进制字符,连字符,四个,连字符,四个,连字符,四个,连字符,十二个字符。BLE使用的版本中,Bluetooth SIG UUID的基础部分具有固定位。
Bluetooth SIG定义了基础UUID:0000XXXX-0000-1000-8000-00805F9B34FB。对于标准16位服务,UUID值将替换到此掩码中:例如,0x180F变为0000180F-0000-1000-8000-00805F9B34FB。自定义服务使用完全独立的由开发者生成的UUID。
创建自定义UUID时,可以使用任何UUID生成器(UUID v4)。随机UUID v4提供122位熵,使得冲突几乎不可能。不要使用修改后的Bluetooth SIG基础UUID版本用于自定义服务 — 这违反了规范。
声明服务带UUID是在创建GATT服务器时在Peripheral端执行的。在iOS中使用Core Bluetooth,在Android中使用android.bluetooth.le。让我们来讨论这两种方法。
在Swift中,通过CBMutableService指定UUID创建服务,然后通过CBMutableCharacteristic向其添加特征。
import CoreBluetooth
// 标准16位UUID
let batteryServiceUUID = CBUUID("180F")
// 自定义128位UUID
let customServiceUUID = CBUUID("E20A39F4-73F5-4BC4-A12F-17D1AD07A961")
let service = CBMutableService(
type: customServiceUUID,
primary: true
)
// 添加特征
service.characteristics = [characteristic]
// 通过peripheralManager发布服务
peripheralManager.add(service)
在Android中,通过BluetoothGattServer和BluetoothGattService注册服务。UUID作为字符串在java.util.UUID.fromString中传递。
import android.bluetooth.*;
// 自定义服务UUID
private static final UUID CUSTOM_SERVICE_UUID =
UUID.fromString("E20A39F4-73F5-4BC4-A12F-17D1AD07A961");
BluetoothGattService service = new BluetoothGattService(
CUSTOM_SERVICE_UUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY
);
// 添加特征
service.addCharacteristic(characteristic);
// 在GATT服务器上注册
gattServer.addService(service);
按Service UUID扫描允许Central查找提供所需服务的设备,而无需连接到所有检测到的Peripheral。BLE广播包可以包含服务UUID列表,这使得Central能够在扫描阶段过滤设备。
在iOS中,CBCentralManager使用按服务UUID的过滤器扫描设备。这降低了功耗并加快了所需设备的检测速度。
import CoreBluetooth
let centralManager = CBCentralManager()
func scanForHeartRateMonitor() {
let services: [CBUUID] = [
CBUUID("180D") // Heart Rate Service
]
centralManager.scanForPeripherals(
withServices: services,
options: nil
)
}
// 委托仅接收Heart Rate Service设备
func centralManager(
_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any],
rssi RSSI: NSNumber
) {
// peripheral仅具有UUID 0x180D的设备
}
在Android中,按UUID过滤也通过ScanFilter.Builder支持。这是一种无需连接到每个设备即可缩小搜索范围的有效方法。
import android.bluetooth.le.*;
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(
new ParcelUuid(
UUID.fromString("0000180D-0000-1000-8000-00805F9B34FB")
)
)
.build();
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
scanner.startScan(
Collections.singletonList(filter),
scanSettings,
scanCallback
);
一个BLE设备可以同时声明多个服务。例如,健身手环可以包含Battery Service(0x180F)、Heart Rate Service(0x180D)和用于与云端数据同步的自定义服务。每个服务都有自己的UUID和自己的一组特征。
在有多个服务的情况下,重要的是要考虑广播包的限制。BLE广播包最多可以包含31字节的数据。如果服务UUID占用太多空间,其中一些可能无法放入广播包。在这种情况下,使用扫描响应(scan response)— 根据Central的请求发送的第二个数据包。
根据Bluetooth Core Specification 5.4(2023),单个GATT服务器上主要服务的最大数量不受规范限制,但实际上受设备内存和性能要求的限制。对于具有256 KB闪存的嵌入式设备,建议不超过5到10个服务。
常见问题
16位UUID由Bluetooth SIG为标准服务保留,在广播包中占用2字节。128位UUID用于自定义服务,占用16字节。选择取决于服务类型:标准功能使用16位UUID,独特功能使用128位UUID。
使用UUID v4 — 由在线工具、终端命令uuidgen或您的编程语言API生成的随机UUID。示例:Java中的UUID.fromString(UUID.randomUUID().toString())或Swift中的UUID()。
不需要,注册不是必须的。Bluetooth SIG仅注册16位UUID。自定义128位UUID由开发者独立生成,并凭借巨大的地址空间(2^128种组合)保证唯一性。
是的,标准GATT服务可以包含无限数量的特征。例如,Battery Service可以包含Battery Level(0x2A19)和Battery Power State(0x2A1A)。每个特征都有自己的UUID和属性集。
如果UUID匹配,Central将无法在没有额外信息的情况下区分一个服务和另一个服务。随机UUID v4冲突的概率微乎其微 — 约为5.3 × 10^−37。请使用随机UUID生成器,不要复制示例中的UUID。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。