上一章谈到了当设备作为 Central 时,搜索、连接、读写的一些基本操作。几乎就是翻译了官方 API,除此之外,API 中还提到了一些枚举,以及在实际运用当中一些可以优化的点,这些都将在本文中一一介绍(就我目前遇到的需求而言)。
CBUUID
CBUUID
对象是用于 BLE 通信中 128 位的唯一标示符。Peripheral 的 Service,Characteristic,Characteristic descriptor 都包含这个属性。这个类包含了一系列生成 UUID 的方法。
UUID 有 16 位的,也有 128 位的。其中 SIG 组织提供了一部分 16 位的 UUID,这部分 UUID 主要用于公共设备,例如有个用蓝牙连接的心率监测仪,如果是用的公共的 UUID,那么无论谁做一个 app,都可以进行连接,因为它的 UUID 是 SIG 官方提供的,是公开的。如果公司是要做一个只能自己的 app 才能连接的设备,那么就需要硬件方面自定义 UUID。(关于这方面,包括通信的 GATT 协议、广播流程等详细介绍,可以看 GATT Profile 简介 这篇文章。讲得比较详细,能在很大程度上帮助我们理解 BLE 通信。)
CBUUID
类提供了可以将 16 位 UUID 转为 128 位 UUID 的方法。下面的代码是 SIG 提供的 16 位的心率 Service UUID 转为 128 位 UUID 的方法:
CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString:@"180D"];
如果需要获取 NSString
形式的 UUID,可以访问 CBUUID
的 UUIDString
只读属性。
检查设备是否能作为 Central
初始化 CBCentralManager
的时候,传入的 self
代理会触发回调 centralManagerDidUpdateState:
。在该方法中可通过 central.state
来获得当前设备是否能作为 Central。 state
为 CBCentralManagerState
枚举类型,具体定义如下:
typedef NS_ENUM(NSInteger, CBCentralManagerState) { CBCentralManagerStateUnknown = 0, CBCentralManagerStateResetting, CBCentralManagerStateUnsupported, CBCentralManagerStateUnauthorized, CBCentralManagerStatePoweredOff, CBCentralManagerStatePoweredOn, };
只有当 state == CBCentralManagerStatePoweredOn
时,才代表正常。
检查 Characteristic 访问权限
如果不检查也没事,因为无权访问会在回调中返回 error,但这毕竟是马后炮。如果有需要在读写之前检测,可以通过 Characteristic 的 properties
属性来判断。该属性为 CBCharacteristicProperties
的 NS_OPIONS
。
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) { CBCharacteristicPropertyBroadcast = 0x01, CBCharacteristicPropertyRead = 0x02, CBCharacteristicPropertyWriteWithoutResponse = 0x04, CBCharacteristicPropertyWrite = 0x08, CBCharacteristicPropertyNotify = 0x10, CBCharacteristicPropertyIndicate = 0x20, CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40, CBCharacteristicPropertyExtendedProperties = 0x80, CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100, CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200 };
多个权限可以通过 |
和 &
来判断是否支持,比如判断是否支持读写:
BOOL isSupport = characteristic.properties & (CBCharacteristicPropertyRead | CBCharacteristicPropertyWrite)
写入后是否回调
在写入 Characteristic 时,可以选择是否在写入后进行回调。调用方法和枚举常量如下:
[self.connectedPeripheral writeValue:data forCharacteristic:connectedCharacteristic type:CBCharacteristicWriteWithResponse];
typedef NS_ENUM(NSInteger, CBCharacteristicWriteType) { CBCharacteristicWriteWithResponse = 0, CBCharacteristicWriteWithoutResponse, };
回调方法为:
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
所以即使没有判断写入权限,也可以通过回调的 error 来判断,但这样比起写入前判断更耗资源。