1. 程式人生 > >iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現

iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現

上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料

iOS連線外設的流程

  • 建立中心管理者
  • 掃描外設 discoverPeripheral
  • 連線外設 connectPeripheral
  • 掃描外設中的服務和特徵 discoverServices discoverCharacteristics
    • 獲取外設的services
    • 獲取外設service中的characteristics
    • 獲取characteristic的值value、descriptor的value
  • 與外設做資料互動 write、read
  • 訂閱characteristic的通知notify
  • 斷開連線 disconnected

實現步驟

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;//斷開外設的委託
    */
     //初始化並設定委託和執行緒佇列,最好一個執行緒的引數可以為nil,預設會就main執行緒
     manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];

2、掃描外設(discover),掃描外設的方法我們放在centralManager成功開啟的委託中,因為只有裝置成功開啟,才能開始掃描,否則會報錯。
所以當重新連線外設時,都不會成功,因為states還沒開啟;一般自己寫藍芽,這個地方要處理一下,連線的時候判斷一下,還未開啟就重連,一直等到PoweredOn

-(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、連線外設
有一點注意,找到的peripheral必須被持有:(比如新增到陣列、賦值給另一個被持有的變數),否則CBCentralManager中也不會儲存這個peripheral,那麼CBPeripheralDelegate中的方法也不會被呼叫

    //掃描到裝置會進入方法
    -(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;//斷開外設的委託
                */

                //找到的裝置必須持有它,否則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]);

    }

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

5、獲取外設的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];
                     }
    }

6、獲取外設的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);
}   

7、把資料寫到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(@"該欄位不可寫!");
    }


}

8、訂閱Characteristic的通知
一般在discoverCharacteristic的代理中,發現了型別是notify的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];
}

9、斷開連線(disconnect)

    //停止掃描並斷開連線
-(void)disconnectPeripheral:(CBCentralManager *)centralManager
                 peripheral:(CBPeripheral *)peripheral{
    //停止掃描
    [centralManager stopScan];
    //斷開連線
    [centralManager cancelPeripheralConnection:peripheral];
}

iOS中藍芽模組OTA升級(YModem協議)

相關推薦

iOS開發iOS 4.0中心模式 程式碼實現

上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料 iOS連線外設的流程 建立中心管理者 掃描外設 discoverPeripheral 連線外設 connectPeripheral

iOS開發在裝置端實現Central角色

若想在裝置上實現Central角色的功能,主要有以下步驟: 2.搜尋周圍廣播的裝置 3.與一個外設進行連線,並探索外設提供的服務 4.向外設傳送讀寫characteristic的請求,如果有需要訂閱characteristic值得更新,來跟蹤資料的變化。 myCe

開發掃描裝置

一、申請位置許可權 在Android6.0以後要掃描藍芽裝置,還需要請求位置許可權: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <

Android開發 BLE4.0低功耗

一、BLE4.0低功耗藍芽 Bluetooth Low Energy,藍芽低功耗,是從藍芽4.0開始支援的技術。相較傳統藍芽,傳輸速度更快、覆蓋範圍廣、安全性高、延時短、耗電低等特點。 二、關鍵術語 1.GATT(通用屬性配置):通用屬性配置檔案,用於ble鏈路上傳送和接

星雲鏈智能合約開發Mac下安裝星雲鏈

Mac下安裝星雲鏈 星雲鏈智能合約開發 Golang環境搭建 版本用最新版:1.10.2 安裝 brew install go 配置環境變量 vi ~/.bash_profile 打開.bash_profile文件,按"i"鍵可進行編輯,添加: export GOROOT=/u

即時通訊音視訊開發視訊編解碼之數字視訊介紹

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 本文是系列文章中的第2篇,本系列文章的大綱如下:   《即時

Python爬蟲開發整站爬蟲與Web挖掘

0×00 介紹 在網際網路這個複雜的環境中,搜尋引擎本身的爬蟲,出於個人目的的爬蟲,商業爬蟲肆意橫行,肆意掠奪網上的或者公共或者私人的資源。顯然資料的收集並不是為所欲為,有一些協議或者原則還是需要每一個人注意。本文主要介紹關於爬蟲的一些理論和約定協議,然後相對完整完成一個爬蟲的基本功能。 本

iOS 元件化開發載入資原始檔

