藍(lán)牙常用開發(fā)步驟

如果你進(jìn)來(lái)了,點(diǎn)下關(guān)注行不行_

隨說(shuō) : 網(wǎng)上資料一大堆, 可以隨便google搜一下加深理解, 這里作一個(gè)整理, 可收藏起來(lái)當(dāng)資料隨時(shí)翻查

藍(lán)牙常用框架 : CoreBluetooth
藍(lán)牙常用庫(kù) :
BabyBluetooth
YmsCoreBluetooth
基本概念要搞清楚

1. 名詞解釋#


CoreBluetooth框架的核心其實(shí)是兩個(gè)東西,peripheral(CBCebtralManager類)和central(CBPeripheralManager類), 可以理解成外設(shè)和中心
打個(gè)比喻.小米手環(huán)是peripheral,我們的iphone手機(jī)是central,所以就會(huì)大量使用CBCebtralManager類。(Iphone理解為連接)
又比如像用一個(gè)ipad和一個(gè)iphone通訊, ipad可以認(rèn)為是central玄糟,iphone端是peripheral ,這種情況下在iphone端就要使用CBPeripheralManager類來(lái)開發(fā)了烈炭。(Iphone理解為外設(shè))
發(fā)起連接的時(shí)central,被連接的設(shè)備為perilheral


每個(gè)藍(lán)牙4.0的設(shè)備都是通過(guò)服務(wù)和特征來(lái)展示自己的

service : 一個(gè)設(shè)備必然包含一個(gè)服務(wù)以上(至少包含一個(gè)服務(wù),有可能包含更多的服務(wù))
characteristic : 包含在服務(wù)下, 描述該服務(wù)下特定的功能的, 一般擁有多個(gè)characteristic, 而且characteristic有類型, 讀(read), 寫(write), 通知(notify)等
UUID(Universally Unique Identifier) : 設(shè)備的每一個(gè)service有他相應(yīng)的UUID, 同時(shí)每一個(gè)characteristic也有相應(yīng)的UUID

簡(jiǎn)單理解 : service and characteristic 每個(gè)設(shè)備會(huì)提供服務(wù)和特征流礁,類似于服務(wù)端的api,但是機(jī)構(gòu)不同。每個(gè)外設(shè)會(huì)有很多服務(wù)晶伦,每個(gè)服務(wù)中包含很多字段,這些字段的權(quán)限一般分為 讀read啄枕,寫write婚陪,通知notiy幾種,就是我們連接設(shè)備后具體需要操作的內(nèi)容频祝。

注 : 藍(lán)牙設(shè)備硬件廠商通常都會(huì)提供他們的設(shè)備里面各個(gè)服務(wù)(service)和特征(characteristics)的功能泌参,比如哪些是用來(lái)交互(讀寫),哪些可獲取模塊信息(只讀)等, 也就是說(shuō), 藍(lán)牙設(shè)備硬件廠商, 提供了這些


2. 開發(fā)基本步驟#

  1. 建立中心角色
  2. 掃描外設(shè)(discover)
  3. 連接外設(shè) (connect)
  4. 掃描外設(shè)中的服務(wù)和特征(discover)
    • 4.1 獲取外設(shè)的services
    • 4.2 獲取外設(shè)的Characteristics,獲取Characteristics的值常空,獲取Characteristics的Descriptor和Descriptor的值
  5. 與外設(shè)做數(shù)據(jù)交互(explore and interact)
  6. 訂閱Characteristic的通知
  7. 斷開連接(disconnect)

一 : 建立中心角色####

// 連接中心角色, 所謂的中心角色,就是藍(lán)牙設(shè)備管理對(duì)象, 可以把他理解為主設(shè)備沽一,通過(guò)他,可以去掃描和鏈接外設(shè)
// 初始化并設(shè)置委托和線程隊(duì)列漓糙,最好一個(gè)線程的參數(shù)可以為nil铣缠,默認(rèn)會(huì)就main線程
self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];


