Bluetooth 4.0 完整使用

1、首先先對藍牙狀態的一種識別,使用ENUM進行狀態判別,分別使用<span style="font-family: Arial, Helvetica, sans-serif;">BluetoothState表示藍牙連接狀態和</span><span style="font-family: Arial, Helvetica, sans-serif;">BluetoothFailState表示藍牙連接失敗的狀態,對BluetoothState和BluetoothFailState設置成全局變量,如下方所示</span>
</pre><pre name="code" class="objc">typedef NS_ENUM(NSInteger, BluetoothState){
    BluetoothStateDisconnect = 0,
    BluetoothStateScanSuccess,
    BluetoothStateScaning,
    BluetoothStateConnected,
    BluetoothStateConnecting
};

typedef NS_ENUM(NSInteger, BluetoothFailState){
    BluetoothFailStateUnExit = 0,
    BluetoothFailStateUnKnow,
    BluetoothFailStateByHW,
    BluetoothFailStateByOff,
    BluetoothFailStateUnauthorized,
    BluetoothFailStateByTimeout
};

</pre><p>2、在連接界面,如<span style="font-family:Menlo; font-size:18px">IsConnectBleViewController,在.h文件中定義</span></p><p><span style="font-family:Menlo; font-size:18px"></span></p><p style="margin-top:0px; margin-bottom:0px; font-size:18px; line-height:normal; font-family:Menlo"></p><pre name="code" class="objc">@property (strong, nonatomic) CBCentralManager * centralManager;
@property (strong, nonatomic) CBPeripheral * discoveredPeripheral;
@property (strong, nonatomic) CBCharacteristic * writeCharachter;


IsConnectBleViewController.m文件中

//藍牙狀態  -- self.seachRssultLabel爲文本提示

- (void)bleState
{
    if (bluetoothFailState == BluetoothFailStateUnExit) {
        switch (bluetoothState) {
            case BluetoothStateConnected:
                self.searchResultLabel.text =[NSString stringWithFormat:@"%@",NSLocalizedString(@"已連接", nil)];
                
                break;
            case BluetoothStateConnecting:
                self.searchResultLabel.text = NSLocalizedString(@"連接中......", nil);
                
                break;
            case BluetoothStateDisconnect:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙已斷開", nil);
                
                break;
            case BluetoothStateScanSuccess:
                self.searchResultLabel.text = NSLocalizedString(@"搜索成功,請選擇你需要連接的藍牙設備", nil);
                break;
            case BluetoothStateScaning:
                self.searchResultLabel.text = NSLocalizedString(@"搜索中", nil);
                break;
            default:
                break;
        }
    }else {
        switch (bluetoothFailState) {
            case BluetoothFailStateByHW:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙硬件不支持", nil);
                break;
            case BluetoothFailStateByOff:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙關閉了", nil);
                break;
            case BluetoothFailStateByTimeout:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙連接超時", nil);
                break;
            case BluetoothFailStateUnauthorized:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙連接失敗", nil);
                break;
            case BluetoothFailStateUnKnow:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙連接錯誤", nil);
                break;
            case BluetoothFailStateUnExit:
                self.searchResultLabel.text = NSLocalizedString(@"藍牙連接中...", nil);
                break;
            default:
                break;
        }
    }
    
}


--------  搜索藍牙的辦法 -----

[self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @NO}];//搜索所有的藍牙服務
 self.centralManager.delegate = self;//必須遵循代理
 bluetoothState = BluetoothStateScaning;//藍牙狀態變爲搜索狀態
[self bleState];
[self performSelector:@selector(searchBluetoothJumpTimeOut) withObject:nil afterDelay:10];//10表示搜索時間,10秒沒有搜索到即定義爲連接超時
#pragma mark - 藍牙連接超時的方法
- (void)searchBluetoothJumpTimeOut
{
    
    if (bluetoothState == BluetoothStateScaning) {
        bluetoothFailState = BluetoothFailStateByTimeout;
        [self ScanBle];//超時之後 -- 的操作,如果不需要超時後繼續連接,則不需要這部步
        self.searchResultLabel.text = NSLocalizedString(@"藍牙連接超時,請重新搜索", nil);

    }
}

