iOS 藍牙開發(fā)-連接外設的代碼實現(xiàn)

iOS連接外設的代碼實現(xiàn)流程

1. 建立中心角色

2. 掃描外設(discover)

3. 連接外設(connect)

4. 掃描外設中的服務和特征(discover)

- 4.1 獲取外設的services

- 4.2 獲取外設的Characteristics,獲取Characteristics的值,獲取Characteristics的Descriptor和Descriptor的值

5. 與外設做數(shù)據(jù)交互(explore and interact)

6. 訂閱Characteristic的通知

7. 斷開連接(disconnect)

準備環(huán)境

1 Xcode

2 開發(fā)證書和手機(藍牙程序需要使用使用真機調(diào)試,使用模擬器也可以調(diào)試,但是方法很蛋疼,我會放在最后說)

3 藍牙外設

實現(xiàn)步驟

1 導入CoreBluetooth頭文件,建立主設備管理類,設置主設備委托

<pre>

#import@interface ViewController : UIViewController@interface ViewController (){

//系統(tǒng)藍牙設備管理對象,可以把他理解為主設備,通過他,可以去掃描和鏈接外設

CBCentralManager *manager;

}

- (void)viewDidLoad {

[super viewDidLoad];

/*

設置主設備的委托,CBCentralManagerDelegate

必須實現(xiàn)的:

- (void)centralManagerDidUpdateState:(CBCentralManager *)central;//主設備狀態(tài)改變的委托,在初始化CBCentralManager的適合會打開設備,只有當設備正確打開后才能使用

其他選擇實現(xiàn)的委托中比較重要的:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外設的委托

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//連接外設成功的委托

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外設連接失敗的委托

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//斷開外設的委托

*/

//初始化并設置委托和線程隊列,最好一個線程的參數(shù)可以為nil,默認會就main線程

manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];

</pre>

2 掃描外設(discover)

掃描外設的方法我們放在centralManager成功打開的委托中,因為只有設備成功打開,才能開始掃描,否則會報錯

<pre>

-(void)centralManagerDidUpdateState:(CBCentralManager *)central{

switch (central.state) {

case CBCentralManagerStateUnknown:

NSLog(@">>>CBCentralManagerStateUnknown");

break;

case CBCentralManagerStateResetting:

NSLog(@">>>CBCentralManagerStateResetting");

break;

case CBCentralManagerStateUnsupported:

NSLog(@">>>CBCentralManagerStateUnsupported");

break;

case CBCentralManagerStateUnauthorized:

NSLog(@">>>CBCentralManagerStateUnauthorized");

break;

case CBCentralManagerStatePoweredOff:

NSLog(@">>>CBCentralManagerStatePoweredOff");

break;

case CBCentralManagerStatePoweredOn:

NSLog(@">>>CBCentralManagerStatePoweredOn");


//開始掃描周圍的外設

/*

第一個參數(shù)nil就是掃描周圍所有的外設,掃描到外設后會進入

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;

*/

[manager scanForPeripheralsWithServices:nil options:nil];

break;

default:

break;

}

}

//掃描到設備會進入方法

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{

NSLog(@"當掃描到設備:%@",peripheral.name);

//接下來可以連接設備

}

3 連接外設(connect)

<pre>

//掃描到設備會進入方法

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{

//接下連接我們的測試設備,如果你沒有設備,可以下載一個app叫l(wèi)ightbule的app去模擬一個設備

//這里自己去設置下連接規(guī)則,我設置的是P開頭的設備

if ([peripheral.name hasPrefix:@"P"]){

/*

一個主設備最多能連7個外設,每個外設最多只能給一個主設備連接,連接成功,失敗,斷開會進入各自的委托

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//連接外設成功的委托

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外設連接失敗的委托

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//斷開外設的委托

*/

//連接設備

[manager connectPeripheral:peripheral options:nil];

}

}

//連接到Peripherals-成功

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral

{

NSLog(@">>>連接到名稱為(%@)的設備-成功",peripheral.name);

}

//連接到Peripherals-失敗

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

{

NSLog(@">>>連接到名稱為(%@)的設備-失敗,原因:%@",[peripheral name],[error localizedDescription]);

}

//Peripherals斷開連接

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

NSLog(@">>>外設連接斷開連接 %@: %@\n", [peripheral name], [error localizedDescription]);

}</pre>

4 掃描外設中的服務和特征(discover)

設備連接成功后,就可以掃描設備的服務了,同樣是通過委托形式,掃描到結(jié)果后會進入委托方法。但是這個委托已經(jīng)不再是主設備的委托(CBCentralManagerDelegate),而是外設的委托(CBPeripheralDelegate),這個委托包含了主設備與外設交互的許多 回叫方法,包括獲取services,獲取characteristics,獲取characteristics的值,獲取characteristics的Descriptor,和Descriptor的值,寫數(shù)據(jù),讀rssi,用通知的方式訂閱數(shù)據(jù)等等。

4.1 獲取外設的services

<pre>

