ios蓝牙开发学习笔记(二)central角色的实现

本文转载自:http://blog.csdn.net/swibyn/article/details/52096321

Performing Common Central Role Tasks

central角色的实现

central 角色需要完成的几件事情,如搜索,连接,与peripheral交互数据。
peripheral 角色同样需要完成几件事情,如,发布和广播服务,响应读,写,订阅请求

本章中,你将学习如何完成central端的功能。
1,创建central manager 对象
2,发现和连接正在广播的peripheral
3,浏览peripheral的数据
4,发送读和写请求到peripheral设备
5,订阅characteristic的值

下一章你将学习如何开发peripheral角色的功能

Starting Up a Central Manager

创建Central manager对象

myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];'

在这里self设置成central角色的代理。dispath queue设置为nil,意味着central事件将交由main queue处理。

创建central manager时,会触发centralManagerDidUpdateState: 代理方法。你必须实现这个代理。

Discovering Peripheral Devices That Are Advertising

搜索正在发送广播的peripheral

[myCentralManager scanForPeripheralsWithServices:nil options:nil];

注意:如果第一个参数设置成nil,那么centralmanager会返回所有被发现的peripherals,在实际应用中,你应该给他赋值 CBUUID 对象数组。这样只有有广播这些uuid服务的peripheral才会被返回,

一旦发现peripheral,将触发
centralManager:didDiscoverPeripheral:advertisementData:RSSi:
代理方法,如果你想连接这个peripheral,请使用强引用变量引用它,这样系统就不会释放掉它。

  • (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
    advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    NSLog(@"Discovered %@", peripheral.name);
    self.discoveredPeripheral = peripheral;
    ...

如果你想连接多个设备,你可以使用NSArray来管理他们。不管什么情况,一旦你找到所有你想要的设备,你应该停止扫描以便节省电量。

[myCentralManager stopScan];

Connecting to a Peripheral Device After You’ve Discovered It

连接peripheral

[myCentralManager connectPeripheral:peripheral options:nil];

如果连接成功,则会触发centralManager:didConnectPeripheral:代理方法,与之通讯之前,你需要为它设置代理

  • (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Peripheral connected");
    peripheral.delegate = self;
    ...

Discovering the Services of a Peripheral That You’re Connected To

查询peripheral的服务

建立连接之后,就可以查询数据,第一步就是查询有哪些services。因为广播包有大小限制,在广播中可能没有显示全部的服务信息,这里你可以使用discoverServices: 来查询所有的services。

[peripheral discoverServices:nil];

注意:实际开发中,你不应该传值nil,因为这样做会返回所有的services,包括那些你不需要的services,这样做会浪费时间和电量。所以你应该传递你需要的uuids。

查找到所有的服务会触发peripheral:didDiscoverServices:代理方法

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    for (CBService *service in peripheral.services) {
    NSLog(@"Discovered service %@", service);
    ...
    }
    ...

Discovering the Characteristics of a Service

查找characteristics

发现service之后,下一步就是查找characteristics

NSLog(@"Discovering characteristics for service %@", interestingService);
[peripheral discoverCharacteristics:nil forService:interestingService];

注意:实际开发中,不要传nil,这样做会返回所有的characteristics,包括那些你不感兴趣的characteristics。这样做即浪费时间又损耗电量。所以你应该传你需要的uuids的值

查找到characteristics之后,会触发peripheral:didDiscoverCharacteristicsForService:error:代理方法

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    for (CBCharacteristic *characteristic in service.characteristics) {
    NSLog(@"Discovered characteristic %@", characteristic);
    ...
    }
    ...

Retrieving the Value of a Characteristic

获取数据

一个characteristic只包含一种信息数据。比如恒温service下的温度characteristic只包含当前温度值,你可以通过读取或订阅来获得这个值。

Reading the Value of a Characteristic

读取characteristic的数据

NSLog(@"Reading value for characteristic %@", interestingCharacteristic);
[peripheral readValueForCharacteristic:interestingCharacteristic];

获取到数据后peripheral调用peripheral:didUpdateValueForCharacteristic:error:代理方法

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    NSData *data = characteristic.value;
    // parse the data as needed
... 

注意:并不是所有的characteristic都是可读的,你可以通过 characteristic的 proterties属性是否包含CBCharacteristicPropertyRead 常量来判断是否可读。在读一个不可读的characteristic的数据值,会在代理方法的error参数中体现异常信息

Subscribing to a Characteristic’s Value

订阅characteristic的值

虽然通过readValueForCharacteristic: 可以有效获取静态值,但如果值是动态改变的,则最好使用订阅的方法。当值变化时,自动获得通知。
设置订阅

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

订阅的时候peripheral会调用peripheral:didUpdateNotificationStateForCharacteristic:error: 代理方法。如果订阅失败了,也可以通过这个方法查询失败的原因

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
    NSLog(@"Error changing notification state: %@",[error localizedDescription]);
    }

注意:并不是所有的characteristics都可以订阅,可以通过检查characteristic的properties属性是否包含CBCharacteristicPropertyNotify 或 CBCharacteristicPropertyIndicate常量来判断是否可订阅

Writing the Value of a Characteristic

写数据

有时也是需要写数据的,比如恒温器,你需要设置目标温度。如果characteristic是可写的,那么你就可以调用writeValue:forCharacteristic:type: 方法来写入数据。如下:

NSLog(@"Writing value for characteristic %@", interestingCharacteristic);
[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic type:CBCharacteristicWriteWithResponse];

当你写数据时,你可以标明写类型。上例中,写类型是CBCharacteristicWriteWithResponse, 这种情况下,不管有没有写成功,peripheral都会通过代理通知你。你需要实现这个方法以便处理异常情况。

  • (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
    NSLog(@"Error writing characteristic value: %@",[error localizedDescription]);
    }
    ...

如果你设置的写类型是CBCharacteristicWriteWithoutResponse, 那么写操作会以更有效的方式执行,但不保证写成功,并且不会有报告。peripheral不会通知任何回调。

注意:characteristic可能只支持特定的写类型,或不支持写操作。你可以通过检查properties属性是否包含CBCharacteristicPropertyWriteWithoutResponse 或 CBCharacteristicPropertyWrite 来判断。

推荐阅读更多精彩内容