#pragma mark - 搜索藍牙
-(void)ScanBle{
    
    if(bluetoothFailState == BluetoothFailStateByTimeout){//連接超時
        [self.centralManager scanForPeripheralsWithServices:nil
                                                    options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @NO }];
        self.searchResultLabel.text = NSLocalizedString(@"正在搜索您的設備,請稍等...", nil);
        
        bluetoothState = BluetoothStateScaning;//藍牙狀態變化成可搜索狀態
        
        [self bleState];//藍牙的狀態
        
        [self performSelector:@selector(searchBluetoothJumpTimeOut) withObject:nil afterDelay:10];//如果連接超時
        
    }
    
    if(bluetoothFailState==BluetoothFailStateByOff){
        self.promptLab.text= NSLocalizedString(@"檢查您的藍牙是否開啓後重試", nil);//如果藍牙設備關閉,提示打開藍牙設備 -- 彈出視圖提示
        [self showPromptLab];
    }
     
}

#pragma mark CBCentralManagerDelegate --- 中心設備(手機)的代理方法,即上面定義的 self.centralManager.delegate = self;//必須遵循代理

監控手機的藍牙狀態,一旦藍牙被關閉可提醒

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (central.state != CBCentralManagerStatePoweredOn) {//end to do
        // In a real app, you'd deal with all the states correctly
        
        NSLog(@"fail, state is off.");
        
        switch (central.state) {
            case CBCentralManagerStatePoweredOff:

                self.searchResultLabel.text = NSLocalizedString(@"連接失敗了,請您再檢查一下您的手機藍牙是否開啓,然後再試一次吧", nil);
                bluetoothFailState = BluetoothFailStateByOff;
                break;

            case CBCentralManagerStateResetting:
                bluetoothFailState=BluetoothFailStateByTimeout;
                break;

            case CBCentralManagerStateUnsupported:
                self.searchResultLabel.text = NSLocalizedString(@"檢測到您的手機不支持藍牙4.0,所以建立不了連接.建議更換您的手機再試試。", nil);
                bluetoothFailState = BluetoothFailStateByHW;
                break;

            case CBCentralManagerStateUnauthorized:
                self.searchResultLabel.text = NSLocalizedString(@"連接失敗了,請您再檢查一下您的手機藍牙是否開啓,然後再試一次吧", nil);
                bluetoothFailState = BluetoothFailStateUnauthorized;
                break;

            case CBCentralManagerStateUnknown:
                bluetoothFailState = BluetoothFailStateUnKnow;
                self.searchResultLabel.text = @"";
                break;
                
            default:
                break;
        }
        
        return;
    }
    
    self.searchResultLabel.text = NSLocalizedString(@"藍牙已經開啓!點擊開始搜索連接你的設備", nil);
    bluetoothFailState = BluetoothFailStateUnExit;
    
}



/*

 中心設備掃描外圍設備

 */

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    
    
    if (peripheral == nil||peripheral.identifier == nil/*||peripheral.name == nil*/) {
        return;
    }

    /*
            藍牙列表去重,防止重複的出現 --- 將 外圍設備添加到數組中,主要針對多選,一對一可設置self.isConnectMuArra變成一個全局的peripheral
     */
    NSMutableArray * repetitionMuArray = [[NSMutableArray alloc]init];
    
    [repetitionMuArray addObject:peripheral];
    
    for (unsigned i = 0; i < repetitionMuArray.count; i++) {
        
        if ([self.isConnectMuArray containsObject:[repetitionMuArray objectAtIndex:i]] == NO) {
            [self.isConnectMuArray addObject:[repetitionMuArray objectAtIndex:i]];
        }
    }
    
    //搜索成功後,修改藍牙狀態
    bluetoothFailState = BluetoothFailStateUnExit;
    bluetoothState = BluetoothStateScanSuccess;//藍牙狀態爲搜索成功
    
    [self bleState];//中心設備狀態實時監控
    
    //輸出廣播名
    NSString *CBName1=[advertisementData valueForKeyPath:CBAdvertisementDataLocalNameKey];
    NSLog(@"廣播名1:%@",CBName1);
    
}


3、掃描設備成功後進行連接


for (int i = 0; i < self.isConnectMuArray.count ; i++) {
            CBPeripheral * selectPeripheral = self.isConnectMuArray[i];
                    [self.centralManager connectPeripheral:selectPeripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES}];
      }


連接之後執行連接的代理方法

