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];