經過前兩篇文章的學習,相信對元件化開發有了大致的瞭解,那我們這篇文章就來講講資原始檔的載入吧 這裡我新建了一個LXFMain元件庫,主要是用來顯示TabBar的玩意,然後再進行元件化抽離出來,其中的過程這裡不再贅述,還沒了解過的同學建議先閱讀下這兩篇文

iOS 元件化開發遠端私有庫的基本使用

隨著專案功能的不斷增加,越來越多的開發人員加入,業務主線也隨之越來越多,造成耦合越來越嚴重,編譯越來越慢,測試不獨立等一系列問題。為了解決此類情況,我們可以考慮到使用元件化開發 概念 元件化就是將一個單一工程的專案, 分解成為各個獨立的元件, 然後

使用NetBeans進行J2ME開發把程式轉移到手機上

原文地址:http://juansusan.iteye.com/admin/blogs/251869/edit【IT168 技術文件】上一篇,我們見識了編寫一個手機程式其實很簡單。但是很多人大概不是很明白怎樣把程式轉移到手機上,不信你就試試,不管你是用資料線,還是用紅外藍芽,

Hyperledger Fabric開發建立網路

執行fabric-samples專案中的一個例子:first-network,建立第一個網路(Building Your First Network)。 該網路共有4個peer節點,劃分為2個組織(organizations),以及1個單獨的orde

Android開發之開啟和裝置搜尋

Android藍芽開發系列目錄: 一、判斷是否系統是否支援藍芽 在使用藍芽之前,我們首先要判斷手機裝置是否支援藍芽,雖然現在基本都支援藍芽了,但是為了程式碼的嚴謹性我們還是需要在程式碼中判斷: private BluetoothManager bluetoothma

Unity3D開發NGUI之UIButton"禁用"狀態時置灰

NGUI中的Button幾乎是最常用到的控制元件之一,並且可以組合各種元件(比如UIButtonColor,UIButtonOffset,UITweenxx),方便設定Button的各種狀態下的屬性,幾乎可以滿足我們的所有需求。 但是對於當Button的isEnabled屬

JavaWeb專案開發Servlet+Bean+Dao+MySQL

需要使用的技術: JSP動態網頁 Servlet獲得客戶端請求、轉發請求、跳轉到下一個介面 JavaBean 業務Bean (業務邏輯具體實現類),處理業務邏輯 Dao 訪問資料庫,操作資料庫例表 (增刪查改) MySQL 資料庫 實現系統以下介面和功能: 登入 我的資

android Bluetooth 開發開啟、關閉、搜尋、允許搜尋、檢視

相關專案的下載連結繼本專案之後實現了語音識別:點選開啟連結1.承接上一篇文章,本篇文章主要實現了藍芽的開啟 關閉 允許搜尋 檢視配對裝置2. BluetoothInit,主要實現了部件的初始化,按鈕的點選事件,通過ListVIew顯示本地配對的藍芽裝置,ListView的點選

Android微信開發程式碼分析

package com.example.teststudyshare.wxapi; import java.io.ObjectOutputStream.PutField; import android.R; import android.app.Activity; import android.content

Android 開發2——低功耗

低功耗藍芽官方文件 本文章是參考官網,然後加入自己實踐中的理解完成!沒有看上一篇的讀者,可以先閱讀一下前一篇,這是一個系列。 官網地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le Android 4.3 (API

建造者模式-Builder Pattern 複雜物件的組裝與建立——建造者模式遊戲角色設計的建造者模式解決方案

8.3 完整解決方案       Sunny公司開發人員決定使用建造者模式來實現遊戲角色的建立,其基本結構如圖8-3所示: 圖8-3 遊戲角色建立結構圖       在圖8-3中,Ac

機器學習與神經網路BP神經網路的介紹和Python程式碼實現

前言:本篇博文主要介紹BP神經網路的相關知識,採用理論+程式碼實踐的方式,進行BP神經網路的學習。本文首先介紹BP神經網路的模型,然後介紹BP學習演算法,推導相關的數學公式,最後通過Python程式碼實現BP演算法,從而給讀者一個更加直觀的認識。 1.BP網路模型 為了將理

資料結構雙向連結串列的的分析與python程式碼實現

概念        每個節點有兩個連結:一個指向前一個節點,當此節點為第一個節點時,指向空值;而另一個指向下一個節點,當此節點為最後一個節點時,指向空值。 特點:         節點包含