CoreBluetooth第一节:Performing Common Central Role Tasks(执行常见的核心端任务)

概述翻译在这里
本文官方文档链接

前言

这几篇文章里Central 和 Peripheral.您可以理解成核心设备和外部设备.

Service是指实现一个函数或者功能的设备(或者设备的一部分)的数据采集和相关行为的集合。例如,一个心率监听器的Service可能包含从监听心率传感器采集的心率数据。

Service本身由Characteristic或者其他被包含的Service所组成。Characteristic提供了更多有关Peripheral的Service中的详细内容。例如,刚才描述的心率Service中可以包含一个用来描述该设备的心率传感器所记录身体位置的Characteristic或者包含发送测量心率数据的Characteristic

这是概述中的描述.个人理解service就是自己定义的数据包.


在低功耗蓝牙交互中,扮演Central的设备需要执行许多常见的任务 - 例如,发现并连接可用Peripheral,与Peripheral提供的数据交互.相反的,Perpheral设备也执行许多常见,但与Central不同的任务 - 例如,发布并广播service,并且响应与之连接的Central的 ,订阅的请求.
在本章中,你将会学到在Central端如何使用CB框架来执行最常见的蓝牙低功耗任务.如下的基于代码的样例会帮助你在Central端开发你的app,你将学到如何:

1.启动central manager对象
2.搜索并连接发送广播的Perpheral设备
3.建立连接之后与Peripheral设备进行数据交换
4.向Peripheral设备发送一个characteristic读写请求
5.订阅一个characteristic的值(该值更新会发送通知)

在下一章节中,你将学到用你的本地设备作为外设来开发app.
在这一章节中的代码样例是简单抽象的,你需要在实际开发中做出实际更改,更多关于Central端相关话题 - 包括小提示与技巧以及最佳实践方案包含在如下章节中,Core Bluetooth Background Processing for iOS Apps 和 Best Practices for Interacting with a Remote Peripheral Device.


启动Central Manager

CBCentralManager 对象在CoreBluetooth面向对象中代表本地Central设备,你必须在执行蓝牙低功耗交互之前分配内存并初始化它.你可以调用initWithDelegate:queue:options方法启动,如下:

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

在本例中,self设置成代理对象来接收Central端事件.通过指定队列为nil,central manager指定使用主队列.
当你创建一个central manager,central manager调用centralManagerDidUpdateState:代理方法.你必须实现该代理方法来确保低功耗蓝牙设备在Central设备中可用.更多关于代理方法的信息


发现广播中的Peripheral设备

Central端的首要执行任务是发现你的app可以连接的peripheral设备.在前面提到的”Central 发现并连接广播中的 Peripheral”一节中,peripheral端通过广播来让其他设备监听到他的存在.你可以调用scanForPeripheralsWithServices:options:方法:

[myCentralManager scanForPeripheralsWithServices:nil options:nil];

Note:如果第一个参数为nil,central manager 返回所有检测到可用的peripheral.实际上,你应该制定一个CBUUID对象的数组,每一个代表一个peripheral广播的service的通用唯一标识符(UUID).当你制定了service UUIDs的数组,central manager 只返回发送这些services的peripheral,允许你只扫描你感兴趣的设备.UUIDs和CBUUID对象的更多细节在这里.

在调用scanForPeriperalsWithServices:options:来发现可用peripherals后,central manager每扫描到一个peripheral就会调用centralManager:didDiscoverPeripheral:advertisementDate:RSSI:.返回的是CBPeripheral对象.如下所示,你可以实现该代理方法来列举发现的peripheral:

- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI {

    NSLog(@"Discovered %@", peripheral.name);
    ...

当发现想要连接的peripheral,停止扫描其他设备来节约电量.

    [myCentralManager stopScan];
    NSLog(@"Scanning stopped");

发现Peripheral后连接它

在找到了你需要连接的设备后,调用connectPeripheral:options:发送连接请求.简单的调用这个方法并指定你想连接的设备,像这样:

[myCentralManager connectPeripheral:peripheral options:nil];

假设连接成功,central manager 调用centralManager:didConnectPeripheral:代理方法,你可以在这里打印连接情况:

- (void)centralManager:(CBCentralManager *)central
  didConnectPeripheral:(CBPeripheral *)peripheral {

    NSLog(@"Peripheral connected");
    ...

在开始和Peripheral交互之前,设置peripheral的代理来确保他会收到正确的回调:

peripheral.delegate = self;

监听连接的peripheral发送的Service

在与peripheral建立连接后就可以探索(explore)它的数据.探索的第一步就是发现peripheral广播的可用services.因为peripheral广播的数据量有大小限制,你可能发现一个peripheral有更多未广播出来的services.你可以调用CBPeripheral类的discoverServices来发现peripheral提供的所有services:

[peripheral discoverServices:nil];

Note:实际开发中将不会传nil作为参数,因为一个peripheral可能会包含多个你需要的service,发现全部的service可能会浪费电池寿命并浪费时间.更应该倾向于指定已知要用到的UUIDs.

当指定的service被发现后,peripheral(连接的CBPeripheral对象)调用peripheral:didDiscoverServices:代理.CB会创建一个存储CBService对象(从peripheral设备上发现的)的数组.你可以实现该代理来访问发现的service:

- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error {

    for (CBService *service in peripheral.services) {
        NSLog(@"Discovered service %@", service);
        ...
    }
    ...

发现Service的Characteristics(特征)

如果你找到了需要的service,下一步就是探索该service提供的所有characteristic.调用CBPeripheral类的discoverCharacteristics:forService:方法获取它所有的特征值,指定相应的service:

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

Note:实际开发中不应该传nil,而是特征值的UUIDs.
peripheral在发现指定service的特征值后调用peripheral:didDiscoverCharacteristicsForService:error:.CB会创建一个CBCharacteristics数组:

- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
             error:(NSError *)error {

    for (CBCharacteristic *characteristic in service.characteristics) {
        NSLog(@"Discovered characteristic %@", characteristic);
        ...
    }
    ...

接收Characteristic的值(特征值)

一个特征值是一个简单的值:代表一个peripheral的service许多信息.例如健康体温计发送的温度测量特征值可能会包含一个值:摄氏度值.可以立刻读取它或者订阅它.

立刻读取特征值

在你找到需要的service的特征值后,使用CBPeripheral类中的readValueForCharacteristic:

    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
    ...

Note:不是所有的特征值都是可读的.你可以访问CBCharacteristicPropertyRead属性来查看是否可读.如果你尝试读取一个不可读的值,peripheral:didUpdateValueForCharacteristic:error:会返回对应的错误.

订阅特征值

尽管使用readValueForCharacteristic:来读取特征值有时候会很高效,但这并不是接收一个变化值的最有效的方法.对于大多值是变化的特征值 - 例如在任何时间段的心率变化 - 你应该通过订阅方式接受他们.当你订阅一个特征值时,你会在这个值变化时收到peripheral发出的通知.

调用CBPeripheral类的setNotifyValue:forCharacteristic:订阅你需要的特征值,指定第一个参数为YES:

[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]);
    }
    ...

Note:不是所有的特性(characteristic)可配置为订阅.你可以通过访问他的私有变量Characteristic Properties枚举
在你成功绑定特征值之后,peripheral设备会在特征值改变时通知你.每次特征值改变,peripheral调用peripheral:didUpdateValueForCharacteristic:error:.然后使用前面说过的立刻读取特征值的方法获取特征值.


写入特征值

在某些情况下,写入特征值是有意义的.例如,如果你的app与蓝牙低功耗数字温度计交互,你可能想向温度计提供一个温度值来设置房间温度,如果一个特征值是可写入的,调用CBPeripheral中的writeValue:forCharacteristic:type:写入一些data(NSData实例变量):

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

当尝试写入特征值时,可指定你想执行的写入类型.如上例:写入类型被指定为CBCharacteristicWriteWithResponse,表明着peripheral会在写入成功之后给你响应.更多写入类型请参考CBCharacteristicWriteType枚举

Peripheral通过peripheral:didWriteValueForCharacteristic:error:响应CBCharacteristicWriteWithResponse写入类型.如果写入失败,可在这里获取错误信息:

- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error {

    if (error) {
        NSLog(@"Error writing characteristic value: %@",
            [error localizedDescription]);
    }
    ...
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值