若想在设备上实现Central角色的功能,主要有以下步骤:
1.需要创建一个 CBCentralManager
对象
2.搜索周围广播的设备
3.与一个外设进行连接,并探索外设提供的服务
4.向外设发送读写characteristic的请求,如果有需要订阅characteristic值得更新,来跟踪数据的变化。
myCentralManager =
[[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
[myCentralManager scanForPeripheralsWithServices:nil options:nil];
//CBCentralManager代理方法
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI {
NSLog(@"Discovered %@", peripheral.name);
self.discoveredPeripheral = peripheral;
...
}
选择需要的外设并建立连接,并设置外设的代理为self,用于与外设的交互
[myCentralManager connectPeripheral:peripheral options:nil];
- (void)centralManager:(CBCentralManager *)central
didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"Peripheral connected");
peripheral.delegate = self;//
...
}
搜索外设提供的服务并读取数据
[peripheral discoverServices:nil];
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error {
for (CBService *service in peripheral.services) {
NSLog(@"Discovered service %@", service);
...
}
...
}
停止搜索外设
[myCentralManager stopScan];
从服务中获取特征
NSLog(@"Discovering characteristics for service %@", interestingService);
[peripheral discoverCharacteristics:nil forService:interestingService];
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error {
for (CBCharacteristic *characteristic in service.characteristics) {
NSLog(@"Discovered characteristic %@", characteristic);
...
}
...
}
从特征中读取数据
NSLog(@"Reading value for characteristic %@", interestingCharacteristic);
[peripheral readValueForCharacteristic:interestingCharacteristic];
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
NSData *data = characteristic.value;
// parse the data as needed
...
}
如果需要获取动态变化的特征,需要订阅特征变化的通知
[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error) {
NSLog(@"Error changing notification state: %@",
[error localizedDescription]);
}
...
}
向外设写数据
NSLog(@"Writing value for characteristic %@", interestingCharacteristic);
[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic
type:CBCharacteristicWriteWithResponse];
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error) {
NSLog(@"Error writing characteristic value: %@",
[error localizedDescription]);
}
...
}
需要注意一下事项:
由于蓝牙是共享无线电硬件设备的来发送和接受数据的,可能其他无线通信也需要使用无线电硬件,例如Wifi,或者其他App也正在使用蓝牙,因此,应该尽量避免长时间使用无线电。可以通过以下方式来对其进行优化
1.只在需要时进行蓝牙外设搜索,当建立与外设的连接后,应停止搜索。调用stopScan方法
2.因为远程外设每秒会广播多次,当使用 scanForPeripheralsWithServices:options:方法搜索可以外设的时候,
系统默认在一次搜索事件中忽略那些相同的外设。如果设置option为CBCentralManagerScanOptionAllowDuplicatesKey,那么每当中心设备受到一个外设的广播时,就会产生一次发现事件。因此应尽量避免使用这个option。
3.准确的获取外设的数据,而不是搜索外设提供的所有的数据,[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];
4.当不再获取数据时,取消对数据的订阅,断开与外设的连接
setNotifyValue:NO forCharacteristic:
[myCentralManager cancelPeripheralConnection:peripheral];
重连外设
Figure 5-1 A sample reconnection workflow