// 這個(gè)是BabyBluetooth第三方庫(kù)
// 單例模式
+ (instancetype)shareBabyBluetooth {
    static BabyBluetooth *share = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        share = [[BabyBluetooth alloc]init];
    });
   return share;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        //初始化對(duì)象
        babyCentralManager = [[BabyCentralManager alloc]init];// 藍(lán)牙中心模式實(shí)現(xiàn)類
        babySpeaker = [[BabySpeaker alloc]init]; // block查找和channel切換
        babyPeripheralManager = [[BabyPeripheralManager alloc]init]; // 外設(shè)模式實(shí)現(xiàn)類
        // babyPeripheralManager里面有一個(gè)成員屬性babySpeaker , 將這個(gè)賦值于它
        babyPeripheralManager->babySpeaker = babySpeaker;
        // babyCentralManager里面有一個(gè)成員屬性babySpeaker , 將這個(gè)賦值于它
        babyCentralManager->babySpeaker = babySpeaker;
    }
    return self;
    
}

// 注冊(cè)藍(lán)牙中心后, 必須調(diào)用的代理方法, 不然會(huì)報(bào)錯(cuò)
// 主設(shè)備狀態(tài)改變的委托,在初始化CBCentralManager的適合會(huì)打開設(shè)備,只有當(dāng)設(shè)備正確打開后才能使用
// 特別注意, 需要在狀態(tài)CBCentralManagerStatePoweredOn下才能使用任何設(shè)備
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    
    //發(fā)送通知
    [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtCentralManagerDidUpdateState object:@{@"central":central}];
    
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            BabyLog(@">>>CBCentralManagerStateUnknown");
            break;
        case CBCentralManagerStateResetting:
            BabyLog(@">>>CBCentralManagerStateResetting");
            break;
        case CBCentralManagerStateUnsupported:
            BabyLog(@">>>CBCentralManagerStateUnsupported");
            break;
        case CBCentralManagerStateUnauthorized:
            BabyLog(@">>>CBCentralManagerStateUnauthorized");
            break;
        case CBCentralManagerStatePoweredOff:
            BabyLog(@">>>CBCentralManagerStatePoweredOff");
            break;
        case CBCentralManagerStatePoweredOn:
            BabyLog(@">>>CBCentralManagerStatePoweredOn");
            [[NSNotificationCenter defaultCenter] postNotificationName:BabyNotificationAtCentralManagerEnable object:@{@"central":central}];
            break;
        default:
            break;
    }
    //狀態(tài)改變callback
    if ([currChannel blockOnCentralManagerDidUpdateState]) {
        [currChannel blockOnCentralManagerDidUpdateState](central);
    }
}



二 : 掃描設(shè)備####

// 框架提供的方法
/*!
 *  @method scanForPeripheralsWithServices:options:
 *
 *  @param serviceUUIDs UUID列表, 參數(shù)有值的話則只掃描改UUID
 *  @param options      An optional dictionary specifying options for the scan.
 *
 *
 *  @see               發(fā)現(xiàn)設(shè)備就會(huì)調(diào)用這個(gè)代理方法 centralManager:didDiscoverPeripheral:advertisementData:RSSI:
 *  @seealso            CBCentralManagerScanOptionAllowDuplicatesKey
 * @seealso   CBCentralManagerScanOptionSolicitedServiceUUIDsKey
 *
 */
- (void)scanForPeripheralsWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs options:(nullable NSDictionary<NSString *, id> *)options;

// 當(dāng)然有掃描方法就有停止掃描的方法
/*!
 *  @method stopScan:
 *
 *  @discussion Stops scanning for peripherals.
 *
 */
- (void)stopScan;



//這個(gè)是BabyBluetooth第三方庫(kù)實(shí)現(xiàn)的掃描方法
//掃描Peripherals
- (void)scanPeripherals {
    [centralManager scanForPeripheralsWithServices:[currChannel babyOptions].scanForPeripheralsWithServices options:[currChannel babyOptions].scanForPeripheralsWithOptions];
}

三 : 發(fā)現(xiàn)設(shè)備 - 連接設(shè)備####

