一: 介绍
近几年, 智能设备越来越火, 这些智能设备中, 有很大一部分是通过手机来控制硬件设备, 来达到预期的效果, 这中间少不了要使用到蓝牙功能, 通过蓝牙来通信来控制设备.
蓝牙分为蓝牙 2.0 和蓝牙 4.0. 蓝牙 2.0 为传统蓝牙, 传统蓝牙也称为经典蓝牙. 蓝牙 4.0 因为低耗电, 所以也叫做低功耗蓝(BLE), 它将三种规格集一体, 包括传统蓝牙技术, 高速技术和低耗能技术.
这篇文章用来介绍 BLE 4.0 的使用以及相关问题的解决.
二: BLE 的两种模式
BLE 的两种模式分为 CBCentralMannager 中心模式 和 CBPeripheralManager 外设模式, 在这里主要和大家分享 CBCentralMannager 中心模式的开发和使用.
CBCentralMannager 中心模式
以手机 (App) 作为中心, 连接其他外设的场景. 详细流程如下:
建立中心角色
扫描外设
发现外设
连接外设 4.1 连接失败 4.2 连接断开 4.3 连接成功
扫描外设中的服务 5.1 发现并获取外设中的服务
扫描外设对应服务的特征 6.1 发现并获取外设对应服务的特征 6.2 给对应特征写数据
订阅特征的通知 7.1 根据特征读取数据
CBPeripheralManager 外设模式
使用手机作为外设连接其他中心设备操作的场景. PS: 因为苹果设备的安全性和封闭性, 苹果设备不能通过与其他设备蓝牙链接进行文件传输等功能, 所以在 iOS 与蓝牙开发的编程中是 CBCentralMannager 中心模式编程居多.
建立外设角色
设置本地外设的服务和特征
发布外设和特征
广播服务
响应中心的读写请求
发送更新的特征值, 订阅中心
三: BLE 开发步骤
在介绍 CBCentralMannager 中心模式开发步骤之前, 首先需要对项目进行如下配置:
- #import "ESPFBYBLEHelper.h"
- #import <CoreBluetooth/CoreBluetooth.h>
- @interface ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
- // 中心管理者(管理设备的扫描和连接)
- @property (nonatomic, strong) CBCentralManager *centralManager;
- // 存储的设备
- @property (nonatomic, strong) NSMutableArray *peripherals;
- // 扫描到的设备
- @property (nonatomic, strong) CBPeripheral *cbPeripheral;
- // 外设状态
- @property (nonatomic, assign) CBManagerState peripheralState;
- @end
- // 蓝牙 4.0 设备名
- static NSString * const kBlePeripheralName = @"lighte290";
- // 通知服务
- static NSString * const kNotifyServerUUID = @"FF03";
- // 写服务
- static NSString * const kWriteServerUUID = @"FFFF";
- // 通知特征值
- static NSString * const kNotifyCharacteristicUUID = @"FF05";
- // 写特征值
- static NSString * const kWriteCharacteristicUUID = @"FF08";
- @implementation ESPFBYBLEHelper
这其中需要导入 CoreBluetooth 框架
#import <CoreBluetooth/CoreBluetooth.h>
遵守 CBCentralManagerDelegate,CBPeripheralDelegate 协议
@interface ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
然后需要检测蓝牙状态, 代码如下:
- // 状态更新时调用
- - (void)centralManagerDidUpdateState:(CBCentralManager *)central
- {
- switch (central.state) {
- case CBManagerStateUnknown:{
- NSLog(@"为知状态");
- self.peripheralState = central.state;
- }
- break;
- case CBManagerStateResetting:
- {
- NSLog(@"重置状态");
- self.peripheralState = central.state;
- }
- break;
- case CBManagerStateUnsupported:
- {
- NSLog(@"不支持的状态");
- self.peripheralState = central.state;
- }
- break;
- case CBManagerStateUnauthorized:
- {
- NSLog(@"未授权的状态");
- self.peripheralState = central.state;
- }
- break;
- case CBManagerStatePoweredOff:
- {
- NSLog(@"关闭状态");
- self.peripheralState = central.state;
- }
- break;
- case CBManagerStatePoweredOn:
- {
- NSLog(@"开启状态 - 可用状态");
- self.peripheralState = central.state;
- NSLog(@"%ld",(long)self.peripheralState);
- }
- break;
- default:
- break;
- }
- }
添加属性和常量, 常量需要根据自己的项目来进行配置. 下面只需要根据实现流程一步步实现即可, 核心代码如下:
1. 建立中心角色
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
2. 扫描外设
- if (self.peripheralState == CBManagerStatePoweredOn){
- [self.centralManager scanForPeripheralsWithServices:nil options:nil];
- }
3. 发现外设
- /**
- 扫描到设备
- @param central 中心管理者
- @param peripheral 扫描到的设备
- @param advertisementData 广告信息
- @param RSSI 信号强度
- */
- - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
- {
- NSLog(@"%@",[NSString stringWithFormat:@"发现设备, 设备名:%@",peripheral.name]);
- }
4. 连接外设
[self.centralManager connectPeripheral:peripheral options:nil];
4.1 连接失败 didFailToConnectPeripheral
- /**
- 连接失败
- @param central 中心管理者
- @param peripheral 连接失败的设备
- @param error 错误信息
- */
- - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
- {
- NSLog(@"%@",@"连接失败");
- }
4.2 连接断开
- /**
- 连接断开
- @param central 中心管理者
- @param peripheral 连接断开的设备
- @param error 错误信息
- */
- - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
- {
- NSLog(@"%@",@"断开连接");
- }
4.3 连接成功
- /**
- 连接成功
- @param central 中心管理者
- @param peripheral 连接成功的设备
- */
- - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
- {
- NSLog(@"连接设备:%@成功",peripheral.name);
- [self.centralManager stopScan];
- }
5. 扫描外设中的服务
- // 设置设备的代理
- peripheral.delegate = self;
- // services: 传入 nil 代表扫描所有服务
- [peripheral discoverServices:nil];
5.1 发现并获取外设中的服务
- /**
- 扫描到服务
- @param peripheral 服务对应的设备
- @param error 扫描错误信息
- */
- - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
- {
- // 遍历所有的服务
- for (CBService *service in peripheral.services)
- {
- NSLog(@"服务:%@",service.UUID.UUIDString);
- }
- }
6. 扫描外设对应服务的特征
- // 获取对应的服务
- if (![service.UUID.UUIDString isEqualToString:kWriteServerUUID])
- {
- return;
- }
- // 根据服务去扫描特征
- [peripheral discoverCharacteristics:nil forService:service];
6.1 发现并获取外设对应服务的特征
- /**
- 扫描到对应的特征
- @param peripheral 设备
- @param service 特征对应的服务
- @param error 错误信息
- */
- - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
- {
- NSLog(@"%@",peripheral);
- }
6.2 给对应特征写数据
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
7. 订阅特征的通知
- if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]){
- [peripheral setNotifyValue:YES forCharacteristic:characteristic];
- }
7.1 根据特征读取数据 didUpdateValueForCharacteristic
- /**
- 根据特征读到数据
- @param peripheral 读取到数据对应的设备
- @param characteristic 特征
- @param error 错误信息
- */
- - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error
- {
- if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
- {
- NSData *data = characteristic.value;
- NSLog(@"%@",data);
- }
- }
四: 源码 Demo 获取方法
来源: https://juejin.im/post/5c98b4bd5188252db02e55d7