藍牙使用 iOS小結

做了一個單例
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];
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章