做了一个单例
h文件
#import
#import
NS_ASSUME_NONNULL_BEGIN
typedef void(^DidRefreshPeripherals)(void);
typedef void(^CentralManagerDidUpdateState)(CBManagerState state);
typedef void(^DidConnectPeripheral)(void);
typedef void(^DidFailToConnectPeripheral)(void);
typedef void(^DidDisconnectPeripheral)(void);
typedef void(^DidDiscoverServicesErr)(NSError *err);
typedef void(^GetConnectionStatus)(NSString *connectionStatus);
typedef void(^DidReceiveMSG)(int value);
@interface BluetoothCenter : NSObject
@property(strong,nonatomic) CBCentralManager *centerManager;//--------中心设备管理器
@property(strong,nonatomic) NSMutableArray *peripherals;//------------所有蓝牙外设
@property(strong,nonatomic) NSDictionary *currentPeripheral;//----------当前连接的外设
@property(copy)CentralManagerDidUpdateState centralManagerDidUpdateState;
@property(copy)DidRefreshPeripherals didRefreshPeripherals;
@property(copy)DidConnectPeripheral didConnectPeripheral;
@property(copy)DidFailToConnectPeripheral didFailToConnectPeripheral;
@property(copy)DidDisconnectPeripheral didDisconnectPeripheral;
@property(copy)DidDiscoverServicesErr didDiscoverServicesErr;
@property(copy)DidReceiveMSG didReceiveMSG;
@property (nonatomic ,assign) BOOL switchStatus;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 没有遵循协议可以不写
- (id)mutableCopy NS_UNAVAILABLE; // 没有遵循协议可以不写
+ (instancetype)sharedCenter;
//第四步:连接蓝牙设备
- (void)connectPeripheral:(CBPeripheral *)peripheral;
- (void)startScanPeripheral;
- (void)stopScanPeripheral;
@end
NS_ASSUME_NONNULL_END
m文件
#import "BluetoothCenter.h"
@implementation BluetoothCenter
// 跟上面的方法实现有一点不同
+ (instancetype)sharedCenter {
static BluetoothCenter *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 要使用self来调用
_sharedSingleton = [[self alloc] init];
[_sharedSingleton initCBCentralManager];
});
return _sharedSingleton;
}
#pragma mark ===== init =====
/*第一步:创建设备管理器
创建完之后,会回掉CBCentralManagerDelegate中的方法:- (void)centralManagerDidUpdateState:(CBCentralManager *)central
*/
-(void)initCBCentralManager
{
self.centerManager = [[CBCentralManager alloc] init];
self.centerManager = [self.centerManager initWithDelegate:self queue:nil];
self.peripherals = [NSMutableArray array]; //存放所有扫描到的蓝牙外设
NSLog(@"self.centerManager ===== %@",self.centerManager);
}
- (void)startScanPeripheral
{
if (self.centerManager.state == CBManagerStatePoweredOn)
{
//扫描蓝牙设备
[self.centerManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@(NO)}];
//key值是NSNumber,默认值为NO表示不会重复扫描已经发现的设备,如需要不断获取最新的信号强度RSSI所以一般设为YES了
}
}
- (void)stopScanPeripheral
{
if ([self.centerManager isScanning])
{
[self.centerManager stopScan];
// [ToolBox noticeContent:@"扫描结束" andShowView:self.view andyOffset:NoticeHeight];
}
}
//外设管理器状态发生变化,初始化centerManger后,会走这里
-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (self.centralManagerDidUpdateState) {
self.centralManagerDidUpdateState(central.state);
}
}
#pragma mark ===== CBCentralManagerDelegate =====
/*第三步:扫描完成,将发现设备的不重复地添加到外设数组中
这个代理方法每扫描到一个外设,就会进入一次。
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI//RSSI信号强度
{
NSString *locolName = [advertisementData objectForKey:@"kCBAdvDataLocalName"];//广播的名称(准确)
NSString *peripheralName = peripheral.name;//设备名称 (修改过的名称获取不到)
NSLog(@"locolName%@\n Discovered name:%@\n identifier:%@\n advertisementData:%@\n RSSI:%@\n state:%ld\n",locolName,peripheral.name, peripheral.identifier,advertisementData,RSSI,(long)peripheral.state);
locolName = locolName == nil ? @"" : locolName;
peripheralName = peripheralName == nil ? @"" : peripheralName;
#warning --做剔除--
NSString * name = locolName.length == 0 ? peripheralName : locolName;
if (![name containsString:@"xxxxxx"] ){
return;
}else{
[self connectPeripheral:peripheral];
NSDictionary *dict = @{@"peripheral":peripheral,@"locolName":locolName,@"peripheralName":peripheralName,@"advertisementData":advertisementData,@"RSSI":RSSI};
[self.peripherals addObject:dict];
return;
}
if (self.peripherals.count == 0)//无数据
{
NSDictionary *dict = @{@"peripheral":peripheral,@"locolName":locolName,@"peripheralName":peripheralName,@"advertisementData":advertisementData,@"RSSI":RSSI};
_currentPeripheral = dict;
//将已连接外设,置为当前外设
if(peripheral.state == CBPeripheralStateConnected)
{
[self.peripherals removeObject:dict];
}
}
else//有数据
{
BOOL isExist = NO;
for (int i = 0; i < self.peripherals.count; i++)
{
NSDictionary *dict = [self.peripherals objectAtIndex:i];
CBPeripheral *per = dict[@"peripheral"];
if ([per.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString])//扫描到的外设已有,替换
{
isExist = YES;
NSDictionary *dict = @{@"peripheral":peripheral,@"locolName":locolName,@"peripheralName":peripheralName,@"advertisementData":advertisementData,@"RSSI":RSSI};
[self.peripherals replaceObjectAtIndex:i withObject:dict];
}
//去除已连接的外设(判断是否是已连接的外设)
if (self.currentPeripheral)
{
CBPeripheral *currentPer = self.currentPeripheral[@"peripheral"];
if ([per.identifier.UUIDString isEqualToString:currentPer.identifier.UUIDString]) {
[self.peripherals removeObjectAtIndex:i];
}
}
}
if (!isExist)//(新扫描到的外设添加)
{
NSDictionary *dict = @{@"peripheral":peripheral,@"locolName":locolName,@"peripheralName":peripheralName,@"advertisementData":advertisementData,@"RSSI":RSSI};
[self.peripherals addObject:dict];
}
//将已连接外设,置为当前外设
if(peripheral.state == CBPeripheralStateConnected)
{
NSDictionary *dict = @{@"peripheral":peripheral,@"locolName":locolName,@"peripheralName":peripheralName,@"advertisementData":advertisementData,@"RSSI":RSSI};
[self.peripherals removeObject:dict];
self.currentPeripheral = dict;
}
}
if (self.didRefreshPeripherals) {
self.didRefreshPeripherals();
}
}
//第四步:连接蓝牙设备
- (void)connectPeripheral:(CBPeripheral *)peripheral
{
[self.centerManager connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES)}];
/*
CBConnectPeripheralOptionNotifyOnDisconnectionKey
在程序被挂起时,断开连接显示Alert提醒框
*/
// 设置外设的代理是为了后面查询外设的服务和外设的特性,以及特性中的数据。
[peripheral setDelegate:self];
}
/*第五步:连接成功后,调用扫描蓝牙外设服务的代理
[peripheral discoverServices:nil];
*/
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
//
// 连接外设成功后关闭扫描
[self.centerManager stopScan];
[peripheral discoverServices:nil];
_currentPeripheral = self.peripherals.firstObject;
[self.peripherals removeAllObjects];
if (self.didConnectPeripheral) {
self.didConnectPeripheral();
}
}
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error//连接失败代理
{
NSLog(@"didFailToConnectPeripheral====%@",error);
if (self.didFailToConnectPeripheral) {
self.currentPeripheral = nil;
self.didFailToConnectPeripheral();
}
}
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error//收到连接状态断开 代理
{
NSLog(@"已断开连接");
if (self.didDisconnectPeripheral) {
self.currentPeripheral = nil;
self.didDisconnectPeripheral();
}
}
#pragma mark ====== CBPeripheralDelegate =====
//配对成功后走
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSString *UUID = [peripheral.identifier UUIDString];
NSLog(@"didDiscoverServices:%@",UUID);
if (error)
{
if (self.didDiscoverServicesErr) {
self.didDiscoverServicesErr(error);
}
return;
}
CBUUID *cbUUID = [CBUUID UUIDWithString:UUID];
NSLog(@"cbUUID:%@",cbUUID);
for (CBService *service in peripheral.services)
{
NSLog(@"---service:%@",service.UUID);
//可以过滤 to do
//第六步:扫描到外设服务后,可以获取外设的服务特性 对外设的CBUUID进行所需的处理
// if ([service.UUID isEqual:@"Device Information"]) {
[peripheral discoverCharacteristics:nil forService:service];
//}
}
}
//发现特征回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
for (CBCharacteristic *characteristic in service.characteristics) {
NSLog(@"发现特征:%@",characteristic);
//订阅
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
//蓝牙交互
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
// characteristic.value
if (self.didReceiveMSG) {
}
}
@end
附 查询方法
//第二步:扫描蓝牙外设
- (void)scan:(id)sender
{
if (_timer)
{
[self stopTimer];
}
_timeNum = 30;
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerCount:) userInfo:nil repeats:YES];
[_timer fire];
[self startScanPeripheral];
}
- (void)startScanPeripheral
{
if ([BluetoothCenter sharedCenter].centerManager.state != CBManagerStatePoweredOn)
{
[ToolBox noticeContent:@"请检查蓝牙是否打开" andShowView:self.view andyOffset:NoticeHeight];
if ([_tableView.mj_header isRefreshing])
[_tableView.mj_header endRefreshing];
return;
}
#warning 当设置serviceUUIDs参数时,只返回指定的服务(官方推荐做法)
//扫描蓝牙设备
[[BluetoothCenter sharedCenter].centerManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@(NO)}];
//key值是NSNumber,默认值为NO表示不会重复扫描已经发现的设备,如需要不断获取最新的信号强度RSSI所以一般设为YES了
}
- (void)stopScanPeripheral
{
if ([[BluetoothCenter sharedCenter].centerManager isScanning])
{
[[BluetoothCenter sharedCenter].centerManager stopScan];
// [ToolBox noticeContent:@"扫描结束" andShowView:self.view andyOffset:NoticeHeight];
}
}