//這個(gè)是BabyBluetooth第三方庫(kù)實(shí)現(xiàn)的連接方法
//掃描到Peripherals, 當(dāng)掃描到設(shè)備, 就會(huì)執(zhí)行這個(gè)代理方法entralManager:didDiscoverPeripheral:advertisementData:RSSI:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    
    //日志
    //BabyLog(@"當(dāng)掃描到設(shè)備:%@",peripheral.name);
    [self addDiscoverPeripheral:peripheral];
    
    //發(fā)出通知
    [[NSNotificationCenter defaultCenter]postNotificationName:BabyNotificationAtDidDiscoverPeripheral
                                                       object:@{@"central":central,@"peripheral":peripheral,@"advertisementData":advertisementData,@"RSSI":RSSI}];
    //掃描到設(shè)備callback
    if ([currChannel filterOnDiscoverPeripherals]) {
        if ([currChannel filterOnDiscoverPeripherals](peripheral.name,advertisementData,RSSI)) {
           // 執(zhí)行回調(diào)Block, 然后就會(huì)執(zhí)行setBlockOnDiscoverToPeripherals:(void (^)(CBCentralManager *central,CBPeripheral *peripheral,NSDictionary *advertisementData, NSNumber *RSSI))block
             if ([currChannel blockOnDiscoverPeripherals]) { 
                [[babySpeaker callbackOnCurrChannel] blockOnDiscoverPeripherals](central,peripheral,advertisementData,RSSI);
            }
        }
    }
    
    //處理連接設(shè)備
    if (needConnectPeripheral) {
        if ([currChannel filterOnconnectToPeripherals](peripheral.name,advertisementData,RSSI)) {
            [centralManager connectPeripheral:peripheral options:[currChannel babyOptions].connectPeripheralWithOptions];
            //開一個(gè)定時(shí)器監(jiān)控連接超時(shí)的情況
            connectTimer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(disconnect:) userInfo:peripheral repeats:NO];
        }
    }
}


注意 : 
1, 回調(diào)這個(gè)代理方法,(CBPeripheral *)peripheral就是返現(xiàn)到的服務(wù), 必須保存下來(lái)作為
2, 需要過(guò)濾搜索結(jié)果, 可以通過(guò)filterOnDiscoverPeripherals Block


------------

連接成功與失敗,斷開連接等會(huì)調(diào)用的三個(gè)代理方法
//連接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
            NSLog(@">>>連接到名稱為(%@)的設(shè)備-成功",peripheral.name);
        }

//連接到Peripherals-失敗
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
            NSLog(@">>>連接到名稱為(%@)的設(shè)備-失敗,原因:%@",[peripheral name],[error localizedDescription]);
        }

//Peripherals斷開連接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
            NSLog(@">>>外設(shè)連接斷開連接 %@: %@\n", [peripheral name], [error localizedDescription]);
        }

---------------

//BabyBluetooth第三方庫(kù)實(shí)現(xiàn)的連接情況Block
//設(shè)置設(shè)備連接成功的委托,同一個(gè)baby對(duì)象攘残,使用不同的channel切換委托回調(diào)
    [baby setBlockOnConnectedAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral) {
        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"設(shè)備:%@--連接成功",peripheral.name]];
    }];
    
    //設(shè)置設(shè)備連接失敗的委托
    [baby setBlockOnFailToConnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"設(shè)備:%@--連接失敗",peripheral.name);
        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"設(shè)備:%@--連接失敗",peripheral.name]];
    }];

    
    //設(shè)置設(shè)備斷開連接的委托
    [baby setBlockOnDisconnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"設(shè)備:%@--斷開連接",peripheral.name);
        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"設(shè)備:%@--斷開失敗",peripheral.name]];
    }];

一些坑爹的情況#

1.為什么掃描不到外設(shè)拙友?
->情況1:設(shè)備不支持
babybluetooth支持BLE4.0藍(lán)牙設(shè)備,如果是2.0的設(shè)備歼郭,那肯定掃描不到
模擬器不支持藍(lán)牙調(diào)試遗契,必須使用真機(jī)調(diào)試
ios操作系統(tǒng)至少要在6.0以上

