多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > ios藍牙開發(二)ios連接外設的代碼實現

ios藍牙開發(二)ios連接外設的代碼實現

來源:程序員人生   發布時間:2017-02-23 09:11:00 閱讀次數:4992次

上1篇文章介紹了藍牙的技術知識,這里我們具體說明1下中心模式的利用場景。主裝備(手機去掃描連接外設,發現外設服務和屬性,操作服務和屬性的利用。1般來講,外設(藍牙裝備,比如智能手環之類的東西),會由硬件工程師開發好,并定義好裝備提供的服務,每一個服務對的特點,每一個特點的屬性(只讀,只寫,通知等等),本文例子的業務場景,就是用1手機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;
        //用于保存被發現裝備
        NSMutableArray *peripherals;
    }

    - (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;//斷開外設的拜托
        */
         //初始化并設置拜托和線程隊列,最好1個線程的參數可以為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");
                    //開始掃描周圍的外設
                    /*
                     第1個參數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{

            //接下連接我們的測試裝備,如果你沒有裝備,可以下載1個app叫lightbule的app去摹擬1個裝備
            //這里自己去設置下連接規則,我設置的是P開頭的裝備
                   if ([peripheral.name hasPrefix:@"P"]){
                   /*
                       1個主裝備最多能連7個外設,每一個外設最多只能給1個主裝備連接,連接成功,失敗,斷開會進入各自的拜托
                    - (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;//斷開外設的拜托
                    */

                    //找到的裝備必須持有它,否則CBCentralManager中也不會保存peripheral,那末CBPeripheralDelegate中的方法也不會被調用?。?                    [peripherals addObject:peripheral];
                    //連接裝備
                   [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]);

        }

有1點非常容易出錯,大家請注意。在 didDiscoverPeripheral這個拜托中有這1行

//找到的裝備必須持有它,否則CBCentralManager中也不會保存peripheral,那末CBPeripheralDelegate中的方法也不會被調用??!
    [peripherals addObject:peripheral];

請特別注意,如果不保存,會影響到后面的方法履行,這個地方很多人出錯,在我的藍牙交換群中每天幾近都會由于這個問題致使沒法連接和對外設后續的操作。

大家也能夠看1下這個拜托在xcode中的說明,重點看@discussion中的內容,里面特別指出了需要retained對象。

/*!
 *  @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
 *
 *  @param central              The central manager providing this update.
 *  @param peripheral           A <code>CBPeripheral</code> object.
 *  @param advertisementData    A dictionary containing any advertisement and scan response data.
 *  @param RSSI                 The current RSSI of <i>peripheral</i>, in dBm. A value of <code>127</code> is reserved and indicates the RSSI
 *								was not available.
 *
 *  @discussion                 This method is invoked while scanning, upon the discovery of <i>peripheral</i> by <i>central</i>. A discovered peripheral must
 *                              be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager. For
 *                              a list of <i>advertisementData</i> keys, see {@link CBAdvertisementDataLocalNameKey} and other similar constants.
 *
 *  @seealso                    CBAdvertisementData.h
 *
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;

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的描寫,1般都是字符串,所以這里我們轉換成字符串去解析
        NSLog(@"characteristic uuid:%@  value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);
    }

5 把數據寫到Characteristic中

//寫數據
    -(void)writeCharacteristic:(CBPeripheral *)peripheral
                characteristic:(CBCharacteristic *)characteristic
                         value:(NSData *)value{

        //打印出 characteristic 的權限,可以看到有很多種,這是1個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){
            /*
                最好1個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];
    }

8 摹擬器藍牙調試,慎用,最好還是用真機去調試。

    由于在iPhone 4s以后的iOS才支持BLE,新1代的這些iOS裝備又都不便宜,在做測試的時候,用iOS摹擬器進行調試,可以節儉1些開發本錢。怎樣在iOS摹擬器上調試BLE,
    蘋果最初給出的說明是,支持BLE的mac機子上可以用摹擬器進行調試,并給出了1份技術文檔(傳送門),惡心的是,后來蘋果抽風,又把這份文檔移除,
    并且把iOS 7.0的摹擬器上對BLE的支持也移除掉了(難道是想讓大家多買裝備測試?Apple sucks.)后面,網上搜了1下,解決辦法以下:
    1. 買1個CSR藍牙4.0 USB適配器(某寶上大概30塊錢),在機子上插入該物(你懂的)
    2. 在Terminal下敲入sudo nvram bluetoothHostControllerSwitchBehavior="never" , 重啟Mac。
    3. 用XCode 4.6調試代碼,在iOS 6.1的摹擬器上跑程序(用XCode 5.0跑iOS 7.0摹擬器會拋異常,緣由上面詳訴過了,Apple sucks,你懂的)

    如何下降摹擬器的IOS版本呢?
    XCode->Preferences->Downloads里面有很多simulators你可以下載
    選擇個6.1的下載好了


我博客中大部份示例代碼都上傳到了github,地址是:https://github.com/coolnameismy/demo,點擊跳轉代碼下載地址

本文代碼寄存目錄是BleDemo

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: jizz亚洲日本 | 五月天在线播放视频在线 | 日本成人在线网站 | 天堂mv亚洲mv在线播放9蜜 | 性xxxx黑人与亚洲 | 一级做a爰片性色毛片中国 一级做a爰全过程免费视频毛片 | 中午字幕在线观看 | 可以看黄色的网址 | 国产乱码精品一区二区三区四川 | 国产91久久久久久久免费 | 亚洲成人偷拍自拍 | 中文在线视频观看 | 最近最新中文字幕免费1 | 国产在线拍揄自揄视精品不卡 | 日本自己的私人影院 | 亚洲国产欧美一区二区欧美 | 2022精品福利在线小视频 | 日本欧美一区二区三区乱码 | 欧美日韩成人在线视频 | www日韩精品| 亚洲欧美日韩国产综合久 | 成人卡通精品卡通动漫第一页 | 欧美18-19sex| 国产激情久久久久影 | 国产成人性色视频 | 波多野结衣一区二区三区四区 | 中文字幕第5页 | 亚洲欧洲日本精品 | 欧美一级毛片欧美大尺度一级毛片 | 国产精品久久久久激情影院 | 国产免费一区二区三区 | 九九久久99综合一区二区 | 午夜亚洲精品久久久久久 | 国产片免费看 | 色中色欧美 | 久久精品一区二区三区资源网 | 亚洲午夜免费视频 | 最近高清无吗免费看 | 91精品国产一区二区三区左线 | 国产精品久久久久久久免费大片 | 欧美日韩久久 |