iOS_SN_BlueTooth (二)iOS 串連外設的代碼實現

來源:互聯網
上載者:User

標籤:

原文:http://www.cocoachina.com/ios/20150917/13456.html?utm_source=tuicool&utm_medium=referral

 

上一篇文章介紹了藍芽的技術知識,這裡我們具體說明一下中心模式的應用情境。主裝置(手機去掃描串連外設,發現外設服務和屬性,操作服務和屬性的應用。一般來說,外設(藍牙裝置,比如智能手環之類的東西),會由硬體工程師開發好,並定義好裝置提供的服務,每個服務對於的特徵,每個特徵的屬性(唯讀,唯寫,通知等等),本文例子的業務情境,就是用一手機app去讀寫藍牙裝置。

iOS串連外設的代碼實現流程

1. 建立中心角色

2. 掃描外設(discover)

3. 串連外設(connect)

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

 - 4.1 擷取外設的services

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

5. 與外設做資料互動(explore and interact)

6. 訂閱Characteristic的通知

7. 中斷連線(disconnect)

準備環境

 1 Xcode

 2 開發認證和手機(藍芽程式需要使用使用真機調試,使用模擬器也可以調試,但是方法很蛋疼,我會放在最後說)

 3 藍芽外設

實現步驟

1 匯入CoreBluetooth標頭檔,建立主裝置管理類,設定主裝置委託

#import <corebluetooth corebluetooth.h="">    @interface ViewController : UIViewController<cbcentralmanagerdelegate>      @interface ViewController (){        //系統藍牙裝置管理對象,可以把他理解為主裝置,通過他,可以去掃描和連結外設        CBCentralManager *manager;    }     - (void)viewDidLoad {        [super viewDidLoad];        /*         設定主裝置的委託,CBCentralManagerDelegate            必須實現的:            - (void)centralManagerDidUpdateState:(CBCentralManager *)central;//主裝置狀態改變的委託,在初始化CBCentralManager的適合會開啟裝置,只有當裝置正確開啟後才能使用            其他選擇實現的委託中比較重要的:            - (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;//斷開外設的委託        */         //初始化並設定委託和線程隊列,最好一個線程的參數可以為nil,預設會就main線程         manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];

  


 

2 掃描外設(discover),掃描外設的方法我們放在centralManager成功開啟的委託中,因為只有裝置成功開啟,才能開始掃描,否則會報錯。

 -(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");                    //開始掃描周圍的外設                    /*                     第一個參數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)

//掃描到裝置會進入方法        -(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{             //接下串連我們的測試裝置,如果你沒有裝置,可以下載一個app叫lightbule的app去類比一個裝置            //這裡自己去設定下串連規則,我設定的是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]);         }

  


 

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

裝置串連成功後,就可以掃描裝置的服務了,同樣是通過委託形式,掃描到結果後會進入委託方法。但是這個委託已經不再是主裝置的委託(CBCentralManagerDelegate),而是外設的委託(CBPeripheralDelegate),這個委託包含了主裝置與外設互動的許多 回叫方法,包括擷取services,擷取characteristics,擷取characteristics的值,擷取characteristics的Descriptor,和Descriptor的值,寫資料,讀rssi,用通知的方式訂閱資料等等。

4.1 擷取外設的services

//串連到Peripherals-成功        - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral        {            NSLog(@">>>串連到名稱為(%@)的裝置-成功",peripheral.name);            //設定的peripheral委託CBPeripheralDelegate            //@interface ViewController : UIViewController<cbcentralmanagerdelegate,cbperipheraldelegate>            [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];                         }         }
4.2 擷取外設的Characteristics,擷取Characteristics的值,擷取Characteristics的Descriptor和Descriptor的值 //掃描到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的值,讀到資料會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error for (CBCharacteristic *characteristic in service.characteristics){ { [peripheral readValueForCharacteristic:characteristic]; } } //搜尋Characteristic的Descriptors,讀到資料會進入方法:-(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,具體開發時,會根據外設協議制定的方式去解析資料 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的描述,一般都是字串,所以這裡我們轉換成字串去解析 NSLog(@"characteristic uuid:%@ value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value); }

  


 

5 把資料寫到Characteristic中

 //寫資料    -(void)writeCharacteristic:(CBPeripheral *)peripheral                characteristic:(CBCharacteristic *)characteristic                         value:(NSData *)value{         //列印出 characteristic 的許可權,可以看到有很多種,這是一個NS_OPTIONS,就是可以同時用於好幾個值,常見的有read,write,notify,indicate,知知道這幾個基本就夠用了,前連個是讀寫權限,後兩個都是通知,兩種不同的通知方式。        /*         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的許可權才可以寫        if(characteristic.properties & CBCharacteristicPropertyWrite){            /*                最好一個type參數可以為CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,區別是是否會有反饋            */            [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];        }else{            NSLog(@"該欄位不可寫!");        }      }

  


 

6 訂閱Characteristic的通知

//設定通知    -(void)notifyCharacteristic:(CBPeripheral *)peripheral                characteristic:(CBCharacteristic *)characteristic{        //設定通知,資料通知會進入: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];    }

  

iOS_SN_BlueTooth (二)iOS 串連外設的代碼實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.