->情況2:外設(shè)沒(méi)有開啟廣播
默認(rèn)情況下打開手機(jī)或者ipad的藍(lán)牙,在使用babybluetooth是掃描不到設(shè)備的病曾,因?yàn)槭謾C(jī)和ipad只是打開了藍(lán)牙設(shè)備的電源而已牍蜂,并沒(méi)有發(fā)送廣播,如果想掃描到設(shè)備泰涂,需要編程的方式鲫竞,通過(guò)iphone或ipad,mac發(fā)送藍(lán)牙廣播逼蒙。demo程序中有一個(gè)iphone和一個(gè)mac發(fā)送藍(lán)牙廣播的程序从绘。
已連接的設(shè)備會(huì)停止廣播,所以也搜索不到

->情況3:為什么系統(tǒng)的藍(lán)牙能找到設(shè)備是牢,但是使用babybluetooth的demo卻無(wú)法找到僵井?
這種情況一般是因?yàn)槟莻€(gè)藍(lán)牙設(shè)備是支持MFI的,并不是普通的ble設(shè)備驳棱。
關(guān)于MFI這里補(bǔ)充一下 :
MFI ( make for ipad ,iphone, itouch ), 專們?yōu)樘O果設(shè)備制作的設(shè)備, 開發(fā)使用的是 ExternalAccessory 框架
所以這篇文章不予談?wù)?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末批什,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子社搅,更是在濱河造成了極大的恐慌驻债,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件形葬,死亡現(xiàn)場(chǎng)離奇詭異合呐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)笙以,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門合砂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人源织,你說(shuō)我怎么就攤上這事翩伪。” “怎么了谈息?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵缘屹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我侠仇,道長(zhǎng)轻姿,這世上最難降的妖魔是什么犁珠? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮互亮,結(jié)果婚禮上犁享,老公的妹妹穿的比我還像新娘。我一直安慰自己豹休,他們只是感情好炊昆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著威根,像睡著了一般凤巨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洛搀,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天敢茁,我揣著相機(jī)與錄音,去河邊找鬼留美。 笑死彰檬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谎砾。 我是一名探鬼主播逢倍,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼棺榔!你這毒婦竟也來(lái)了瓶堕?” 一聲冷哼從身側(cè)響起隘道,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤症歇,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后谭梗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忘晤,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年激捏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了设塔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡远舅,死狀恐怖闰蛔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情图柏,我是刑警寧澤序六,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站蚤吹,受9級(jí)特大地震影響例诀,放射性物質(zhì)發(fā)生泄漏随抠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一繁涂、第九天 我趴在偏房一處隱蔽的房頂上張望拱她。 院中可真熱鬧,春花似錦扔罪、人聲如沸秉沼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氧猬。三九已至,卻和暖如春坏瘩,著一層夾襖步出監(jiān)牢的瞬間盅抚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工倔矾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妄均,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓哪自,卻偏偏與公主長(zhǎng)得像丰包,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壤巷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • (一) iOS藍(lán)牙開發(fā)藍(lán)牙相關(guān)基礎(chǔ)知識(shí) 藍(lán)牙常見(jiàn)名稱和縮寫 MFI ======= make for ipad ...
    雷鳴1010閱讀 4,999評(píng)論 2 12
  • 這里我們具體說(shuō)明一下中心模式的應(yīng)用場(chǎng)景邑彪。主設(shè)備(手機(jī)去掃描連接外設(shè),發(fā)現(xiàn)外設(shè)服務(wù)和屬性胧华,操作服務(wù)和屬性的應(yīng)用寄症。一般...
    丶逝水流年閱讀 2,261評(píng)論 3 4
  • 等先生,你真要走矩动,嗯有巧,那你走我不挽留,你真要走悲没,嗯篮迎,我放開你的手,你真要走示姿,我在雨的這邊守候甜橱,等你回首。
    宿命里的我們閱讀 162評(píng)論 0 0
  • 今天在做論壇之后的一些調(diào)研與反饋栈戳,有學(xué)員對(duì)于我主持風(fēng)格提出了一些建議岂傲,希望我能夠更棒!我突然想起龐太師第一...
    胡永群閱讀 683評(píng)論 0 50
  • 董明明閱讀 865評(píng)論 3 2