//
// BleUtil.m
// yu
//
// Created by CharkWong on 2019/5/14.
// Copyright © 2019 CharkWong. All rights reserved.
//
#import “BleUtil.h”
#import “…/context/DataBox.h”
NSString const SERVICE_UUID = @"6E400001-B5A3-F393-E0A9-E50E24DCC**";
NSString const TX_WRITE_UUID = @"6E400002-B5A3-F393-E0A9-E50E24DC***";
NSString const RX_NOTIFY_UUID = @"6E400003-B5A3-F393-E0A9-E50E2***A9E";
@interface BleUtil ()<CBCentralManagerDelegate,CBPeripheralDelegate>
//手机
@property(nonatomic,strong)CBCentralManager *centralManager;
//蓝牙外设
@property(nonatomic,strong)CBPeripheral *peripheral;
//扫描外设数组
@property(nonatomic,strong)NSMutableArray<CBPeripheral *> *scanArr;
//写入外设回调
@property(nonatomic,copy)NSMutableData *(^writeBlock)(void);
//连接外设回调
@property(nonatomic,copy)void(^connectBlock)(NSError *);
@end
@implementation BleUtil
//单例
- (instancetype)getSingleton {
static BleUtil *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 要使用self来调用
_sharedSingleton = [[self alloc] init];
// centralMgr = [_sharedSingleton getCentralMgr];
});
return _sharedSingleton;
}
-(CBCentralManager *)centralManager{
if(_centralManager == nil){
//创建蓝牙
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
return _centralManager;
}
//检测蓝牙是否可用
-
(BOOL)availableBluethooth
{
CBManagerState state = [self.centralManager state];
/**
CBManagerStateUnknown = 0,未知(第一次启动蓝牙中心是未知状态)
CBManagerStateResetting,蓝牙不可用 (未知错误)
CBManagerStateUnsupported,当前手机不支持蓝牙
CBManagerStateUnauthorized,//未授权
CBManagerStatePoweredOff,//蓝牙关闭
CBManagerStatePoweredOn,//蓝牙可用
*/
BOOL flag = NO;
NSString *stateStr;
switch (state) {
case CBManagerStateUnknown:
stateStr = @“第一次启动蓝牙”;
flag = YES;
break;
case CBManagerStateResetting:
stateStr = @“蓝牙不可用”;
break;
case CBManagerStateUnsupported:
stateStr = @“蓝牙未授权”;
break;
case CBManagerStatePoweredOff:
stateStr = @“蓝牙关闭”;
//实际开发中可以给用户一个弹窗提示 点击跳转到系统蓝牙设置界面
break;
case CBManagerStatePoweredOn:
flag = YES;
stateStr = @“蓝牙可用”;break; default: break;
}
NSLog(@“BleUtil stateStr=%@”,stateStr);
return flag;
}
#pragma mark -连接外设
-
(void)connectPeripheral:(void(^)(NSError *))connBlock Completion:(NSMutableData *(^)(void))writeBlock
{
NSAssert([self availableBluethooth] == YES, @“BleUtil当前蓝牙不可用,请检查蓝牙状态”);NSString *uuidStr = [DataBox getBlePeripheralsUUID];
if(uuidStr == nil){
NSLog(@“UUID为空!”);
return;
}
//[self.centralManager scanForPeripheralsWithServices:nil options:nil];
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidStr];
NSArray *arr = [self.centralManager retrievePeripheralsWithIdentifiers:[NSArray arrayWithObject:uuid]];
CBPeripheral *per = [arr lastObject];
// CBPeripheral *per = nil;
// for(CBPeripheral *pera in _scanArr){
// if([pera.identifier.UUIDString isEqualToString:uuidStr]){
// per = pera;
// break;
// }
// }
if(per == nil){
NSLog(@“找不到蓝牙设备!”);
return;
}
NSLog(@“state:%ld==%ld”,(long)per.state,(long)CBPeripheralStateDisconnected);
if(per.state == CBPeripheralStateDisconnected){
[self.centralManager connectPeripheral:per options:nil];
}
//保存连接回调
self.connectBlock = connBlock;
self.writeBlock = writeBlock;
}
//发现蓝牙设备监听
-
(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
NSString *perName = peripheral.name;if(perName == nil){
return;
}
NSLog(@“扫描成功,发现蓝牙设备!”);
if (self.scanArr == nil) {
self.scanArr = [[NSMutableArray alloc] init];
}
if([_scanArr containsObject:peripheral]){
return;
}
[_scanArr addObject:peripheral];
}
//已连接蓝牙设备监听
-
(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@“BleUtil已经连接设备:%@”, peripheral.name);
if (self.connectBlock) {
self.connectBlock(nil);
}
[self.centralManager stopScan];
//1.先保存外设
self.peripheral = peripheral;
//2.设置外设的代理
self.peripheral.delegate = self;#pragma mark -流程4 开发发现外设的服务
//如果没有寻找服务的话,外设的服务数组是空
//3.寻找外设的服务,为nil则表示寻找所有的服务
[self.peripheral discoverServices:nil];
// for (CBService *service in peripheral.services) {
// // 找到对应的服务
// if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_UUID]]) {
// // 查找特征
// [peripheral discoverCharacteristics:nil forService:service];
// break;
// }
// }
// //搜索服务
// NSMutableData *data=[[NSMutableData alloc] initWithCapacity:0];
// int8_t byte0 = 0x51;
// [data appendBytes:&byte0 length:sizeof(byte0)];
// int8_t byte1 = 0x01;
// [data appendBytes:&byte1 length:sizeof(byte1)];
// int8_t byte2 = 0x01;
// [data appendBytes:&byte2 length:sizeof(byte2)];
// //写入
// [peripheral writeValue:data forCharacteristic:chara type:CBCharacteristicWriteWithResponse];
}
//连接蓝牙设备监听失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@“蓝牙连接失败:%@”,error);
if (self.connectBlock) {
self.connectBlock(error);
}
}
//发现服务监听
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error
{
NSLog(@“BleUtil发现服务!”);
for (CBService *service in peripheral.services) {
// 找到对应的服务
if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_UUID]]) {
// 查找特征
[peripheral discoverCharacteristics:nil forService:service];
break;
}
}
}
//发现特征值监听
-
(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
for (CBCharacteristic *chara in service.characteristics) {
if ([[chara UUID] isEqual:[CBUUID UUIDWithString:TX_WRITE_UUID]]){
NSMutableData *data = nil;
if (self.writeBlock) {
data = self.writeBlock();
}
if(data != nil){
//写入
[peripheral writeValue:data forCharacteristic:chara type:CBCharacteristicWriteWithResponse];
//NSLog(@“找到可写特征: %@”, chara);
NSLog(@“BleUtil开始写入成功!”);
}else{
NSLog(@“BleUtil开始写入失败!”);
}} if ([[chara UUID] isEqual:[CBUUID UUIDWithString:RX_NOTIFY_UUID]]){ // 监听外设特征值 [peripheral setNotifyValue:YES forCharacteristic:chara]; // 读取特征数据 [peripheral readValueForCharacteristic:chara]; //NSLog(@"找到可读特征 : %@", chara); }
}
}
//向peripheral中写入数据后的回调函数
- (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(@“BleUtil写入成功: %@”, characteristic.value);
}
#pragma mark- 获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取。
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(@“外设发送过来的数据:%@”,characteristic.value.description );
}
#pragma mark- 中心读取外设实时数据
-
(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {}
if (characteristic.isNotifying) {
//读取外设数据
[peripheral readValueForCharacteristic:characteristic];
NSLog(@“BleUtil%@”,characteristic.value);
} else {}
} -
(void)centralManagerDidUpdateState:(nonnull CBCentralManager *)central {
switch (central.state) {
case CBManagerStateUnknown:
{
NSLog(@“BleUtil无法获取设备的蓝牙状态”);
}
break;
case CBManagerStateResetting:
{
NSLog(@“BleUtil蓝牙重置”);
}
break;
case CBManagerStateUnsupported:
{
NSLog(@“BleUtil该设备不支持蓝牙”);
}
break;
case CBManagerStateUnauthorized:
{
NSLog(@“BleUtil未授权蓝牙权限”);
}
break;
case CBManagerStatePoweredOff:
{
NSLog(@“BleUtil蓝牙已关闭”);
}
break;
case CBManagerStatePoweredOn:
{
NSLog(@“BleUtil蓝牙已打开”);
}
break;default: { NSLog(@"BleUtil未知的蓝牙错误"); } break;
}
}
@end
如果蓝牙已连接成功,再重新扫描蓝牙并尝试连接,找到的蓝牙CBPeripheral为空,不能再重复使用CBPeripheral。只有把连接好的CBPeripheral放到外部全局变量中,让其他类访问。