iOS開發(fā)-藍(lán)牙4.0-BLE開發(fā)(代碼篇)

上一篇文章我們講了iOS開發(fā)的理論知識,下面我們就從代碼開始講解。

1.CoreBluetooth.framework導(dǎo)入

1.在General->TARGETS->Linked Framworks and Libraries中點(diǎn)擊添加并選擇CoreBluetooth.framework導(dǎo)入症杏。


image

2.在代碼中導(dǎo)入CoreBluetooth.framework Swift:import CoreBluetooth Objective-C:#import

3.聲明協(xié)議:使用CoreBluetooth需要支持CBCentralManagerDelegate(需要藍(lán)牙管理者mgr 管理者可以掃描外圍設(shè)備), CBPeripheralDelegate協(xié)議(mgr掃描到外設(shè)桨踪,與外設(shè)進(jìn)行連接斷開連接信息交流等一系列反饋回調(diào)),即前面所說的中心設(shè)備和外圍設(shè)備缅叠,并實(shí)現(xiàn)相應(yīng)方法

2.建立一個Central Manager實(shí)例進(jìn)行藍(lán)牙管理

self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

一旦設(shè)置代理在運(yùn)行程序的時候,就會調(diào)用協(xié)議里一個必須要完成的方法:
這個方法是查看中心設(shè)備是否打開藍(lán)牙虏冻。
#pragma mark - 只要中心管理者初始化 就會觸發(fā)此代理方法 判斷手機(jī)藍(lán)牙狀態(tài)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state)
    {
            // PoweredOff
        case CBCentralManagerStatePoweredOff:
            break;
            // PoweredOn
        case CBCentralManagerStatePoweredOn: //藍(lán)牙已開啟
            // 搜索外設(shè)
            [self.centralManager scanForPeripheralsWithServices:nil  options:self.centralManagerOptionDic];
            break;
            // Resetting
        case CBCentralManagerStateResetting:
            break;
            // Unsupported
        case CBCentralManagerStateUnsupported: //不支持藍(lán)牙
            break;
            // Unauthorized
        case CBCentralManagerStateUnauthorized:
            break;
            // Unknown state
        case CBCentralManagerStateUnknown:
            break;
        default:
            break;
    }
}
[manager scanForPeripheralsWithServices:nil options:nil];
第一個參數(shù)那里表示掃描帶有相關(guān)服務(wù)的外部設(shè)備肤粱,例如填寫@[[CBUUIDUUIDWithString:@"需要連接的外部設(shè)備的服務(wù)的UUID"]],即表示帶有需要連接的外部設(shè)備的服務(wù)的UUID的外部設(shè)備厨相,nil表示掃描全部設(shè)備领曼;
options處以后細(xì)講,暫時可以寫一個@{CBCentralManagerScanOptionAllowDuplicatesKey :@YES}這樣的參數(shù)蛮穿,YES表示會讓中心設(shè)備不斷地監(jiān)聽外部設(shè)備的消息庶骄,NO就是不能。

3.掃描周邊的藍(lán)牙設(shè)備

// 1.中心管理者 2.外設(shè) 3.外設(shè)攜帶的數(shù)據(jù) 4.外設(shè)發(fā)出的藍(lán)牙信號強(qiáng)度
- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI
{
     /*
     peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341, Name = "OBand-75", state = disconnected>, advertisementData = {
     kCBAdvDataChannel = 38;
     kCBAdvDataIsConnectable = 1;
     kCBAdvDataLocalName = OBand;
     kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
     kCBAdvDataServiceUUIDs =     (
     FEE7
     );
     kCBAdvDataTxPowerLevel = 0;
     }, RSSI = -55
     
     */
    
    if ([peripheral.name hasPrefix:@"OBand"]) {
        [self.centralManager stopScan];
        // 在此處對我們的 advertisementData(外設(shè)攜帶的廣播數(shù)據(jù)) 進(jìn)行一些處理
        // 標(biāo)記我們的外設(shè),讓他的生命周期 = vc
        self.peripheral = peripheral;
        // 發(fā)現(xiàn)完之后就是進(jìn)行連接
        [self.centralManager connectPeripheral:self.peripheral options:nil];
        NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
    }
}

4.連接外圍設(shè)備

// 中心管理者連接外設(shè)成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"%s, line = %d, %@=連接成功", __FUNCTION__, __LINE__, peripheral.name);
    // 連接成功之后,可以進(jìn)行服務(wù)和特征的發(fā)現(xiàn)
    
    //  設(shè)置外設(shè)的代理
    self.peripheral.delegate = self;
    
    // 外設(shè)發(fā)現(xiàn)服務(wù),傳nil代表不過濾
    // 這里會觸發(fā)外設(shè)的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    [self.peripheral discoverServices:nil];
}

// 連接失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullableNSError *)error;(連接失敿酢)

// 丟失連接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"%s, line = %d, %@=斷開連接", __FUNCTION__, __LINE__, peripheral.name);
}

5.獲得外圍設(shè)備的服務(wù) & 6.獲得服務(wù)的特征

