iOS藍牙開發(fā)(bluetooth)

藍牙庫( 4.0 BLE )

蘋果自身有一個操作藍牙的庫 CoreBluetooth.framework肥哎,這是 大部分人進行藍牙開發(fā)的首選框架。
除此之外,目前github上還有一個比較流行的對原生框架進行封裝的三方庫 BabyBluetooth

藍牙設備版本要求

藍牙設備必須是4.0及以上.
BLE : bluetouch low enery,藍牙4.0設備因為低功耗,所以也被稱為BLE垢夹。蘋果在 iphone4s 及之后的手機都支持藍牙4.0。
低于藍牙4.0協(xié)議的設備需要進行MFI認證
MFI : make for ipad, iphone, itouch 專門為蘋果設備制作的設備
MFI : 開發(fā)框架為 ExternalAccessory 框架
BLE 4.0 : 開發(fā)框架為 CoreBluetooth 框架

藍牙知識 ( 主講中心模式维费,外設暫未開發(fā)留作以后補充 )

藍牙處理是16進制果元,并且每次傳輸最多是20個字節(jié)
CoreBluetooth 框架主要核心部分就是兩個,peripheral 和 central犀盟。
發(fā)起連接的是中心設備而晒,被連接的是外圍設備。
中心模式:以app作為中心阅畴,連接其他外設的場景
外設模式:使用手機作為外設連接其他中心設備的操作場景

服務倡怎,特征,特征的屬性(service and characteristic)

一個外設可以包含一個或多個服務(CBService)贱枣,一個服務又包含一個或多個特征(CBCharacteristic)监署,特征就是具體功能的鍵值對,提供數(shù)據的地方纽哥。每個特征的屬性分為:通知钠乏,讀,寫這幾種方式

外設春塌,服務晓避,特征之間的關系如下:


關系圖

藍牙中心模式流程 ( 以BabyBluetooth為例 )

1.初始化中心設備管理者:CBCentralManager
/**
將藍牙模塊進行封裝單例
初始化藍牙設置藍牙中心設備
*/
+ (instancetype)shareBaby {
    
    static BabyBlueToothManager *babyBluetooth;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!babyBluetooth) {
            babyBluetooth = [[self class] alloc];
            // 提示藍牙功能開啟
            NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey: @YES};
            babyBluetooth.centeralManager = [[CBCentralManager alloc] initWithDelegate:babyBluetooth queue:nil options:options];
            
            // 初始化 baby 藍牙庫
            babyBluetooth.baby = [BabyBluetooth shareBabyBluetooth];
            // 設置藍牙代理
            [babyBluetooth babyDelegate];
           //babyBluetooth.baby.scanForPeripherals().begin();
        }
    });
    return babyBluetooth;
}
2.掃描外圍設備
[BabyBlueToothManager shareBaby].baby.scanForPeripherals().begin();
3.掃描結果通過CBCentralManagerDelegate代理進行回調簇捍,這里BabyBluetooth進行block塊封裝
/**
搜索設備獲取中心設備,
外設
外設advertisementData數(shù)據(廣告數(shù)據)够滑,通常情況下mac地址會存儲在這里
RSSI為信號強度
*/
[_baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"搜索到了設備:%@",peripheral.name);
        @strongify_self
    
    }];
/**
獲取外設后,對外設進行過濾吕世,篩選符合規(guī)則的藍牙設備
*/
[_baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        //判斷設備彰触,通過相應規(guī)則搜索出的設備會顯示在  BlockOnDiscoverToPeripherals 這個方法中
        if (peripheralName.length >1) {
            if ([advertisementData[@"kCBAdvDataLocalName"] hasPrefix:@"Pxxxxx"] || [advertisementData[@"kCBAdvDataLocalName"] hasPrefix:@"Sxxxx"]) {
                return YES;
            }
        }
        return NO;
    }];
4.連接設備并斷開搜索
/**
 連接藍牙
 */

- (void)connetBlueToothWithCBPeripheral:(CBPeripheral *)peripheral {
    
// 連接外設.發(fā)現(xiàn)服務.發(fā)現(xiàn)特征.讀取特征數(shù)據.發(fā)現(xiàn)特征數(shù)據(鍵值對).讀取特征描述.開始連接
self.baby.having(peripheral).connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();  
// 取消搜索藍牙
    [self.baby cancelScan];

}
5.設備連接狀態(tài)回調
// 設備連接成功
    [_baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        NSLog(@"設備:%@--連接成功",peripheral.name);
        @strongify_self
    }];

//設置設備連接失敗的委托
    [_baby setBlockOnFailToConnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"設備:%@--連接失敗",peripheral.name);
        [GGProgress showProgressWithTitle:@"設備連接失敗"];
    }];

//設置設備斷開連接的委托
    [_baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"設備:%@--斷開連接",peripheral.name);
        @strongify_self
        // 這里可以處理重新連接
    }];
6.連接成功后發(fā)現(xiàn)設備服務(service)
// 發(fā)現(xiàn)設備服務
 [_baby setBlockOnDiscoverServices:^(CBPeripheral *peripheral, NSError *error) {
        for (CBService *s in peripheral.services) {
            //每個service
        }
    }];
//設置發(fā)現(xiàn)設service的Characteristics的委托
    [_baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"===service name:%@",service.UUID);
        [service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull characteristic, NSUInteger idx, BOOL * _Nonnull stop) {
            // 通過枚舉獲取服務特征
            NSLog(@"aaaaaaaa    %@ \n %lu ", characteristic.UUID , (unsigned long)characteristic.properties);
        }];
    }];
 //設置發(fā)現(xiàn)characteristics的descriptors的委托
    [_baby setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
7.讀取設備服務-特征的數(shù)據
  [_baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        // 
        @strongify_self
        CBUUID *uuid = characteristics.UUID;
        if ([uuid.UUIDString isEqualToString:@"xxxx"]) {
            // 如果是想要的服務特征 則賦值到 相對應的 外設及 特征中,進行數(shù)據交互
            self.characteristic = characteristics;
            self.peripheral = peripheral;
        }
    }];
