蓝牙(CoreBluetooth)-中心设备(客户端)
蓝牙(CoreBluetooth)-中心设备(客户端)
蓝牙客户端-中心设备
主要内容
1. 创建`中央管理器`
2. 发现并且连接外设
3. 寻找连接上的外设数据
4. 发送读或写`特征值`的请求
5. 订阅外设特征值
1. 创建中心管理器
因为CBCentralManager
代表着本地中央设备
,所以你必须先创建一个中央管理器对象,通过CBCentralManager
的initWithDelegate:queue:options:
如:
myCentralManager =
[[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
在上面的例子中,self设置为中央管理器的代理,它将接收来自中央管理器
的事件回调,queue设置为nil,表示为主队列.当你创建一个中心管理器时,就会调用它代理的centralManagerDidUpdateState:
方法,你必须实现这个代理方法来确保你的设备支持蓝牙4.0.
2. 扫描外部设备
[myCentralManager scanForPeripheralsWithServices:nil options:nil];
注意
:如果第一个参数传入nil,中央管理器
返回全部找到的外设,忽略它们所支持的服务,你可以传入一个有独特UUID的服务
数组,当你指定服务的时候,中央管理器
只返回具拥有这些服务的外设.在你调用
scanForPeripheralsWithServices:options:
方法之后,中央管理器
就会调用它代理的centralManager:didDiscoverPeripheral:advertisementData:RSSI:
,没发现一个外设就会调用一次,发现的外部设备通过CBPeripheral
对象传入.你可以实现这个方法列出所发现的外设.- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI { NSLog(@"Discovered %@", peripheral.name);
...当你找到你需要的外设后,你需要停止搜索.
3. 连接外部设备
当你找到自己需要的外设后,你应该请求连接外部设备,通过调用BCentralManager
的connectPeripheral:options:
方法.如:
[myCentralManager connectPeripheral:peripheral options:nil];
假如连接外设成功,中央管理器
就会调用它代理的centralManager:didConnectPeripheral:
方法,
- (void)centralManager:(CBCentralManager *)central
didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"Peripheral connected");
...
在与外设进行交互之前你应该首先设置外设的代理
4. 发现已经连接设备上的服务.
当你连接上一个外设,你就可以开始检索数据了,第一步,检索一个外设上都提供什么服务,通过下面的方法你可以检索出,所有的外设提供的所有的服务
[peripheral discoverServices:nil];
注意
:尽管你这么做可以反问这个外设
上的所有服务
,但是在一个真实的App
中你通常不传入一个nil
,因为一个外设可能非常多的服务,这些服务并不是你需要的,发现他们全部可能缩短电池的使用时间并且浪费时间.更多情况你需要制定服务
的UUID
来检索你感兴趣的服务
.
但发现指定的服务后,将会调用CBPeripheral
对象的代理方法peripheral:didDiscoverServices:
,核心蓝牙框架会把所发现的服务放到一个数组中,设置给这个外设对象.你可以实现这个代理方法,访问这些服务
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error {
for (CBService *service in peripheral.services) {
NSLog(@"Discovered service %@", service);
...
}
...
5. 发现一个服务上的特征.
假设你已经找到了你需要的服务,下一步就是检索该服务上的特征,检索服务上的所有特征你只需要调用CBPeripheral
方法 discoverCharacteristics:forService:
并指定服务
NSLog(@"Discovering characteristics for service %@", interestingService);
[peripheral discoverCharacteristics:nil forService:interestingService];
注意
: 尽管你这么做可以反问这个服务
上的所有特征
,但是在一个真实的App
中你通常不要出入一个nil,因为一个服务
可能非常多的特征
,这些特征
并不是你需要的,发现他们全部可能会缩短电池的使用时间并且浪费时间.更多情况你需要制定特征
的UUID
来检索你感兴趣的特征
.
当外设检索到指定服务的特征后,就会调用代理对象的peripheral:didDiscoverCharacteristicsForService:error:
核心蓝牙会把所发现的特征放到数组中设置给服务的characteristics
属性,你可以实现这个代理方法,获取检索到的特征
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error {
for (CBCharacteristic *characteristic in service.characteristics) {
NSLog(@"Discovered characteristic %@", characteristic);
...
}
...
6. 取出一个特征的值
一个特征
包含一个单独的值
,这个代表着外设提供的服务的详细信息.例如在一个体温计中的一个温度的特征
有一个值代表着摄氏度的温度.你可以可以直接读取这个值或订阅这个值
1. 读出一个特征的值
当你找到需要的服务的一个特征后,你可以读取这个特征的值,通过调用CBPeripheral
的readValueForCharacteristic:
传入那个特征.像这样
NSLog(@"Reading value for characteristic %@", interestingCharacteristic);
[peripheral readValueForCharacteristic:interestingCharacteristic];
当你试图读取一个特征的值的时候,外设就会调用它代理的peripheral:didUpdateValueForCharacteristic:error:
方法,如果这个被成功的获取,你就可访问特征
的value
属性获取这个值,像这样
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
NSData *data = characteristic.value;
// parse the data as needed
...
注意:
并不是所有的特征都有读的权限,你要检测这个特征是否有读的权限可以通过特征的properties
属性中CBCharacteristicPropertyRead
Key ,如果你试图读取一个不可度的特征值,那么在peripheral:didUpdateValueForCharacteristic:error:
方法中将会传入一个合适的错误
2. 订阅一个特征的值
尽管在某些情况下你可以通过readValueForCharacteristic:
很方便的读取一个特征的值,但是对于一个经常变化的值这不是一中高效
的方式.大部分特征的值的变化的--例如心率是每时每刻都在变化,此时你应该订阅它.当你订阅一个特征的值的时候,你将会收到一个通知,当外设的值改变的时候
你可以订阅一个特征的值,通过调用CBPeripheral
的setNotifyValue:forCharacteristic:
第一个参数传入YES
,像这样
[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];
当你尝试订阅(或取消订阅)一个特征的值时,外设的代理方法peripheral:didUpdateNotificationStateForCharacteristic:error:
就会被调用.如果订阅请求因任何原因失败,这个代理方法中都会通过error
告诉你错误的原因.例如:
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error) {
NSLog(@"Error changing notification state: %@",
[error localizedDescription]);
}
...
注意:
不是所有特征都可以订阅他们的值,你可以通过Characteristic
的Properties
属性来判断这个特征是否支持订阅.
当你成功订阅一个特征的值后,外设将会在它的值改变的时候通知你.每次值的改变都会调用代理的peripheral:didUpdateValueForCharacteristic:error:
方法,为了获取这个这你需要实现这个代理方法.
7.写入一个特征的值
有些时候可能需要需要写入一个特征的值,比如你app和基于蓝牙4.0的自动温度调节器交互,你可能需要提供一个值来设置室内温度,如果这个特征值是可写的,你通过CBPeripheral
的 writeValue:forCharacteristic:type:
方法,第一个参数传入一个NSData
对象,像这样:
NSLog(@"Writing value for characteristic %@", interestingCharacteristic);
[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic
type:CBCharacteristicWriteWithResponse];
当你写入特征的值时,你需要指定按照什么类型写入,在上面的例子中指定是CBCharacteristicWriteWithResponse
它告诉外设需要让你的app知道是否写入成功.
外设通过调用代理对象的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
属性.附录. 中心设备流程
中心设备流程.jpg
蓝牙(CoreBluetooth)-中心设备(客户端)的更多相关文章
- Android-低功耗蓝牙(BLE)-客户端(主机/中心设备)和服务端(从机/外围设备)
一.Android 低功耗蓝牙(BLE)的API简介 从Android 4.3(API 18)才支持低功耗蓝牙(Bluetooth Low Energy, BLE)的核心功能, BLE蓝牙协议是GAT ...
- 蓝牙(CoreBluetooth)-概述
蓝牙(CoreBluetooth)-概述 通过此框架可以让你的Mac和iOS应用程序与外部蓝牙设备通信 外部设备: 就是需要通过iOS App控制器的其他设备: 例如:心率检测仪.数字温控器 蓝牙通讯 ...
- 蓝牙 CoreBluetooth
baseK(相关基础知识)蓝牙常见名称和缩写 BLE:(Bluetooth low energy)蓝牙4.0设备因为低耗电,也叫BLEperipheral,central:外设和中心设备,发起链接的是 ...
- 蓝牙(CoreBluetooth)-外部设备(服务端)
蓝牙(CoreBluetooth)-外部设备(服务端) 主要内容 1. 创建外部管理器对象 2. 设置本地外设的服务和特征 3. 添加服务和特征到到你的设置的数据库中 4. 向外公布你的的服务 5. ...
- iOS蓝牙--CoreBluetooth基本使用
蓝牙使用步骤: 1. 扫描外设 2. 连接外设 3. 连上外设后,获取指定外设的服务 4. 获取服务后,遍历服务的特征,得到可读,可写等特征,然后与中心管理者进行数据交互 附上代码 一:导入框架 #i ...
- 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ A2DP.SINK.sink_connect.s ...
- Spring Cloud(十四)Config 配置中心与客户端的使用与详细
前言 在上一篇 文章 中我们直接用了本应在本文中配置的Config Server,对Config也有了一个基本的认识,即 Spring Cloud Config 是一种用来动态获取Git.SVN.本地 ...
- Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
关键词:蓝牙blueZ A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...
- Spring Cloud 中注册中心Eureka客户端配置
注册中心配置客户端(注册一个虚拟的商品服务) 一.新建项目: 1.创建一个SpirngBoot应用,增加服务注册和发现依赖 2.模拟商品信息,存储在内存中 3.开发商品列表接口 ...
随机推荐
- CDHtmlDialog 基本使用
跳转 Navigate("res://tt.exe/#138"); 138是html的资源号 输入框的Get,set HRESULT CTTDlg::OnButtonCancel( ...
- 通过命名管道协议方式访问群集SQL的一个小问题
原来的单机实例SQL如果开放命名管道协议访问可以在.Net程序的连接字符串中增加“;Net=dbnmpntw"以通过命名管道协议方式访问,但是当迁移到群集SQL后,.net通过它可能无法正常 ...
- HTML5中表单验证的8种方法
HTML5中表单验证的8种方法 2012-4-21 11:00| 发布者: benben| 查看: 2765| 评论: 0 摘要: 前一篇,我们介绍了HTML5中新的表单特性和函数, 今天就继续来谈谈 ...
- javascript 中contentWindow和 frames和iframe之间通信
iframe父子兄弟之间通过jquery传值(contentWindow && parent),iframe的调用包括以下几个方面:(调用包含html dom,js全局变量,js方法) ...
- iOS: 工具栏控件UIToolBar和工具栏按钮控件UIBarButtonItem的使用
一.工具栏控件:UIToolBar:UIView 介绍: ToolBar工具栏是视图View的属性,可以在工具栏上添加工具栏按钮Bar Button Item(可以是自定义的Custom.也可以是系统 ...
- 这里先发布一个,自己写得unityUI的适配的方案(插播)
这个适配是依据坐标系的象限的思想来进项适配的.參考了部分的NGUI的适配方案. 在程序的事实上,来測量UI距离相机边界的像素然后依据比例来进行适配,个人认为还不错. 放码! . 有个前提哦就是你要先定 ...
- C# 中的"yield"与 "yield break"使用
yield是C#为了简化遍历操作实现的语法糖,我们知道如果要要某个类型支持遍历就必须要实现系统接口IEnumerable,这个接口后续实现比较繁琐要写一大堆代码才能支持真正的遍历功能.举例说明 usi ...
- iOS7重磅推新--不断尝试与重新设计的过程
来源:GBin1.com iOS7重磅推新--不断尝试与重新设计的过程 或许你心里已经有了关于iPhone最新操作系统的评价,可能你喜欢它,也可能不喜欢,事实上大多数设计者不喜欢.设计界似乎一致认为I ...
- Android异步载入全解析之大图处理
Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...
- ASP.NET WEB API处理流程
前言:大图请看 http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf Web Api Hosting 我们不仅可以通过Web应用程 ...