#pragma mark - CBPeripheralDelegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
    
    if (error)
    {
        NSLog(@"error:%@",error.localizedDescription);
        return ;
    }
    
    for (CBService *service in peripheral.services)
    {
         NSLog(@"Discovered service %@", service);

        [peripheral discoverCharacteristics:nil forService:service];
    }
}
當(dāng)我們掃描到特征的時候单刁,就會跳入發(fā)現(xiàn)特征的協(xié)議方法里去:

// 發(fā)現(xiàn)外設(shè)服務(wù)里的特征的時候調(diào)用的代理方法(這個是比較重要的方法,你在這里可以通過事先知道UUID找到你需要的特征府适,訂閱特征幻碱,或者這里寫入數(shù)據(jù)給特征也可以)
- (void)peripheral:(CBPeripheral *)peripheral
  didDiscoverCharacteristicsForService:(CBService *)service
                    error:(nullable NSError *)error
{
    
    if (error) {
        NSLog(@"error:%@",error.localizedDescription);
        return ;
    }
    
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);

    // 下面的36F6和36F5根據(jù)需求自己定義
    for (CBCharacteristic *characteristic in service.characteristics)
    {
        if ([[[characteristic UUID] UUIDString] isEqualToString:@"36F6"])
        {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
        else if([[[characteristic UUID] UUIDString] isEqualToString:@"36F5"] )
        {
            // 記錄要之后每次要寫入的特征
            writeCBCharacteristic = characteristic;
        }
    }    
}

7.給外圍設(shè)備發(fā)送數(shù)據(jù)(也就是寫入數(shù)據(jù)到藍(lán)牙)

發(fā)送數(shù)據(jù)只需要在指定的service和characteristic組合下發(fā)送即可,如果是以CBCharacteristicWriteWithResponse模式發(fā)送细溅,發(fā)送完后還會調(diào)用
CBPeripheralDelegate的peripheral:(CBPeripheral *) didWriteValueForCharacteristic:(CBCharacteristic *) error:(NSError *)褥傍,實(shí)現(xiàn)該協(xié)議方法可判斷發(fā)送是否成功。
以CBCharacteristicWriteWithoutResponse模式則不會有回調(diào)喇聊。

[connectPeripheral writeValue:data forCharacteristic:writeCBCharacteristic type:CBCharacteristicWriteWithResponse];
//第一個參數(shù)是已連接的藍(lán)牙設(shè)備 恍风;第二個參數(shù)是要寫入到哪個特征; 第三個參數(shù)是通過此響應(yīng)記錄是否成功寫入

- (void)peripheral:(CBPeripheral *)peripheral
    didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
    error:(nullable NSError *)error
{
    
    if (error)
    {
        NSLog(@"error:%@, %@",error.localizedDescription, characteristic);
        return ;
    }

    if (!(characteristic.properties & CBCharacteristicPropertyNotify))
    {
        [peripheral readValueForCharacteristic:characteristic];
    }
}

8.從外圍設(shè)備讀數(shù)據(jù)

// 更新特征的value的時候會調(diào)用 (凡是從藍(lán)牙傳過來的數(shù)據(jù)都要經(jīng)過這個回調(diào)誓篱,簡單的說這個方法就是你拿數(shù)據(jù)的唯一方法) 你可以判斷是否修改密碼成功, 獲取電量信息等, 以及getToken(以我工程藍(lán)牙鎖為例子)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
    if (characteristic == @"你要的特征的UUID或者是你已經(jīng)找到的特征") {
    //characteristic.value就是你要的數(shù)據(jù), 類型是NSData, 二進(jìn)制數(shù)據(jù)
    }
}

// 如果有寫特征將notift設(shè)置為yes之后: [peripheral setNotifyValue:YES forCharacteristic:c]朋贬,訂閱的通知消息會走下面這個接口
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{}

以上內(nèi)容有寫的不對的地方,請大家指出窜骄,有理解不了的地方可以同我交流锦募。

參考資料:
iOS藍(lán)牙開發(fā):藍(lán)牙連接和數(shù)據(jù)讀寫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市邻遏,隨后出現(xiàn)的幾起案子糠亩,更是在濱河造成了極大的恐慌虐骑,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赎线,死亡現(xiàn)場離奇詭異廷没,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)垂寥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門颠黎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滞项,你說我怎么就攤上這事狭归。” “怎么了文判?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵过椎,是天一觀的道長。 經(jīng)常有香客問我律杠,道長潭流,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任柜去,我火速辦了婚禮灰嫉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗓奢。我一直安慰自己讼撒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布股耽。 她就那樣靜靜地躺著根盒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪物蝙。 梳的紋絲不亂的頭發(fā)上炎滞,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音诬乞,去河邊找鬼册赛。 笑死,一個胖子當(dāng)著我的面吹牛震嫉,可吹牛的內(nèi)容都是我干的森瘪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼票堵,長吁一口氣:“原來是場噩夢啊……” “哼扼睬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悴势,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤窗宇,失蹤者是張志新(化名)和其女友劉穎措伐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體担映,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡废士,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年叫潦,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝇完。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡矗蕊,死狀恐怖短蜕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情傻咖,我是刑警寧澤朋魔,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站卿操,受9級特大地震影響警检,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜害淤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一扇雕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窥摄,春花似錦镶奉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至币砂,卻和暖如春建峭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背决摧。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工亿蒸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜜徽。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓祝懂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拘鞋。 傳聞我的和親對象是個殘疾皇子砚蓬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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