前言
公司一直在做和 POS机的相关工作,就是厂家把 POS机器送给我们,我们把 POS机根据厂家的 SDK添加到我们自己的安卓和应用程序上.安卓那边老早就已经封装了一套自己蓝牙的东西,统一搜索调用,很好管理.但是 iOS 端一直是分开使用厂家自带的 SDK. 这种做法,最开始自己深知就是埋了一颗雷,果不其然,上周功能迭代,终于要求实现自动重连
和绑定设备
的功能模块,自己封装一套蓝牙搜索工具类,成必须的了.
蓝牙技术, 在看iOS中目前提供了四个蓝牙的实现方案.我自己知道的是 GameKit和 CoreBluttooth.但是这里因为我项目的原因,我这里只讲到 CoreBluetooth相关的介绍标题提到的那三小块. 我们最常用的,最火热的也正好是 CoreBluetooth.
看到这里,大家肯定觉得什么情况,就这么点东西.好在,天无绝人之路,这里隆重的推荐我的大学同学即SwiftGG翻译组的 Miss.唐. Miss.唐在去年跑到深圳之后,就在一家蓝牙硬件和软件通讯的貌似是做玩具的公司开始了她辉煌的蓝牙4.0生涯.我很早就看到她在个站上关于 CoreBluetooh 的文章,涵盖了基础的定义
,搜索链接
,自动重连
,数据交互
等等.各位看官完全可以在我这篇后,完全可以细读Miss.唐的八篇文章,读完,你做手头的工作基本差不多了.
八篇CoreBluetooth 文章!让你遨游在和蓝牙4.0设备交互的海洋!!感谢 Miss.唐
当然,大家看我的这篇文章再看上边八篇,也是极好的.
今天的.....这篇前言好长....废话好多!!!!!
iOS 中蓝牙的四种实现方案
直接贴上某培训机构的 PPT 截图,足够简明,如下:
CoreBluetooth简介
核心结构
- 第一行中,
CBCentral
和CBPeripheral
即中心和周边,这两个是相对且角色可以互换的.最简单的例子就是两个手机. A手机(central)搜索连接到到 B手机(peripheral),也可以 B手机(central)搜索连接到到 A手机(peripheral).
同时,我们前边提到蓝牙设备之间的数据交换.CBPeripheral
的CBCentral
之间的数据交换是相互的.那就意味两者其实都能够彼此对对方发出的请求(我们这里叫做他们在发送广播)做出响应,这就各自需要一个控制器类,即CBCentralManager
和 CBPeripheralManager
.达到和对方'控制'和'沟通'的效果.
- 第二行中,
CBService
和CBCharacteristic
,是归属于CBPeripheral,每个周边蓝牙4.0设备就是通过服务(Service)和特征(Characteristic)来展示自己的.再或者引用 Miss唐原文中的话来说:
当你操作 peripheral 的时候,实际上是在和它的 service 和 characteristic 打交道,这两个分别由CBService和CBCharacteristic表示。
一个 CBPeripheral 包含多个 service,而一个 service 又可以包含多个 characteristic(前半句:service 可以包含 service 或者 characteristic。
后半句:service 本身的信息很少,更为详细的 service 信息意思就是,它里面包含哪些 characteristic,然后 characteristic 的信息就作为 service 信息的补充。). 所以他们的关系大致可以表示为:
在设备充当时,CBPeripheralManager这个类提供的主要方法则是对 service 的管理,同时还兼备着向 central 广播数据的功能. CBPeripheralManager处理的是可变的 service 和 characteristic,分别由CBMutableService和CBMutableCharacteristic表示
- 第三行中,
CBUUID
和CBATTRequest
.关于CBUUID
,引自《iOS CoreBluetooth 教程》的一段描述,如下:
每一个服务和特征都需要用一个UUID(unique identifier)去标识,UUID是一个16bit或者128bit的值。如果你要创建你的中央-周边App,你需要创建你自己的128bit的UUID。你必须要确定你自己的UUID不能和其他已经存在的服务冲突。如果你正要创建一个自己的设备,需要实现标准委员会需求的UUID;如果你只是创建一个中央-周边App(就像我们现在做的这样),我建议你打开Mac OS X的Terminal.app,用uuidgen命令生成一个128bit的UUID。你应该用该命令两次,生成两个UUID,一个是给服务用的,一个是给特征用的。然后,你需要添加他们到中央和周边App中。现在,在view controller的实现之前,我们添加以下的代码:
>static NSString * const kServiceUUID = @"312700E2-E79-4D5C-8DCF-49908332DF9F";
static NSString * const kCharacteristicUUID = @"FFA28CDE-6525-4489-801C-1C060CAC9767";
注意:你自己用uuidgen生成的UUID和我的是不一样的。
上边提到的UUID,即是 CBUUID.另外,在scanForPeripheralsWithServices:options:
方法中,我们还可以根据 CBUUID 来指定@[UUID1,UUID2]的设备.
CBATTRequest
是我们在对characteristics进行操作的时候,系统代理方法中的一个结果参数.比如,下边这个方法:
//读characteristics请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{
}
CoreBluetooth(搜索(自定义选择列表)+连接+自动重连)
Demo 描述
Demo 已经写完了,这里和大家简单说一下,这个 Demo 的流程.本来打算写一个的,但是写着写着,发现还是 Miss.唐的 Demo 里的流程和我需求十分相近.虽然,有几个地方我感觉到有点可疑,但是经过测试和验证之后,发现 Miss.唐的已经足够正确.所以我的流程和她的基本相近,当然,我也做了部分优化,加入了自定义的类似 UIAlertView 的选择列表框.
首先,工具类是继承自 NSObject, 因为是自动重连还是重新搜索
是每次执行工具类,最先应该判断的,所以直接放到了初始化-(instancetype)init
方法中,是否自动重连的依据就是本地偏好设置,是否保存了设备的 indentify.(这里要提依据,我们搜索到的 CBPeripheral 对象中的 identify 属性是描述蓝牙设备唯一性的类似于 mac 地址的东西,但是也需要注意,不同的 iOS设备 连接同一个 peripheral 获得的 identifier 是不一样的,然而这并不影响我们确定唯一的设备). 如果自动重连,则执行自动重连.如果不符合自动重连的条件,那么就执行重新搜索或者其他你自己公司需求规定的处理代码.
如果自动重连不成功,那么则我们可以进行搜索->连接
的步骤.
主要方法
1.初始化中心管理者
//1. 创建中心设备管理者,并且设置代理
//初始化方式一:,不会提示出现"打开蓝牙允许'xxxx'连接都配件"的系统提示
_myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
//初始化方式二
_myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
2.获取可以自动重连的设备
NSArray *resultArray = [NSArray arrayWithArray:[self.myCentralManager retrievePeripheralsWithIdentifiers:@[connentIdentify]]];
这个方法,是根据connentIdentify获取到自动重连设备数组,然后选择自动重连的设备(我的项目中只要求绑定一个设备),然后执行连接设备.
3.连接设备
[self.myCentralManager connectPeripheral:peripheral options:nil];
4.搜索周边蓝牙设备
//搜索蓝牙设备
[self.myCentralManager scanForPeripheralsWithServices:nil options:nil];
关于几个弯儿
1.最开始做自动重连的时候,我思路是,必须得保证搜索到的设备里边有需要自动重连的设备,我们才能够进行自动重连.其实,我们在执行retrievePeripheralsWithIdentifiers:
然后选择进行connectPeripheral:options:
连接的时候,对应的设备存在或者已经打开开关,是否连接成功就已经能够体现了.
另外,还有一种自动重连的思路就是:你还可以把自动重连的方法写在搜索方法里边.每次执行搜索设备方法的时候,进行判断,如果本地已经有了保存的绑定设备,那么就优先重新连接本地设备,如果没有的话,那么搜索设备.
CoreBluetooth补充
CoreBluetooth 的基本常识
CoreBluetooth 的开发步骤
Demo
还是直接看 Demo吧.
我的 Demo地址:我的 Demo 地址
Miss.唐的Demo地址:Miss.唐的Demo地址
推荐文章
Miss.唐的八篇 CoreBluetooth 文章:
1.《CoreBluetooth1 初识》
2.《CoreBluetooth2 作为 Central 时的数据读写》
3.《CoreBluetooth3 作为 Central 时的数据读写(补充)》
4.《CoreBluetooth4 作为 Central 时的数据读写(最佳实践》
5.《CoreBluetooth5 作为 Central 时的数据读写(OTA 固件升级与文件传输)》
6.《CoreBluetooth6 作为 Peripheral 时的请求响应》
7.《CoreBluetooth7 作为 Peripheral 时的请求响应(最佳实践)》
8.《CoreBluetooth8 后台运行蓝牙服务》
另一番推荐刘彦玮
的写的几篇:
1.《【投稿】iOS蓝牙开发(一)蓝牙相关基础知识》
2.《iOS 蓝牙开发(二)iOS 连接外设的代码实现》
3.《iOS 蓝牙开发(三)app作为外设被连接的实现》
4.《iOS 蓝牙开发(四)BabyBluetooth蓝牙库介绍》
其次,我还参考了,如下几篇文章:
希望能和大家交流技术
GitHub:https://github.com/lilongcnc