做了一個單例
h文件
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
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<CBCentralManagerDelegate,CBPeripheralDelegate>
@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];
}
}