转载自https://www.jianshu.com/p/f0e4b0e98336
2015年的时候自己写过一个蓝牙4.0项目,当忘了写博客,最近看到这篇博客写的挺详细,所以转载一下
一: 介绍
蓝牙分为蓝牙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); } }