#pragma mark - 已經連接藍牙設備
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{

    [self.centralManager stopScan];//連接成功後停止搜索
    
    bluetoothState=BluetoothStateConnected;
    [self bleState];
    //discoveredPeripheral是全部變量 多連接是否需要創建數組?
    discoveredPeripheral=peripheral;  /----   前面所說如果是需要一對一創建全局變量 -----  如果一對多,則選擇下面一步添加數組/
    discoveredPeripheral.delegate = self;
    [(sysDege).discoverPeripheralArray addObject:peripheral];//(sysDege).discoverPeripheralArray是全局數組    

     [peripheral discoverServices:@[[CBUUID UUIDWithString:UUID_SERVICE]]];//設置掃描 -- 外圍設備掃描自己的服務   UUID_SERVICE是硬件方面的序列號,可爲nil

    [[NSNotificationCenter defaultCenter]postNotificationName:@"ConnectSuccess" object:nil];//通知成功的消息
    
}

上一步連接成功外圍設備,就開始發送掃描服務的指令,在這裏執行掃描到服務的代理辦法

#pragma mark - 外圍設備已經被發現
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    if (error) {//如果發現錯誤
        NSLog(@"Error discovering services: %@", [error localizedDescription]);
        return;
    }

    NSLog(@"外圍設備已被發現peripheral.services%@",peripheral.services);
    
    for (CBService * service in peripheral.services) {
        
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:UUID_CHARACTERISTIC]] forService:service];//掃描到服務就可以發送掃描特性的指令
        
        return;
    }
    
}

#pragma mark - 外圍設備掃描到特性

-(void)peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    for (CBCharacteristic * achar in service.characteristics) {
        
        NSLog(@"外圍設備Discovered characteristic:CBCharacteristic * achar%@", achar);
        
        NSLog(@"service uuid:%@ characteristics UUID:%@,achar.value:%@",service.UUID,achar.UUID,achar.value);
        
#pragma mark - 掃描到特性後 設置讀寫
        [aPeripheral readValueForCharacteristic:achar];
        [aPeripheral setNotifyValue:YES forCharacteristic:achar];//修改通知的狀態
 
        //可讀寫的特性?
        if (self.writeCharachter != achar) {
            self.writeCharachter = achar;
            writeCharachter = achar;

        
        if (self.discoveredPeripheral != aPeripheral) {
            self.discoveredPeripheral = aPeripheral;
        }
	//可以通過不同的UUID進行發送不同的指令
	[self writeCommand:data];
    }
}

#pragma mark - 寫入特性

-(void)writeCommand:(NSData *)data{
    
    NSLog(@"writeCommand:(NSData *)data:%@",data);
    //    連接外圍設備爲空或者藍牙狀態爲斷開,退出
    if (self.discoveredPeripheral == nil||bluetoothState == BluetoothStateDisconnect) {
        return;
    }
    
    
    [self.discoveredPeripheral writeValue:data
                        forCharacteristic:self.writeCharachter
                                     type:CBCharacteristicWriteWithResponse];
    NSLog(@"write command is success");
     
}


//發送指令後可以得到硬件返回的信息


#pragma mark - 特性值變化

- (void) peripheral:(CBPeripheral *)aPeripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
              error:(NSError *)error
{
    
    
    NSLog(@"特性回調值:%@",characteristic);
    
    NSString *result = [[NSString alloc] initWithData:characteristic.value  encoding:NSUTF8StringEncoding];
    NSLog(@"特性回調值的溫度:%@",result);
  
}



連接不成功 -- 即斷開

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{

    self.discoveredPeripheral = nil;//斷開之後爲空  -- 一對一的方法,一對多爲(sysDege).discoverPeripheralArray數組清空
    bluetoothState = BluetoothStateDisconnect;
    [self bleState];
    self.searchResultLabel.text = NSLocalizedString(@"藍牙設備已經斷開了,請重新搜索", nil);

    [[NSNotificationCenter defaultCenter]postNotificationName:@"bleDis" object:nil];//發送藍牙斷開的通知 

}

藍牙發送數據 -- self.discoveredPeripheral表示外圍設備 --self.writeCharachter表示特性 
[self.discoveredPeripheral writeValue:data
                        forCharacteristic:self.writeCharachter
                                     type:CBCharacteristicWriteWithResponse];




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