//連接到Peripherals-成功? ??

? ? - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral? ? ? ? {? ? ? ??

? ? NSLog(@">>>連接到名稱為(%@)的設備-成功",peripheral.name);? ? ? ? ? ? //設置的peripheral委托CBPeripheralDelegate? ? ? ? ? ? //@interface ViewController : UIViewController[peripheral setDelegate:self];

//掃描外設Services,成功后會進入方法:

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{

[peripheral discoverServices:nil];

}

//掃描到Services

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{

//? NSLog(@">>>掃描到服務:%@",peripheral.services);

if (error)

{

NSLog(@">>>Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);

return;

}

for (CBService *service in peripheral.services) {

NSLog(@"%@",service.UUID);

//掃描每個service的Characteristics,掃描到后會進入方法: -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error

[peripheral discoverCharacteristics:nil forService:service];

}

}

</pre>

4.2 獲取外設的Characteristics,獲取Characteristics的值,獲取Characteristics的Descriptor和Descriptor的值

<pre>

//掃描到Characteristics

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{

if (error)

{

NSLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);

return;

}

for (CBCharacteristic *characteristic in service.characteristics)

{

NSLog(@"service:%@ 的 Characteristic: %@",service.UUID,characteristic.UUID);

}

//獲取Characteristic的值,讀到數(shù)據(jù)會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

for (CBCharacteristic *characteristic in service.characteristics){

{

[peripheral readValueForCharacteristic:characteristic];

}

}

//搜索Characteristic的Descriptors,讀到數(shù)據(jù)會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

for (CBCharacteristic *characteristic in service.characteristics){

[peripheral discoverDescriptorsForCharacteristic:characteristic];

}

}

//獲取的charateristic的值

-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{

//打印出characteristic的UUID和值

//!注意,value的類型是NSData,具體開發(fā)時,會根據(jù)外設協(xié)議制定的方式去解析數(shù)據(jù)

NSLog(@"characteristic uuid:%@? value:%@",characteristic.UUID,characteristic.value);

}

//搜索到Characteristic的Descriptors

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{

//打印出Characteristic和他的Descriptors

NSLog(@"characteristic uuid:%@",characteristic.UUID);

for (CBDescriptor *d in characteristic.descriptors) {

NSLog(@"Descriptor uuid:%@",d.UUID);

}

}

//獲取到Descriptors的值

-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{

//打印出DescriptorsUUID 和value

//這個descriptor都是對于characteristic的描述,一般都是字符串,所以這里我們轉(zhuǎn)換成字符串去解析

NSLog(@"characteristic uuid:%@? value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);

}</pre>

5 把數(shù)據(jù)寫到Characteristic中

<pre>

//寫數(shù)據(jù)

-(void)writeCharacteristic:(CBPeripheral *)peripheral

characteristic:(CBCharacteristic *)characteristic

value:(NSData *)value{

//打印出 characteristic 的權(quán)限,可以看到有很多種,這是一個NS_OPTIONS,就是可以同時用于好幾個值,常見的有read,write,notify,indicate,知知道這幾個基本就夠用了,前連個是讀寫權(quán)限,后兩個都是通知,兩種不同的通知方式。

/*

typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {

CBCharacteristicPropertyBroadcast? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x01,

CBCharacteristicPropertyRead? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x02,

CBCharacteristicPropertyWriteWithoutResponse? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x04,

CBCharacteristicPropertyWrite? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x08,

CBCharacteristicPropertyNotify? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x10,

CBCharacteristicPropertyIndicate? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x20,

CBCharacteristicPropertyAuthenticatedSignedWrites? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x40,

CBCharacteristicPropertyExtendedProperties? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = 0x80,

CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)? ? ? ? = 0x100,

CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)? = 0x200

};

*/

NSLog(@"%lu", (unsigned long)characteristic.properties);

//只有 characteristic.properties 有write的權(quán)限才可以寫

if(characteristic.properties & CBCharacteristicPropertyWrite){

/*

最好一個type參數(shù)可以為CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,區(qū)別是是否會有反饋

*/

[peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

}else{

NSLog(@"該字段不可寫!");

}

}

</pre>

6 訂閱Characteristic的通知

<pre>

//設置通知

-(void)notifyCharacteristic:(CBPeripheral *)peripheral

characteristic:(CBCharacteristic *)characteristic{

//設置通知,數(shù)據(jù)通知會進入:didUpdateValueForCharacteristic方法

[peripheral setNotifyValue:YES forCharacteristic:characteristic];

}

//取消通知

-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral

characteristic:(CBCharacteristic *)characteristic{

[peripheral setNotifyValue:NO forCharacteristic:characteristic];

}

7 斷開連接(disconnect)

//停止掃描并斷開連接

-(void)disconnectPeripheral:(CBCentralManager *)centralManager

peripheral:(CBPeripheral *)peripheral{

//停止掃描

[centralManager stopScan];

//斷開連接

[centralManager cancelPeripheralConnection:peripheral];

}

</pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容