IOS BLE4.0蓝牙和外设连接和收发数据的流程

前言:

苹果在IOS 6系统之后开始支持BLE 4.0,iPhone4s,iPod 5,iPad 3等之后的机型开始内嵌BLE4.0硬件,因此在开发前请先确认你的开发环境符合上述要求,并且苹果在BLE4.0之后,对外部的连接设备已经不在需要MFI认证了,当然你的外设肯定得要有蓝牙4.0模块了

综述:

开发BLE4.0的App,你需要在你的项目里面导入框架:

CoreBluetooth.framework

在需要使用到蓝牙的文件里面你需要导入头文件:

#import <CoreBluetooth/CoreBluetooth.h>

#import<CoreBluetooth/CBService.h>

并且你需要在你的蓝牙类里面实现两个协议,CBCentralManagerDelegate ,CBPeripheralDelegate

现在我们需要有两个实例对象CBCentralManager和CBPeripheral,第一个是蓝牙中心管理器,主要用来搜索外设,连接外设以及处理外设断开的情况;第二个主要用于在蓝牙中心管理器成功连接外设之后的一系列动作,如:读取外设的服务号CBService,特征值号CBCharacteristic以及对这些特征值号进行读写操作等,下面我们来看一下IOS这边和外设联机的一个大概流程:

1):IOS这边蓝牙中心管理器开始扫描广播包(扫描的时长可以自己写一个定时器控制,并且可以设定扫描的具体条件)

2):外设开始广播(当然外设的广播时长也是可以设定的,这是硬件那边的事了,我不太懂)

3):IOS发现有广播包,就请求连接外设(这是底层自动实现,我们不需要写代码),之后外设会接收到连接请求,如果外设接收这个连接请求,就会给IOS那边发送一个连接请求的确认包,当IOS这边收到这个包后,两边设备就完成了连接(当然,由于连接底层已经写好,比较复杂,我讲的比较肤浅,只是一个大概步骤而已)

4):连接成功之后IOS这边就可以读取外设的相关信息了,比如服务号CBService,特征值号CBCharacteristic,还有外设的一些硬件信息,电池电量,信号强度RSSI什么的

5):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和IOS程序里对于连接断开的处理代码了

6):当然,外设和IOS端也可以主动发起断开连接的请求

下面我们看看IOS端具体的代码流程和基本的含义,你只需要跟着我的顺序走就可以了,以下顺序符合IOS BLE4.0联机的流程:

在你的蓝牙类的初始化里面,先实例化一下中心设备管理器

_centralMan =  [[CBCentralManager alloc] initWithDelegate:self  queue:nil];

代码很简单吧,只需要一行就可以了,主要是要设置委托的对象,至于是否要加入某个队列,就看你的需求了,还记得我们蓝牙类里面继承了CBCentralManagerDelegate ,CBPeripheralDelegate两个协议吧,你可以跟进去看一下里面的协议方法,我就不多说了,先讲第一个需要实现的协议方法

-   (void)centralManagerDidUpdateState:(CBCentralManager *)central

这个方法主要是来检查IOS设备的蓝牙硬件的状态的,比如说你的设备不支持蓝牙4.0,或者说你的设备的蓝牙没有开启,没有被授权什么的,一般是在你确定了你的IOS设备的蓝牙处于打开的情况下,你才应该执行扫描的动作,[_centralMan scanForPeripheralsWithServices:Nil options:Nil]; 我记得我之前没有检查蓝牙的状态就直接扫描了,虽然项目可以运行,但是控制台给出了一大堆的警告什么的,看着很烦人,那么我们执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了

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

这个方法里面的信息量可是比较大啊,看那个CBPeripheral,你在这个方法里面你就已经可以获取它的名称了可以使用peripheral.name来获取名称,当然,这里还可以获取设备的一个广播名称 NSString *CBName=[advertisementData valueForKeyPath:CBAdvertisementDataLocalNameKey]; 这两个名称一般是不一样的,除非你们硬件那边把人家写一样了,当然还有其他的很多信息,具体看代码吧;在这个回调里我们可以获取外设的广播包信息,当然我们就可以根据广播包的信息符合不符合你们的自定义的协议,符合就可以发起连接请求了,这样可以避免连接上其它一些自己不希望连接上的外设;当然你应该也看到了这里还有一个RSSI的值,这里是广播包附带过来的,根据这个值我们可以大概估计出广播设备里我们IOS设备有多远,如果信号太弱距离过远,我们是不是就不考虑连接这个外设了;这里我们假设广播包数据符合条件,我们发起了连接请求[_centralMan connectPeripheral:_peripheral options:Nil];那么如果连接成功,就会回调下面的协议方法了:

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