8.讀取特征的數(shù)據描述(鍵值對)命辖,注冊特征通知况毅,中心設備讀取外設外圍所發(fā)送過來的數(shù)據
   //設置讀取Descriptor的委托
       [_baby setBlockOnReadValueForDescriptors:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        @strongify_self
        CBUUID *uuid = descriptor.characteristic.UUID;
        CBCharacteristic *charach = descriptor.characteristic;
        NSData *data = charach.value;
        //  判斷是否是當前設備
        if ([[BlueToothInfo shareBlueToothInfo].localName isEqualToString:@"xxxx"]) {
            // 獲取 所要獲取的特征
            if ([uuid.UUIDString isEqualToString:@"xxxx"]) {
                self.characteristic = descriptor.characteristic;
                self.peripheral = peripheral;
            }else {
                // 進行注冊特征通知,獲取外圍數(shù)據
                [self.baby notify:peripheral characteristic:descriptor.characteristic block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                    @strongify_self
                     // 收到的指令數(shù)據
                    NSData *wineData = characteristics.value;
                    // 16進制數(shù)據轉換尔艇,判斷指令
                    NSString *str16 = [self convertDataToHexStr:wineData];
                }];
            }
        }
        NSLog(@"Descriptor name:%@ value is:%@\n %@",descriptor.characteristic.UUID, descriptor.value, data);
    }];
9.處理數(shù)據(數(shù)據接收結束)尔许。以下為向外圍設備發(fā)送數(shù)據
/** 通過單例 獲取當前外設, 通過特征值進行寫入操作
data 通過 NSASCIIStringEncoding ASCII進行轉換终娃,藍牙接收數(shù)據為16進制
 writeType 分為兩種
1.CBCharacteristicWriteWihResponse(寫成功一次味廊,只可讀)即有反饋
2.CBCharacteristicWriteWithoutResponse(一次也不能寫成功,可以讀棠耕,也可以通知)即無反饋
*/
[[BabyBlueToothManager shareBaby].peripheral writeValue:data forCharacteristic:[BabyBlueToothManager shareBaby].characteristic type:writeType];
// 寫入的數(shù)據 均在 步驟 8中的 notify 回調中 回調數(shù)據
10.寫入成功與否的回調
//寫Characteristic成功后的block
 [_baby setBlockOnDidWriteValueForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
        // error判斷 寫入特征是否成功余佛,自行處理
    }];
//寫descriptor成功后的block
[_baby setBlockOnDidWriteValueForDescriptor:^(CBDescriptor *descriptor, NSError *error) {
         // error判斷 寫入特征描述數(shù)據是否成功,自行處理
    }];
11.斷開連接
//斷開連接
- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral {
    [babyCentralManager cancelPeripheralConnection:peripheral];
}
//斷開所有連接
- (void)cancelAllPeripheralsConnection {
    [babyCentralManager cancelAllPeripheralsConnection];
}

如有疑問可以探討窍荧,如有錯誤可以指正辉巡,歡迎補充,感謝支持??

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蕊退,一起剝皮案震驚了整個濱河市郊楣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓤荔,老刑警劉巖净蚤,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異输硝,居然都是意外死亡塞栅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門腔丧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來放椰,“玉大人,你說我怎么就攤上這事愉粤±剑” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵衣厘,是天一觀的道長如蚜。 經常有香客問我压恒,道長,這世上最難降的妖魔是什么错邦? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任探赫,我火速辦了婚禮,結果婚禮上撬呢,老公的妹妹穿的比我還像新娘伦吠。我一直安慰自己,他們只是感情好魂拦,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布毛仪。 她就那樣靜靜地躺著,像睡著了一般芯勘。 火紅的嫁衣襯著肌膚如雪箱靴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天荷愕,我揣著相機與錄音衡怀,去河邊找鬼。 笑死安疗,一個胖子當著我的面吹牛狈癞,可吹牛的內容都是我干的。 我是一名探鬼主播茂契,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蝶桶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了掉冶?” 一聲冷哼從身側響起真竖,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厌小,沒想到半個月后恢共,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡璧亚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年讨韭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片癣蟋。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡透硝,死狀恐怖,靈堂內的尸體忽然破棺而出疯搅,到底是詐尸還是另有隱情濒生,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布幔欧,位于F島的核電站罪治,受9級特大地震影響丽声,放射性物質發(fā)生泄漏。R本人自食惡果不足惜觉义,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一雁社、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晒骇,春花似錦霉撵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屠缭。三九已至箍鼓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呵曹,已是汗流浹背款咖。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奄喂,地道東北人铐殃。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像跨新,于是被迫代替她去往敵國和親富腊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • 今天感恩節(jié)哎域帐,感謝一直在我身邊的親朋好友赘被。感恩相遇!感恩不離不棄肖揣。 中午開了第一次的黨會民假,身份的轉變要...
    迷月閃星情閱讀 10,551評論 0 11
  • 彩排完,天已黑
    劉凱書法閱讀 4,187評論 1 3
  • 表情是什么龙优,我認為表情就是表現(xiàn)出來的情緒羊异。表情可以傳達很多信息。高興了當然就笑了彤断,難過就哭了野舶。兩者是相互影響密不可...
    Persistenc_6aea閱讀 124,207評論 2 7