本來(lái)以為對(duì)手機(jī)系統(tǒng)藍(lán)牙已連接的設(shè)備的搜索炼蛤、連接、通信是使用ExternalAccessory框架的塘辅。后來(lái)和硬件部的溝通情龄,才發(fā)現(xiàn)ExternalAccessory框架是對(duì)Lightning接口的硬件或者藍(lán)牙(2.1)的設(shè)備才管用。我們使用的是ble協(xié)議的藍(lán)牙癣丧,所以不能使用ExternalAccessory框架槽畔。只能繼續(xù)找辦法。后來(lái)發(fā)現(xiàn)CBCentralManager類就能實(shí)現(xiàn)胁编。下面是CBCentralManager對(duì)系統(tǒng)藍(lán)牙已連接外設(shè)的搜索厢钧、連接的一個(gè)簡(jiǎn)單的Demo代碼。(連接成功自然就能發(fā)送指令了嬉橙,通信前要不要發(fā)送內(nèi)部協(xié)商的握手指令就看自己了)
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "XJConstants.h"
@interface ViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate>
/** 系統(tǒng)藍(lán)牙管理類 */
@property (nonatomic, strong) CBCentralManager *bleCentral;
/** 找到的指定的設(shè)備 */
@property (nonatomic, strong) CBPeripheral *findPeripheral;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 創(chuàng)建藍(lán)牙操作線程
dispatch_queue_t queue = dispatch_queue_create("xj.ble.thread", DISPATCH_QUEUE_CONCURRENT);
// 創(chuàng)建系統(tǒng)藍(lán)牙管理類
_bleCentral = [[CBCentralManager alloc] initWithDelegate:self queue:queue];
}
#pragma mark - CBCentralManagerDelegate
/** 藍(lán)牙連接狀態(tài)改變 */
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
XJBleLog(@"藍(lán)牙狀態(tài)改變 %ld",central.state);
// 如果藍(lán)牙不是開(kāi)啟狀態(tài)
if(central.state != CBManagerStatePoweredOn){ return; }
// 自定義的服務(wù)ID早直。注意這里是服務(wù)ID,不是設(shè)備的[peripheral.identifier UUIDString]這個(gè)值
CBUUID* serviceId = [CBUUID UUIDWithString:@"自定義的服務(wù)ID"];
// 根據(jù)自定義的服務(wù)ID找出手機(jī)系統(tǒng)已連接的設(shè)備
NSArray<CBPeripheral*>* peripheralArray = [_bleCentral retrieveConnectedPeripheralsWithServices:@[serviceId]];
// 如果沒(méi)有發(fā)現(xiàn)已經(jīng)連接的設(shè)備
if(peripheralArray.count == 0){
XJBleLog(@"沒(méi)有發(fā)現(xiàn)已連接的設(shè)備");
// -------------------- 掃描設(shè)備 -------------------
// 設(shè)置 不重復(fù)掃描已發(fā)現(xiàn)設(shè)備
NSDictionary *option = @{ CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO] };
// 開(kāi)始掃描
[_bleCentral scanForPeripheralsWithServices:nil options:option];
}else{
// 遍歷系統(tǒng)已連接的設(shè)備
for (CBPeripheral* peripheral in peripheralArray) {
NSString* deviceId = [peripheral.identifier UUIDString];
// 這里必須保存這個(gè)引用才可以連接設(shè)備成功市框,不然會(huì)連接失敗
self.findPeripheral = peripheral;
XJBleLog(@"存在設(shè)備 - peripheral.name: %@ 連接狀態(tài):%ld 設(shè)備ID: %@ ",peripheral.name, peripheral.state, deviceId);
[_bleCentral connectPeripheral:peripheral options:nil];
}
}
}
/**
* 發(fā)現(xiàn)外設(shè)
* advertisementData 是廣播的值霞扬,一般攜帶設(shè)備名,serviceUUIDs等信息
* RSSI絕對(duì)值越大枫振,表示信號(hào)越差喻圃,設(shè)備離的越遠(yuǎn)。如果想裝換成百分比強(qiáng)度粪滤,(RSSI+100)/100
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{
// 設(shè)備id
NSString* deviceId = [peripheral.identifier UUIDString];
// 設(shè)備名稱
NSString* deviceName = peripheral.name;
// 根據(jù)設(shè)備名找到指定設(shè)備
if([deviceName isEqualToString:@"自定義的設(shè)備名"]){
XJBleLog(@"發(fā)現(xiàn)設(shè)備 - peripheral.name: %@ RSSI: %@ 設(shè)備ID: %@",peripheral.name, RSSI, deviceId);
// 這里必須保存這個(gè)引用才可以連接設(shè)備成功斧拍,不然會(huì)連接失敗
self.findPeripheral = peripheral;
[_bleCentral connectPeripheral:peripheral options:nil];
}
}
/** 連接外設(shè)成功 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
// 設(shè)備id
NSString* deviceId = [peripheral.identifier UUIDString];
NSString* deviceName = peripheral.name;
XJBleLog(@"連接設(shè)備成功 - peripheral.name: %@ 連接狀態(tài):%ld 設(shè)備ID: %@ ",deviceName, peripheral.state, deviceId);
// 注意這里是服務(wù)ID,不是設(shè)備的[peripheral.identifier UUIDString]這個(gè)值
CBUUID* serviceId = [CBUUID UUIDWithString:@"自定義的服務(wù)ID"];
NSArray<CBPeripheral*>* peripheralArray = [_bleCentral retrieveConnectedPeripheralsWithServices:@[serviceId]];
for (CBPeripheral* peripheral in peripheralArray) {
XJBleLog(@"------已連接的設(shè)備 - peripheral.name: %@ 連接狀態(tài):%ld 設(shè)備ID: %@ ",peripheral.name, peripheral.state, deviceId);
}
}
/** 連接外設(shè)失敗 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{}
/** 已經(jīng)斷開(kāi)連接 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{}
#pragma mark - CBPeripheralDelegate
/** 發(fā)現(xiàn)服務(wù) */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{}
/** 發(fā)現(xiàn)特征 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{}
/** 訂閱的特征值的value發(fā)生改變的回調(diào) */
// read 外設(shè) --> 中心 (由控制類去解析返回的數(shù)據(jù))
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{}
/**
* 當(dāng)寫入某個(gè)特征值后 外設(shè)代理執(zhí)行的回調(diào)
* 發(fā)送類型必須是CBCharacteristicWriteWithResponse才會(huì)回調(diào)
*/
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{}
/**
* 讀取信號(hào)強(qiáng)度回調(diào)的方法
* peripheral 調(diào)用 readRSSI方法觸發(fā)該代理
*/
-(void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error{}
@end