如果你能回调到上面这个方法,说明你已经成功连接外设了,具体你可以打个断点试试,既然连接已经成功,我们就该考虑是不是要停止中心管理设备的扫描动作了,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的IOS设备就会也去连接这个设备(因为IOS BLE4.0是支持一对多连接的),导致数据的混乱。所以我们在这个方法里面停止扫描动作:[_centralMan stopScan];  现在是时候让我们的第二个实例对像出场了  CBPeripheral,这里需要注意的是,记得要设置CBPeripheral的委托对象 _peripheral.delegate =self;为了以后使用方便,我们还是一次性读出外设的所有服务UUID:[_peripheral discoverServices:nil];这样一旦我们读取到外设的相关服务UUID就会回调下面的方法:

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

接着在这个方法里面我们还可以接着往里面剥,读取某个CBService 里面的特征值UUID:[peripheral discoverCharacteristics:nil forService:s];同上,如果我们成功读取某个特征值UUID,就会回调下面的方法:

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

能进入到这个方法,说明你已经读取到某个特征值UUID了,到达这一步,我们基本上也完成对外设的层层剥离了,接下来就是一些对某个特征值的读写操作了,当然我们首先要找到我们需要写数据的特征值UUID了,这里我们可以简单地通过循环来找出外设含有的某个特征值UUID:

for(int i=0; i < service.characteristics.count; i++) {

CBCharacteristic *c = [service.characteristicsobjectAtIndex:i];

if ([[c UUID] isEqual:[CBUUIDUUIDWithString:@"FFF1"]])

{ //你的动作}

}

在这里我们需要强调一下,由于特征值UUID是外设设定的,并且特征值UUID的属性properties有很多种,比如Read,WriteWithoutResponse,Write,Notify等等,因此你需要根据你们之间的协议还确定对某个特征值UUID怎么处理了,当然你也可以自己读出来这个特征值UUID的属性:c.properties,这里我们假设一个特征值UUID :“FFF1”的属性为WriteWithoutResponse,我们往里面写一个数据

Byte dataArr[2];

dataArr[0]=0xaa; dataArr[1]=0xbb;

NSData * myData = [NSData dataWithBytes:dataArr length:2];

[_peripheral writeValue:myData forCharacteristic:c type:CBCharacteristicWriteWithResponse];

这样我们就完成了一次向外设写数据,但是如果外设的特征值UUID是Read,怎么办呢?比如说获取外设的电池电量信息(注:这个属于标准服务里面自带),服务UUID:“180F”,特征值UUID:“2A19”,我们可以这样写:

[_peripheral readValueForCharacteristic:cbc];

cbc就是指特征值为“2A19”的特征值对象,当然还有属性为Notify的,方法和这个类似:[peripheralsetNotifyValue:YES forCharacteristic:c];

那么我们设置读这个特征值对象的值了,怎么接收它发过来的值呢,其实如果外设有特征值对象的值更新了,会自动回调下面的方法:

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

在这个回调函数里面我们就可以根据characteristic的值来判断是哪个特征值UUID发送过来的值了,那个peripheral主要是用来判断是哪个外设发送的值,主要用于蓝牙一对多的情况,如果是一对一的,基本没用。那么我们再说一下怎么输出接收到的值,就以接收电池电量来说吧,看代码:

if ([[characteristic UUID] isEqual:[CBUUID UUIDWithString:@"2A19"]]){

const unsigned char *hexBytesLight = [characteristic.valuebytes];

NSString * battery = [NSStringstringWithFormat:@"%02x", hexBytesLight[0]];

NSLog(@"batteryInfo:%@",battery);

}

其实,外设向IOS这边发数据,都会自动回调上面的那个方法,因此你接收外设发送过来的数据,也只能在这个方法里面,通过不同的特征值判断是哪个UUID发送过来的,解析出数据再执行相应的动作就可以了,好了到这里我们应该很清楚IOS和外设是怎么进行数据沟通的了,如果还想深入就靠你自己了,当然我们最后再说一点,如果连接上的两个设备突然断开了,程序里面会自动回调下面的方法:

-   (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error

在这个方法里面,我们可以做一些补救措施,比如回连,我们就可以在这个方法里写上:

[_centralMan connectPeripheral:_peripheral options:nil];

从这个方法里,我们还可以输出连接断开的原因:我们这样写:error.code,跟进去看会发现错误的原因有很多种,比如说CBErrorConnectionTimeout,CBErrorOperationCancelled,CBErrorPeripheralDisconnected,你可以根据错误的原因来进行不同的动作,好了,其实还有很多的回调方法,大家可以去看苹果官方的文档,这里只列出了一些常用的而已,水平有限,有不到之处,还请指证!如果大家还有什么疑问可以加我 QQ:631965569;额,最好还是发邮件到QQ邮箱吧!

最近两天写了一个demo,放在Github上面了,地址是:https://github.com/Allen-L/BLE4.0-Demo-IOS.git ,模仿lightblue写的,由于各种原因,没有写完全,可供参考,转载http://m.blog.csdn.net/blog/liang_ke_ke/39251951

时间: 2024-08-08 13:52:53

IOS BLE4.0蓝牙和外设连接和收发数据的流程的相关文章

IOS学习之蓝牙4.0

转载请注明出处 作者:小马 IOS学习也一段时间了,该上点干货了.前段时间研究了一下IOS蓝牙通讯相关的东西,把研究的一个成果给大家分享一下. 一 项目背景 简单介绍一下做的东西,设备是一个金融刷卡器,通过蓝牙与iphone手机通讯.手机端的app通过发送不同的指令(通过蓝牙)控制刷卡器执行一些动作,比如读磁条卡,读金融ic卡等.上几张图容易理解一些:              看了上面几张图,你应该大概了解这是个什么东东了. 二 IOS 蓝牙介绍 蓝牙协议本身经历了从1.0到4.0的升级演变,

iOS开发- 蓝牙后台接收数据(BLE4.0)

最近在做一个蓝牙相关的项目, 需要在应用进入后台, 或者手机属于锁屏状态的情况下, 仍然保持蓝牙连接, 并且能正常接收数据. 本来以后会很麻烦, 但是学习了下..发现就2步而已.简单的不能再简单了. 好了.下面是具体实现办法. 1.在xxx-info.plist文件中, 新建一行  Required background modes , 加入下面两项. App shares data using CoreBluetooth 和  App communicates using CoreBlueto

Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探

Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便写下这篇博客心得 Google API:http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#terms 其实大家要学习Android的技术,Google的API就是最详细的指导书了,而且通俗易懂,就算看不懂

iOS蓝牙接收外设数据自动中断

一.错误原因 在做iOS设备作为central,与蓝牙外设连接,接收蓝牙外设传输的数据时发生蓝牙中断. 在- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error方法报Code=6 "The connection has timed out unexpectedly错误. 二.解决办法 找

Android项目实战(三十四):蓝牙4.0 BLE 多设备连接

原文:Android项目实战(三十四):蓝牙4.0 BLE 多设备连接 最近项目有个需求,手机设备连接多个蓝牙4.0 设备 并获取这些设备的数据. 查询了很多资料终于实现,现进行总结. -------------------------------------------------------------------------------------------------------------------------------------------------------------

iOS CoreBluetooth 教程 蓝牙

去App Store搜索并下载"LightBlue"这个App,对调试你的app和理解Core Bluetooth会很有帮助. ================================ Demo下载地址:http://download.csdn.net/detail/jimoduwu/7146875 ================================ Core Bluetooth for iOS 6 CoreBluetooth的API是基于BLE4.0的标准的.这

iOS开发之蓝牙(二)CoreBluetooth

Core Bluetooth的使用场景 运动手环.智能家居.嵌入式设备等等(金融刷卡器.心电测量器) Core Bluetooth测试比较麻烦,正常情况下,得至少有2台真实的蓝牙4.0设备 Core Bluetooth的核心结构图 Core Bluetooth的基本常识 Core Bluetooth的基本常识 每个蓝牙4.0设备都是通过服务(Service)和特征(Characteristic)来展示自己的 一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征 特征是与外界交互的最小单位

IOS系统之蓝牙外接设备

Ios系统对于蓝牙外接设备在iphone4以前都是蓝牙2.0的时候,需要通过苹果的审核,据统计通过率仅有2%左右,现在蓝牙2.0基本上处于淘汰状态,所以在这里就不考虑了. 现在iphone4s以后的设备(包括iphone4s.iPhone5.iphone5s.iphone6.iphone6s)的设备中都使用的是蓝牙4.0,所以我们讲一下蓝牙4.0的外接设备的使用. 蓝牙4.0的设备在使用的时候,不需要通过苹果公司外接设备的审核,所以使用起来会相对容易一些! 在使用的时候我们需要导入CoreBlu

ble4.0 app后台运行、报警、通知实现

先把收集到有用资料整理一下,等项目完成再写篇文章 app在后台播放报警音:https://developer.apple.com/library/ios/qa/qa1668/_index.html 后台运行设置:http://blog.shiqichan.com/ios-ble-background-central-scanning/ http://blog.csdn.net/monsterguaishou/article/details/36013659 蓝牙app后台运行接收数据.通知设定: