iOS藍(lán)牙開發(fā)

iOS藍(lán)牙開發(fā)有三個(gè)框架

1.GameKit.framework:iOS7之前的藍(lán)牙通訊框架昧谊,從iOS7開始過期凤价。
2.MultipeerConnectivity.framework:iOS7開始引入的新的藍(lán)牙通訊開發(fā)框架鸽斟,用于取代GameKit。
3.CoreBluetooth.framework:功能強(qiáng)大的藍(lán)牙開發(fā)框架利诺,要求設(shè)備必須支持藍(lán)牙4.0富蓄。目前藍(lán)牙開發(fā)多半基于此框架,此筆記也是寫基于此框架慢逾。

藍(lán)牙開發(fā)有兩種模式:
1.手機(jī)作為中心設(shè)備立倍,獲取外設(shè)的數(shù)據(jù)
2.手機(jī)作為外設(shè)躏吊,對(duì)外提供數(shù)據(jù)(這里不做討論)

本文記錄的是利用tableView展示所有掃描到的外設(shè),點(diǎn)擊某行時(shí)連接對(duì)應(yīng)的外設(shè)進(jìn)行數(shù)據(jù)交互
實(shí)現(xiàn)流程如下:

1.導(dǎo)入藍(lán)牙庫帐萎,宏定義服務(wù)UUID、讀數(shù)據(jù)UUID胜卤、寫數(shù)據(jù)UUID
#import <CoreBluetooth/CoreBluetooth.h>

#define     kServiceUUID        @"1234"http://服務(wù)UUID
#define     kReadUUID           @"1236"http://讀數(shù)據(jù)UUID
#define     kWriteUUID          @"1235"http://寫數(shù)據(jù)UUID

@property (nonatomic, strong) CBPeripheral   *peripheral;               //外設(shè)
@property (nonatomic, strong) CBCentralManager *myCentralManager;       //管理中心
@property (nonatomic, strong) CBCharacteristic *readCharacteristic;     //讀取數(shù)據(jù)特性
@property (nonatomic, strong) CBCharacteristic *writeCharacteristic;    //寫數(shù)據(jù)特性

2.創(chuàng)建藍(lán)牙管理中心
 _myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];//如果設(shè)置為nil疆导,默認(rèn)在主線程中跑。設(shè)置了代理為self葛躏,記得遵守協(xié)議

3.監(jiān)測藍(lán)牙狀態(tài)澈段,如果藍(lán)牙開啟則掃描外設(shè)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state){
        case CBCentralManagerStateUnknown:
            break;
        case CBCentralManagerStateUnsupported:
            JCLog(@"模擬器不支持藍(lán)牙調(diào)試");
            break;
        case CBCentralManagerStateUnauthorized:
            break;
        case CBCentralManagerStatePoweredOff:{
            JCLog(@"藍(lán)牙處于關(guān)閉狀態(tài)");
        }
            break;
        case CBCentralManagerStateResetting:
            break;
        case CBCentralManagerStatePoweredOn:{
            JCLog(@"藍(lán)牙已開啟");
            //開始掃描外設(shè)
            [_myCentralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:NO]}];
        }
            break;
    }
}

4.實(shí)現(xiàn)代理方法。當(dāng)掃描到外部設(shè)備時(shí)會(huì)進(jìn)入         發(fā)現(xiàn)外設(shè)        的代理方法
- (void)centralManager:(CBCentralManager *)central //管理中心
 didDiscoverPeripheral:(CBPeripheral *)peripheral //發(fā)現(xiàn)的外設(shè)
     advertisementData:(NSDictionary *)advertisementData //外設(shè)中的廣播數(shù)據(jù)
                  RSSI:(NSNumber *)RSSI //外設(shè)信號(hào)強(qiáng)度
{
    
//    JCLog(@"藍(lán)牙廣播數(shù)據(jù)------>>%@",advertisementData);
//每次掃描出一個(gè)外設(shè)都會(huì)進(jìn)入此代理方法舰攒,在此方法中可以將外設(shè)添加到外設(shè)數(shù)組中败富,在添加進(jìn)數(shù)組之前,判斷一下數(shù)組中是否已經(jīng)添加過這個(gè)外設(shè)摩窃,如果添加過兽叮,則不再添加。
if(![_allperipherals containsObject:peripheral]){
        [_allperipherals addObject:peripheral];
//添加了新的外設(shè)進(jìn)去猾愿,刷新tableview
       [_tableView reloadData];
    }

5.連接外設(shè)
//在選中某行cell的代理方法中鹦聪,調(diào)用連接藍(lán)牙外設(shè)的方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//需要連接的外設(shè)必須強(qiáng)引用,否則出了此方法作用域后會(huì)被釋放掉蒂秘,導(dǎo)致藍(lán)牙斷開連接泽本,控制臺(tái)輸出錯(cuò)誤信息
    _peripheral = _allperipherals[indexPath.row];
    JCLog(@"連接藍(lán)牙:%@",_peripheral.name);
    [_myCentralManager connectPeripheral:_peripheral options:nil];//連接藍(lán)牙
}

6.藍(lán)牙連接成功,會(huì)調(diào)用代理方法
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
//    JCLog(@"成功連接%@",peripheral.name);
    _peripheral = peripheral;
    peripheral.delegate = self;
    //開始尋找外設(shè)服務(wù)
    [peripheral discoverServices:nil];
/*
關(guān)于外設(shè)服務(wù)是什么的理解:
每個(gè)藍(lán)牙4.0的設(shè)備都是通過服務(wù)和特征來展示自己的姻僧,一個(gè)設(shè)備必然包含一個(gè)或多個(gè)服務(wù)规丽,每個(gè)服務(wù)下面又包含若干個(gè)特征。
特征是與外界交互的最小單位撇贺。比如說赌莺,一臺(tái)藍(lán)牙4.0設(shè)備,用特征A來描述自己的出廠信息显熏,用特征B來與收發(fā)數(shù)據(jù)等雄嚣。
此處應(yīng)用時(shí)可以借助一個(gè)叫:LightBlue的App來理解藍(lán)牙外設(shè)的服務(wù)及特征值。
最近做的一個(gè)藍(lán)牙項(xiàng)目中喘蟆,硬件工程師選擇的藍(lán)牙模塊有提供開發(fā)文檔缓升,文檔中有提供 服務(wù)值 及 讀取數(shù)據(jù) 和 寫數(shù)據(jù) 的特征值。按照文檔中提供的對(duì)應(yīng)的值填寫即可蕴轨。借助LightBlue也可以看到服務(wù)值和讀寫數(shù)據(jù)特征值港谊。具體值,參考步驟1中的三個(gè)宏定義橙弱。
理解不是很到位歧寺,請(qǐng)見諒燥狰。
*/
}

連接外部藍(lán)牙設(shè)備失敗調(diào)用此方法,可在此再次連接外設(shè)
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
//如何實(shí)現(xiàn)自動(dòng)斷線重連斜筐,就是在斷開的委托方法中龙致,執(zhí)行連接藍(lán)牙的方法  可以在此處重新調(diào)用連接藍(lán)牙方法
//    JCLog(@"連接%@失敗--error:%@",peripheral.name,error);
    [_myCentralManager connectPeripheral:_peripheral options:nil];//連接藍(lán)牙
}

7.發(fā)現(xiàn)藍(lán)牙外設(shè)服務(wù),調(diào)用此方法
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    
    if(error){
        JCLog(@"外圍設(shè)備尋找服務(wù)過程中發(fā)生錯(cuò)誤顷链,錯(cuò)誤信息:%@",error.localizedDescription);
    }
    //遍歷查找到的服務(wù)
    CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
    for (CBService *service in peripheral.services) {
        if([service.UUID isEqual:serviceUUID]){
            //外圍設(shè)備查找指定服務(wù)中的特征
            [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kReadUUID],[CBUUID UUIDWithString:kWriteUUID]] forService:service];
        }
    }
}

