Core Bluetooth库编程指南官方文档翻译1-3

执行普通中央角色任务

在蓝牙低功耗交互中实现了中央角色的设备执行一些普通任务--例如,发现和连接有效的外设,探索并与外设提供的数据进行交互。与此形成鲜明对比的是,实现外设角色的设备执行一些普通但不同的任务—例如,发布和广播服务,响应从连接的中央读写和订阅请求。
在这章中,你将会学习到怎样使用Core Bluetooth框架来从中央端执行大多数的蓝牙低功耗任务。下面一个基本的代码示例将会有助于开发你的应用程序来在你的本地设备上实现中央角色。
*启动一个中央管理者对象
*发现和连接正在广播的外设
*连接外设之后探索其中数据
*给外设的服务的一个特征发送读写请求
*订阅一个值在更新时发出通知的特征
在下一章节,你将会学习到怎样开发你的应用程序在你的本地设备上实现外设角色。
在这个章节你发现的代码示例是简单的和抽象的;你可能需要进行适当的修改,将其纳入你的真实世界的应用。更高级的主题是与实现中央角色有关--包括提示,技巧和好的练习--在后面的章节会提到。Core Bluetooth Background Processing for iOS AppsBest Practices for Interacting with a Remote Peripheral Device.

启动一个中央管理者

一个CBCentralManager对象是在Core Bluetooth中对象定向表示为本地中央设备,你必须在你执行一些蓝牙低功耗事务时分配内存和初始化一个中央管理者实例,你可以通过调用CBCentralManager类中的initWithDelegate:queue:options:方法来启动你的中央管理者,例如:

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

在这个例子中,self是作为接受中央角色事件的代理,通过指定派遣队列是nil,中央管理者会在主队列中处理中央角色事件。
当你创建了中央管理者,中央管理者会调用它的代理对象centralManagerDidUpdateState:方法。你必须实现这个代理方法来确保设备支持蓝牙低功耗且中央设备可以有效使用。关于怎样实现这个代理方法更多的信息,请看CBCentralManagerDelegate Protocol Reference

发现正在广播的外设

中央端的其中的一个任务是你可能需要执行发现一些你的应用程序能够有效连接的外设。在Centrals Discover and Connect to Peripheral That Are Advertising早有提及,广播是外设被知道的主要方式。你可以通过调用CBCentralManager类中的scanForPeripheralsWithService:options:方法来发现一些正在广播的外设。

[myCentralManager scanForPeripheralsWithService:nil options:nil];

注意:如果你给第一个参数指定为nil,中央管理者会返回所有发现的外设,不管它们支持的服务。在一个真实的应用程序中,你将更可能指定一个CBUUID对象的数组,这个对象表示正在广播的外设的一个服务的普通唯一标识(UUID),当你指定了服务UUIDs数组,中央管理者会返回只广播这些服务的外设,允许你只扫描你可能感兴趣的外设。
UUIDs,和CBUUID对象来表示它们,在Services and Characteristic Are Identified by UUIDs有更详细的讨论。

在你调用scanForPeripheralsWithServices:options:方法来发现可用的外设后,中央管理者在每次发现外设时会调用它的代理对象的centralManager:didDiscoverPeripheral:advertisementData:RSSI:方法。任何一个被发现的外设都会返回一个CBPeripheral对象。如以下所示,你可以实现这个代理方法来列出任何被发现的外设。

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

当你已经发现了你感兴趣想要连接的外设,为了保存手机能量停止扫描其他的外设。

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

当你已经发现了外设之后连接外设

当你已经发现了正在广播你感兴趣的服务的外设,你可以通过调用CBCentralManager类的connectPeripheral:options:方法来请求连接外设。用简单地调用这个方法并指定你想连接的已经发现的外设。例如:

[myCentralManager connectPeripheral:peripheral options:nil];

假设连接成功,中央管理者会调用它代理对象的centralManager:didConnectPeripheral:方法,你可以在这里面实现打印建立连接的信息,如下所示:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Peripheral connected");
    ...
}

在你与该外设交互之前,你应该设置外设的代理来确保它能接受到适当的回调,例如:

peripheral.delegate = self;

发现你已经连接外设的服务

在你已经与外设建立连接之后,你可以开始探索它的数据。在探索的第一步外设必须提供正在被发现的有效服务。因为外设能广播有大小限制的数据量,你可能会发现一个外设有更多的广播服务(在它的广播包中),你可以通过调用CBPeripheral类中的discoverServices:方法来发现外设提供的所有服务。如下:

[peripheral discoverServices:nil];

