FZBluetooth
ios 蓝牙原生封装,助力智能硬件开发
最近公司在做硬件设备,作为一名 iOS 开发人员,主要负责手机软件、硬件的连接方面,开发连接硬件使用的 SDK,其中主要模块是蓝牙连接,通过蓝牙与硬件设备连接,发送指令使硬件工作。 说起来很简单,但是寻找了好几天的蓝牙方面的 Demo,看到了很多前人大神们封装的 Bluetooth 方法,感觉对于我等小白实在是有点深奥,方法繁多,不知从何处下手。所以最后考虑再三,还是从底层基础入手,自己重新整理、封装了一份蓝牙的查找、连接、写入、断开的类,本着程序员的开源精神,分享出来,欢迎大家指正。
使用 Cocoapods 导入
FZBluetooth 可在 CocoaPods 上使用。将以下代码添加到 Podfile 中
pod "FZBluetooth","~>1.0.0"
目录
方法说明简介
系统蓝牙状态监听
这个功能很方便,可以通过系统蓝牙方法 centralManagerDidUpdateState 来实时获取蓝牙状态的变化,因此可以用一个 Block 回调来获得状态,并据此进行操作。
方法代码如下:
/**
系统当前蓝牙的状态
@paramstateBlock 实时返回当前蓝牙状态
*/
- (void)returnBluetoothStateWithBlock:(FZStateUpdateBlock)stateBlock;
蓝牙搜索
蓝牙搜索的功能方法中,使用系统原生方法`scanForPeripheralsWithServices:options:`,在蓝牙搜索的代理方法`centralManager:didDiscoverPeripheral:advertisementData:RSSI:`中获取搜索结果,并使用Block返回搜索结果。另外,添加了通过设置参数`nameStr`来筛选返回设备名称的方法,`nameStr`是设备模糊搜索参数,设备中包含`nameStr`字段即可返回搜索结果。
封装后的代码调用方法如下:
/*
* 开始搜索蓝牙外设,每次在block中返回一个蓝牙外设信息
*@paramnameStr 模糊搜索设备名称,目标设备名称包含字段
* 返回的block参数可参考CBCentralManager 的centralManager:didDiscoverPeripheral:advertisementData:RSSI:
*@paramdiscoverBlock 搜索到蓝牙外设后的回调
*/
- (void)scanForPeripheralsWithPrefixName:(NSString *)nameStr discoverPeripheral:(FZDiscoverPeripheralBlock)discoverBlock;
蓝牙设备的连接
蓝牙连接使用系统方法`connectPeripheral:options:`,连接设备结果通过代理方法`centralManager:didConnectPeripheral:`返回成功,通过`centralManager:didFailToConnectPeripheral:error:`返回失败。通过两个Block分别返回成功和失败信息。其中成功后要停止搜索`stopScan`,失败时要返回失败原因。
代码方法如下:
/*
* 连接某个蓝牙外设,并查询服务,特性,特性描述
*@paramperipheral 要连接的蓝牙外设
*@paramcompletionBlock 操作执行完的回调
*/
- (void)connectPeripheral:(CBPeripheral *)peripheral completeBlock:(FZConnectSuccessBlock)completionBlock failBlock:(FZConnectFailBlock)failBlock;
设备的自动连接设置
设备的自动连接,这里我写了两种方法,大家可以根据各自喜好自由选择。
1.根据设备peripheral自动连接
方法代码如下:
/**
设置或删除自动连接设备
设置后,在代理方法connectionWithPerpheral:里会返回设备的peripheral
@param setOrDel 自动连接和删除自动连接
@param peripheral 设备peripheral
*/
-(void)createAutomaticConnectionEquipmenWithSetOrDelate:(AutomaticConnectionEquipmenEnum)setOrDel Peripheral:(CBPeripheral *)peripheral;
该方法中`setOrDel`有两个枚举值,分别为:`SetAutomaticConnectionEquipmen`(设置自动重连)和`DelateAutomaticConnectionEquipmen`(删除自动重连)。
使用方法:
设置自动重连设备后,这里传入的`peripheral`会自动保存,服从代理:`FZAutomaticConnectionDelegate`,在代理方法中可以获取到重连的设备`peripheral`,然后进行连接操作。
/**
自动连接的设备代理方法
*/
- (void)connectionWithPerpheral:(CBPeripheral *)peripheral;
删除自动重连设备,调用代理方法即可。
2.通过设备UUID自动连接
代码方法如下:
/**
通过UUID获取peripheral
用户自主记录想要自动连接的UUID,获取peripheral后调用连接方法
@param UUIDString UUID
@return peripheral
*/
- (CBPeripheral *)retrievePeripheralWithUUIDString:(NSString *)UUIDString;
使用方法: 获取到设备的UUID后,使用此方法得到设备的`peripheral`,然后调用连接设备的方法即可自动重新连接。
写入数据
写入数据,在大多数的第三方方法中会有UUID、characteristic、peripheral等许多参数,容易混乱且难以理解。这里我封装后只留了一个characteristic特性参数,并且已经帮大家进行了筛选,可以在封装方法头文件中直接获取。另一方面,写入内容可以使用NSString类型,内部会自动将其转换为NSData格式写入设备。
写入数据原生方法为`writeValue:forCharacteristic:type:`,写入数据后会在代理方法`peripheral:didWriteValueForCharacteristic:error:`中得到是否写入成功的信息,成功与否通过Block返回结果。另外,如果蓝牙设备有应答时,会在`peripheral:didUpdateValueForCharacteristic:error:`方法中返回,处理起来相对复杂,我下面封装了两种方法,一种通过Block异步返回结果,另一种为同步返回应答结果,大家可以根据需求自由选择。
1.异步Block方式返回结果
代码封装后的接口为:
/*
* 往某个特性中写入数据
*@paramcharacteristic 特性对象
*@paramcompletionBlock 写入完成后的回调,只有type为CBCharacteristicWriteWithResponse时,才会回调
*/
- (void)writeValue:(NSString *)dataStr forCharacteristic:(CBCharacteristic *)characteristic completionBlock:(FZWriteToCharacteristicBlock)completionBlock returnBlock:(FZEquipmentReturnBlock)equipmentBlock;
2.同步返回结果
接口方法为:
/**
* 往某个特性中写入数据,同步返回结果
* @param dataStr 写入的数据
* @param characteristic 特性对象
* @return 设备应答结果 returnStr 应答内容 error 错误信息
*/
-(NSDictionary *)writeValue:(NSString *)dataStr forCharacteristic:(CBCharacteristic *)characteristic;
同步返回的字典中有两个参数:returnStr和error,returnStr为设备应答数据,error为错误信息。当error为nil时表示成功,此时可以直接通过returnStr进行下一步操作。
这里需要注意的是:在实际开发中,可以使用名为lightBlue的蓝牙开发辅助APP查看设备有多少特征值,以及实际使用时需要查询哪个特征值。可以直接向硬件厂商或硬件开发人员咨询。在调用写入方法前,设置封装类中属性UUIDString的对应值,可以确保连接过程中稳定且不出问题。
蓝牙的断开
蓝牙的断开操作只有一个方法,用于断开当前连接的设备。使用系统原生方法cancelPeripheralConnection:,设备信息在连接时已自动记录,因此不需要传入参数。
代码封装后的方法如下:
/*
* 断开蓝牙连接
*/
- (void)readRSSICompletionBlock:(FZGetRSSIBlock)getRSSIBlock;
其他
其他的方法,在头文件中开放了三个方法:“RSSI转距离double类型数据”、“NSData转16进制字符串”、“NSString类型转NSData类型数据”。