8.尋找藍(lán)牙服務(wù)中的特性
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {//報(bào)錯(cuò)直接返回退出
        JCLog(@"didDiscoverCharacteristicsForService error : %@", [error localizedDescription]);
        return;
    }
    
    for (CBCharacteristic *characteristic in service.characteristics)//遍歷服務(wù)中的所有特性
    {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kReadUUID]]){//找到收數(shù)據(jù)特性
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];//訂閱其特性(這個(gè)特性只有訂閱方式)
            _readCharacteristic = characteristic;
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWriteUUID]]) {//找到發(fā)數(shù)據(jù)特性
            _writeCharacteristic = characteristic;
        }
    }
}

9.收到外設(shè)更新發(fā)送過來的數(shù)據(jù)
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    if (error) {
        JCLog(@"更新特征值時(shí)發(fā)生錯(cuò)誤目代,錯(cuò)誤信息:%@",error.localizedDescription);
        return;
    }
    NSString *value=[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
    JCLog(@"讀取到特征值:%@",value);//即收到的數(shù)據(jù)
}

10.發(fā)送數(shù)據(jù)到外設(shè)
-(void)sendString:(NSString *)string{
   NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
   [_eripheral writeValue:data
        forCharacteristic:_writeCharacteristic
                     type:CBCharacteristicWriteWithoutResponse];
}

/*======至此,藍(lán)牙收發(fā)數(shù)據(jù)的流程基本結(jié)束======*/

/*
注意點(diǎn):
1.發(fā)送到外設(shè)的數(shù)據(jù)最大為20字節(jié)
2.接收的數(shù)據(jù)也為20字節(jié)
3.MAC端藍(lán)牙調(diào)試助手推薦使用CoolTerm嗤练,相當(dāng)于windows中的串口調(diào)試助手
4.iPhone手機(jī)端調(diào)試榛了,推薦LightBlue
*/


/*
關(guān)于服務(wù)UUID,特征值UUID的解釋
1.此文介紹的藍(lán)牙開發(fā)是固定的服務(wù)UUID煞抬、固定的特征值UUID霜大。即已獲知項(xiàng)目中使用的外設(shè)藍(lán)牙模塊的服務(wù)UUID、特征值UUID革答,這兩個(gè)數(shù)據(jù)可以在硬件工程師那里拿到战坤,藍(lán)牙模塊文檔中一般會(huì)提及。如果沒有蝗碎,則使用上文中提到的調(diào)試工具LightBlue可以獲取得到湖笨。
2.最近開發(fā)項(xiàng)目中的服務(wù)UUID、特征值UUID都是使用LightBlue獲知蹦骑。
*/

如有錯(cuò)誤之處慈省,望看到此文的大神批評(píng)指正,謝謝眠菇!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末边败,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子捎废,更是在濱河造成了極大的恐慌笑窜,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件登疗,死亡現(xiàn)場離奇詭異排截,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)辐益,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門断傲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人智政,你說我怎么就攤上這事认罩。” “怎么了续捂?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵垦垂,是天一觀的道長宦搬。 經(jīng)常有香客問我,道長劫拗,這世上最難降的妖魔是什么间校? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮页慷,結(jié)果婚禮上撇簿,老公的妹妹穿的比我還像新娘。我一直安慰自己差购,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布汉嗽。 她就那樣靜靜地躺著欲逃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饼暑。 梳的紋絲不亂的頭發(fā)上稳析,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音弓叛,去河邊找鬼彰居。 笑死,一個(gè)胖子當(dāng)著我的面吹牛撰筷,可吹牛的內(nèi)容都是我干的陈惰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毕籽,長吁一口氣:“原來是場噩夢啊……” “哼抬闯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起关筒,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤溶握,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蒸播,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睡榆,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年袍榆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胀屿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜡塌,死狀恐怖碉纳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情馏艾,我是刑警寧澤劳曹,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布奴愉,位于F島的核電站,受9級(jí)特大地震影響铁孵,放射性物質(zhì)發(fā)生泄漏锭硼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一蜕劝、第九天 我趴在偏房一處隱蔽的房頂上張望檀头。 院中可真熱鬧,春花似錦岖沛、人聲如沸暑始。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽廊镜。三九已至,卻和暖如春唉俗,著一層夾襖步出監(jiān)牢的瞬間嗤朴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工虫溜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雹姊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓衡楞,卻偏偏與公主長得像吱雏,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘾境,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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