注意:在真实的应用程序中,你不需要将参数设置成nil;这样做会返回外设的所有有效服务。因为一个外设可能包含很多你感兴趣的服务,发现它们的所有会浪费电池的寿命同时也没有必要。更多的情况下,你将指定你已经知道你所感兴趣的服务的UUIDs,在Explore a Peripheral's Data Wisely可以看。
当一个指定的服务被发现,外设(你已经连接的CBPeripheral对象)会调用它的代理对象的peripheral:didDiscoverServices:方法。Core Bluetooth创建了一个数组包含CBService对象--代表着一个在外设中被发现的服务。如下所示,你可以实现这个代理方法来访问发现服务的数组:

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

发现服务的特征

假设你已经发现了你感兴趣的服务,接下来的一步是探索外设已经提供的正在被发现的服务的特征。通过调用CBPeripheral类的discoverCharacteristics:forService:方法很容易发现服务的所有特征,指定合适的服务,如下:

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

注意:在真实的应用程序中,你可能不需要设置第一个参数为空,这样做会返回一个外设服务的所有特征。因为一个外设服务可能包含你感兴趣的更多的特征,发现它们的所有会浪费电池的寿命,而且也会花费不必要的时间。所以在发现特征的时候,你可以指定你感兴趣的已知特征的UUIDs。

当指定服务的特征被发现了外设会调用它的代理对象的peripheral:didDiscoverCharacteristicsForService:error:方法,Core Bluetooth创建一个数组保存CBCharacteristic对象--一个被发现的特征。下面的例子显示你可以实现这个代理方法来简单的打印每个被发现的特征值的信息:

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

得到特征值

一个特征包含一个代表一个外设服务信息的值。例如,一个健康温度计的一个温度测量特征可能有一个值来表明一个摄氏温度。你可以通过正确地读取或订阅它来得到这个特征值。

读取特征值

在你发现了一个你感兴趣的服务的特征之后,你可以通过CBPeripheral类的readValueForCharacteristic:方法,指定一个合适的特征,来读取特征值。就像:

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

当你想要读取一个特征值时,外设会调用它的代理对象的peripheral:didUpdateValueForCharacteristic:error:方法来得到这个值。如果这个值是成功的获得,你可以通过这个特征的值属性来访问它。就像:

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

注意:不是所有的特征都保证有一个值是可读的。你可以通过访问CBCharacteristicPropertyRead常量属性来决定特征值是否可读,具体请看CBCharacteristic Class Reference.如果你尝试读取不可读的特征值,代理方法peripheral:didUpdateValueForCharacteristic:error:将会返回一个错误的信息。

订阅特征值

通过使用readValueForCharacteristic:方法来读取特征值在一些情况下是有效的,但它并不是一个高效的方式来获取一个改变的特征值。对于大多数改变的特征值--例如在每一个给定的时间的心率值--你应该通过订阅它们来获取它们的值,当你订阅了一个特征值,当外设的特征值改变的时候你会接受到一个通知。你可以通过调用CBPeripheral类的setNotifyValue:forCharacteristic:方法并指定第一个参数为YES来订阅一个你感兴趣的特征值。就像:

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

当你想要订阅(或取消订阅)一个特征值时,外设会调用它的代理对象的peripheral:didUpdateNotificationStateForCharacteristic:error:方法,如果因为一些原因而订阅失败,你可以实现这个代理方法来访问错误的原因,如下所示:

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

注意:并不是所有的特征都配置了允许你订阅它们的值。你可以通过访问在Characteristic Properties枚举中有关的常量来决定这个特征是否已经配置来,具体请看CBCharacteristic Class Reference

当你成功的订阅了一个特征值以后,在该特征值改变时外设会通知你的应用程序。每次值的改变,外设会调用它的代理对象的peripheral:didUpdateValueForCharacteristic:error:方法。为了获得这个更新的值,你可以用同样的方式实现这个方法在Reading the Value of a Characteristic的描述中.

给特征值写入数据

在一些情况下,需要给一些特征写一些有意义的值。例如,如果你的应用程序与蓝牙低功耗数字恒温控制器交互,你可能会想要提供给恒温控制器一些值来设置房间的温度。如果一个特征值是可写的,你可以通过调用CBPeripheral类的writeValue:forCharacteristic:type:方法来写入一些数据(NSData类型的实例).就像:

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

当你想要给一个特征写入值,你需要指定你想要执行的写入类型。在上面的例子中,指定的类型是CBCharacteristicWriteWithResponse,这表明外设让你的应用程序知道是否写入成功,想要知道Core Bluetooth框架中提供的写入类型更多信息,请看在CBPeripheral Class Reference中的CBCharacteristicWriteType枚举。
外设通过调用它的代理对象的peripheral:didWriteValueForCharacteristic:error:方法会响应指定为CBCharacteristicWriteWithResponse类型的写入请求。如果因为一些原因写入失败,你可以实现这个代理方法来访问失败的原因,如下例所示:

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

注意:特征可能只允许某些类型可写入值。为了确定哪些特征值允许被写入,你可以访问Characteristic Properties枚举中的相关属性,详细的请看CBCharacteristic Class Reference;

---翻译的文档地址:Performing Common Central Role Tasks

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容