蓝牙(CoreBluetooth)-中心设备(客户端)

蓝牙客户端-中心设备

主要内容

  1. 1. 创建`中央管理器`
  2. 2. 发现并且连接外设
  3. 3. 寻找连接上的外设数据
  4. 4. 发送读或写`特征值`的请求
  5. 5. 订阅外设特征值

1. 创建中心管理器

因为CBCentralManager代表着本地中央设备,所以你必须先创建一个中央管理器对象,通过CBCentralManagerinitWithDelegate:queue:options: 如:

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

在上面的例子中,self设置为中央管理器的代理,它将接收来自中央管理器的事件回调,queue设置为nil,表示为主队列.当你创建一个中心管理器时,就会调用它代理的centralManagerDidUpdateState: 方法,你必须实现这个代理方法来确保你的设备支持蓝牙4.0.

2. 扫描外部设备

  1. [myCentralManager scanForPeripheralsWithServices:nil options:nil];
  1. 注意:如果第一个参数传入nil,中央管理器 返回全部找到的外设,忽略它们所支持的服务,你可以传入一个有独特UUID的服务数组,当你指定服务的时候,中央管理器 只返回具拥有这些服务的外设.
  2. 在你调用scanForPeripheralsWithServices:options:方法之后,中央管理器就会调用它代理的centralManager:didDiscoverPeripheral:advertisementData:RSSI:,没发现一个外设就会调用一次,发现的外部设备通过CBPeripheral对象传入.你可以实现这个方法列出所发现的外设.

    1. - (void)centralManager:(CBCentralManager *)central
    2. didDiscoverPeripheral:(CBPeripheral *)peripheral
    3. advertisementData:(NSDictionary *)advertisementData
    4. RSSI:(NSNumber *)RSSI {
    5. NSLog(@"Discovered %@", peripheral.name);
    6. ...

    当你找到你需要的外设后,你需要停止搜索.

3. 连接外部设备

当你找到自己需要的外设后,你应该请求连接外部设备,通过调用BCentralManagerconnectPeripheral:options:方法.如:

[myCentralManager connectPeripheral:peripheral options:nil];
假如连接外设成功,中央管理器就会调用它代理的centralManager:didConnectPeripheral:方法,

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

在与外设进行交互之前你应该首先设置外设的代理

4. 发现已经连接设备上的服务.

当你连接上一个外设,你就可以开始检索数据了,第一步,检索一个外设上都提供什么服务,通过下面的方法你可以检索出,所有的外设提供的所有的服务

  1. [peripheral discoverServices:nil];

注意:尽管你这么做可以反问这个外设上的所有服务,但是在一个真实的App中你通常不传入一个nil,因为一个外设可能非常多的服务,这些服务并不是你需要的,发现他们全部可能缩短电池的使用时间并且浪费时间.更多情况你需要制定服务UUID来检索你感兴趣的服务.

但发现指定的服务后,将会调用CBPeripheral 对象的代理方法peripheral:didDiscoverServices:,核心蓝牙框架会把所发现的服务放到一个数组中,设置给这个外设对象.你可以实现这个代理方法,访问这些服务

  1. - (void)peripheral:(CBPeripheral *)peripheral
  2. didDiscoverServices:(NSError *)error {
  3. for (CBService *service in peripheral.services) {
  4. NSLog(@"Discovered service %@", service);
  5. ...
  6. }
  7. ...

5. 发现一个服务上的特征.

假设你已经找到了你需要的服务,下一步就是检索该服务上的特征,检索服务上的所有特征你只需要调用CBPeripheral 方法 discoverCharacteristics:forService: 并指定服务

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

注意: 尽管你这么做可以反问这个服务上的所有特征,但是在一个真实的App中你通常不要出入一个nil,因为一个服务可能非常多的特征,这些特征并不是你需要的,发现他们全部可能会缩短电池的使用时间并且浪费时间.更多情况你需要制定特征UUID来检索你感兴趣的 特征.

当外设检索到指定服务的特征后,就会调用代理对象的peripheral:didDiscoverCharacteristicsForService:error: 核心蓝牙会把所发现的特征放到数组中设置给服务的characteristics 属性,你可以实现这个代理方法,获取检索到的特征

  1. - (void)peripheral:(CBPeripheral *)peripheral
  2. didDiscoverCharacteristicsForService:(CBService *)service
  3. error:(NSError *)error {
  4. for (CBCharacteristic *characteristic in service.characteristics) {
  5. NSLog(@"Discovered characteristic %@", characteristic);
  6. ...
  7. }
  8. ...

6. 取出一个特征的值

一个特征包含一个单独的,这个代表着外设提供的服务的详细信息.例如在一个体温计中的一个温度的特征有一个值代表着摄氏度的温度.你可以可以直接读取这个值或订阅这个值

1. 读出一个特征的值

当你找到需要的服务的一个特征后,你可以读取这个特征的值,通过调用CBPeripheralreadValueForCharacteristic: 传入那个特征.像这样

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

当你试图读取一个特征的值的时候,外设就会调用它代理的peripheral:didUpdateValueForCharacteristic:error: 方法,如果这个被成功的获取,你就可访问特征value属性获取这个值,像这样

  1. - (void)peripheral:(CBPeripheral *)peripheral
  2. didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
  3. error:(NSError *)error {
  4. NSData *data = characteristic.value;
  5. // parse the data as needed
  6. ...

注意: 并不是所有的特征都有读的权限,你要检测这个特征是否有读的权限可以通过特征的properties属性中CBCharacteristicPropertyRead Key ,如果你试图读取一个不可度的特征值,那么在peripheral:didUpdateValueForCharacteristic:error: 方法中将会传入一个合适的 错误

2. 订阅一个特征的值

尽管在某些情况下你可以通过readValueForCharacteristic: 很方便的读取一个特征的值,但是对于一个经常变化的值这不是一中高效的方式.大部分特征的值的变化的--例如心率是每时每刻都在变化,此时你应该订阅它.当你订阅一个特征的值的时候,你将会收到一个通知,当外设的值改变的时候

你可以订阅一个特征的值,通过调用CBPeripheralsetNotifyValue:forCharacteristic: 第一个参数传入YES,像这样

  1. [peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

当你尝试订阅(或取消订阅)一个特征的值时,外设的代理方法peripheral:didUpdateNotificationStateForCharacteristic:error: 就会被调用.如果订阅请求因任何原因失败,这个代理方法中都会通过error告诉你错误的原因.例如:

  1. - (void)peripheral:(CBPeripheral *)peripheral
  2. didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
  3. error:(NSError *)error {
  4. if (error) {
  5. NSLog(@"Error changing notification state: %@",
  6. [error localizedDescription]);
  7. }
  8. ...

注意: 不是所有特征都可以订阅他们的值,你可以通过CharacteristicProperties 属性来判断这个特征是否支持订阅.

当你成功订阅一个特征的值后,外设将会在它的值改变的时候通知你.每次值的改变都会调用代理的peripheral:didUpdateValueForCharacteristic:error:方法,为了获取这个这你需要实现这个代理方法.

7.写入一个特征的值

有些时候可能需要需要写入一个特征的值,比如你app和基于蓝牙4.0的自动温度调节器交互,你可能需要提供一个值来设置室内温度,如果这个特征值是可写的,你通过CBPeripheralwriteValue:forCharacteristic:type: 方法,第一个参数传入一个NSData对象,像这样:

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

当你写入特征的值时,你需要指定按照什么类型写入,在上面的例子中指定是CBCharacteristicWriteWithResponse 它告诉外设需要让你的app知道是否写入成功.

外设通过调用代理对象的peripheral:didWriteValueForCharacteristic:error: 来响应指定类型参数CBCharacteristicWriteWithResponse写入请求.任何原因导致的写入失败,你都会收到一个错误对象,它描述了错误的原因,例如

  1. - (void)peripheral:(CBPeripheral *)peripheral
  2. didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
  3. error:(NSError *)error {
  4. if (error) {
  5. NSLog(@"Error writing characteristic value: %@",
  6. [error localizedDescription]);
  7. }
  8. ...

注意:特征可能只允许以特定的类类型写入,想知道特征都支持那种类型的写入可以遍历Characteristicproperties 属性.

附录. 中心设备流程

中心设备流程.jpg

蓝牙(CoreBluetooth)-中心设备(客户端)的更多相关文章

  1. Android-低功耗蓝牙(BLE)-客户端(主机/中心设备)和服务端(从机/外围设备)

    一.Android 低功耗蓝牙(BLE)的API简介 从Android 4.3(API 18)才支持低功耗蓝牙(Bluetooth Low Energy, BLE)的核心功能, BLE蓝牙协议是GAT ...

  2. 蓝牙(CoreBluetooth)-概述

    蓝牙(CoreBluetooth)-概述 通过此框架可以让你的Mac和iOS应用程序与外部蓝牙设备通信 外部设备: 就是需要通过iOS App控制器的其他设备: 例如:心率检测仪.数字温控器 蓝牙通讯 ...

  3. 蓝牙 CoreBluetooth

    baseK(相关基础知识)蓝牙常见名称和缩写 BLE:(Bluetooth low energy)蓝牙4.0设备因为低耗电,也叫BLEperipheral,central:外设和中心设备,发起链接的是 ...

  4. 蓝牙(CoreBluetooth)-外部设备(服务端)

    蓝牙(CoreBluetooth)-外部设备(服务端) 主要内容 1. 创建外部管理器对象 2. 设置本地外设的服务和特征 3. 添加服务和特征到到你的设置的数据库中 4. 向外公布你的的服务 5. ...

  5. iOS蓝牙--CoreBluetooth基本使用

    蓝牙使用步骤: 1. 扫描外设 2. 连接外设 3. 连上外设后,获取指定外设的服务 4. 获取服务后,遍历服务的特征,得到可读,可写等特征,然后与中心管理者进行数据交互 附上代码 一:导入框架 #i ...

  6. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

  7. Spring Cloud(十四)Config 配置中心与客户端的使用与详细

    前言 在上一篇 文章 中我们直接用了本应在本文中配置的Config Server,对Config也有了一个基本的认识,即 Spring Cloud Config 是一种用来动态获取Git.SVN.本地 ...

  8. Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    关键词:蓝牙blueZ  A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...

  9. Spring Cloud 中注册中心Eureka客户端配置

    注册中心配置客户端(注册一个虚拟的商品服务) 一.新建项目:     1.创建一个SpirngBoot应用,增加服务注册和发现依赖     2.模拟商品信息,存储在内存中     3.开发商品列表接口 ...

随机推荐

  1. tez是什么?

    [Apache Tez是什么?] http://dongxicheng.org/mapreduce-nextgen/apache-tez/ 浅谈Apache Tez中的优化技术 http://dong ...

  2. CMakeFile命令之file

    file:文件操作命令. file(WRITE filename "message towrite"... ) WRITE 将一则信息写入文件’filename’中,如果该文件存在 ...

  3. ISP图像调试工程师——自动白平衡(熟悉3A算法)

    http://blog.csdn.net/wzwxiaozheng/article/details/40586293 https://wenku.baidu.com/view/24632048767f ...

  4. 你以为border-radius只是圆角吗?【各种角度】

    border-radius,国内翻译成圆角,你可能以为这个属性就是用来画圆角,没错,但是除此之外,它还可以做点别的事情. radius其实指的是边框所在圆的半径,这个CSS3属性不仅能够创建圆角,还可 ...

  5. 心路历程——毕设程序mr跑不通的问题

    这个bug改了实在是太多天了,前前后后折腾了太久,最后多谢@CC学长的帮助,找到了问题,才终于跑通了!!!这里记录一下这个bug我前后改的过程,引以为戒! 毕设中需要进行mapreduce进行数据清洗 ...

  6. MVVM和MVC的区别,以及MVVM的缺点

    MVVM和MVC的区别 MVC和MVVM的区别其实并不大.都是一种设计思想. 主要就是MVC中Controller演变成MVVM中的viewModel. MVVM主要解决了MVC中大量的DOM操作使页 ...

  7. 扩展JButton实现自己的图片按钮

    实现效果: 代码: import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.In ...

  8. 说说C#之父——安德斯·海尔斯伯格

    安德斯·海尔斯伯格(Anders Hejlsberg,1960.12~),丹麦人,Turbo Pascal编译器的主要作者,Delphi和.NET之父! 看到照片的那一刹那儿,我就觉得帅爆了,53岁的 ...

  9. Core Data NSAttribute Type 数据类型

    一:使用Core Data 的可用数据类型 NSAttributeType Defines the possible types of NSAttributeType properties. Thes ...

  10. UIWebView捕获内部web点击事件

    在此有一个webView默认是打开 百度的页面:设置代理,并在代理中处理 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest ...