一: 介绍
近几年,智能设备越来越火,这些智能设备中,有很大一部分是通过手机来控制硬件设备,来达到预期的效果,这中间少不了要使用到蓝牙功能,通过蓝牙来通信来控制设备。
蓝牙分为蓝牙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获取方法
如果需要源码demo,欢迎关注 【网罗开发】微信公众号,回复【94】便可领取。
网罗天下方法,方便你我开发,所有文档会持续更新,欢迎关注一起成长!
欢迎关注公众号「网罗开发」