iOS藍(lán)牙編程CoreBluetooth

iOS的藍(lán)牙框架是支持藍(lán)牙4.0協(xié)議的婉刀。
理解iOS CoreBluetooth兩個(gè)很重要的概念脊另,Central 和 Periperal Devices
這兩個(gè)概念可以用傳統(tǒng)的模式client-server來(lái)理解嗅钻,central意思是中心粤剧,其作用類(lèi)似server,periperal就是外設(shè)奕污,一般攜帶有數(shù)據(jù),我們需要去其中獲取數(shù)據(jù)按厘,下圖是蘋(píng)果官網(wǎng)的例子医吊,peripheral是心跳儀,按期作用逮京,我們?nèi)ミ@個(gè)外設(shè)中取心跳數(shù)據(jù)遮咖,則心跳儀的作用就類(lèi)似server了,我們的手機(jī)去心跳儀中獲取數(shù)據(jù)造虏,類(lèi)似client御吞。


Peripheral如何讓central知道它的存在呢? peripheral.比如上圖的心跳儀,通過(guò)不斷廣播自己的存在,并且在廣播過(guò)程中附帶廣告包(advertising packet),這樣你就發(fā)現(xiàn)了這個(gè)設(shè)備漓藕,并且獲取到它提供的服務(wù)陶珠。


介紹完這些概念,我們來(lái)看看實(shí)際代碼應(yīng)該如何填寫(xiě).這里對(duì)于我的藍(lán)牙小票機(jī)來(lái)編寫(xiě)的享钞,因?yàn)槲乙獙?duì)藍(lán)牙小票機(jī)器進(jìn)行寫(xiě)操作揍诽,手機(jī)是搜索peripharal的,所以手機(jī)為central,小票機(jī)為peripharal栗竖。

  1. 首先導(dǎo)入這個(gè)框架

  2. 該框架有主要有幾個(gè)類(lèi)值得我們注意,CBCentralManager暑脆,也就是我們之前提到的Central,可以用來(lái)發(fā)現(xiàn)外設(shè)的。
    #import

     @interface ViewController () 
    
     @property (nonatomic, retain) CBCentralManager *centralManager;
    
     @end
    
     @implementation ViewController
    
     - (void)viewDidLoad {
         [super viewDidLoad];
         // Do any additional setup after loading the view, typically from a nib.
         self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
     }
    

上面代碼這里我們創(chuàng)建了一個(gè)CBCentralManager,用來(lái)發(fā)現(xiàn)外設(shè)狐肢,當(dāng)創(chuàng)建成功添吗,CBCentralManager會(huì)回調(diào)代理說(shuō)創(chuàng)建成功了,如下面代碼

    /*
     Invoked whenever the central manager's state is updated.
     */
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
    NSString * state = nil;

    switch ([central state])
    {
        case CBCentralManagerStateUnsupported:
            state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
            break;
        case CBCentralManagerStateUnauthorized:
            state = @"The app is not authorized to use Bluetooth Low Energy.";
            break;
        case CBCentralManagerStatePoweredOff:
            state = @"Bluetooth is currently powered off.";
            break;
        case CBCentralManagerStatePoweredOn:
            state = @"work";
            break;
        case CBCentralManagerStateUnknown:
        default:
            ;
    }

    NSLog(@"Central manager state: %@", state);
    }

上面的代碼如果這個(gè)時(shí)候如果是CBCentralManagerStatePoweredOn份名,代表藍(lán)牙可用碟联。一定要在該方法回調(diào)后去開(kāi)啟掃描外設(shè),否則無(wú)反應(yīng).

  1. 現(xiàn)在可以連接掃描外設(shè)了

     - (IBAction)scan:(id)sender {
     [self.centralManager scanForPeripheralsWithServices:nil options:nil];
     }
    

上面代碼我創(chuàng)建了一個(gè)按鈕來(lái)掃描僵腺,就不上對(duì)應(yīng)的xib圖片了.
這個(gè)方法如果傳入的事nil,代表掃描所有外設(shè)鲤孵。
- (IBAction)scan:(id)sender {
[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"FFE0"]] options:nil];
}
如果你只想搜索有提供對(duì)應(yīng)的服務(wù)號(hào)的外設(shè)(去peripharal 的advertising packet里匹配服務(wù)號(hào),傳入一個(gè)數(shù)組進(jìn)入辰如,對(duì)象為CBUUID,也就是Service的唯一標(biāo)識(shí)符普监。一般我們搜索過(guò)一個(gè)nil的就會(huì)知道我們要的服務(wù)好是什么樣子的了,之后編程就可以直接使用這個(gè)已知的服務(wù)好琉兜。除非你的藍(lán)牙設(shè)備的廠家更改服務(wù)號(hào)凯正,不過(guò)幾乎不可能。
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
static int i = 0;
NSString *str = [NSString stringWithFormat:@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.UUID, advertisementData];
NSLog(@"%@",str);
[self.discoverdPeriparals addObject:peripheral];
}
當(dāng)你發(fā)現(xiàn)了一個(gè)設(shè)備呕童,該方法會(huì)回調(diào)漆际。peripheral代表你發(fā)現(xiàn)的設(shè)備,advertisementData時(shí)廣告數(shù)據(jù)夺饲,rssi代表著信號(hào)強(qiáng)度.



從廣播數(shù)據(jù)中可以看到一個(gè)服務(wù)UUIDs,因?yàn)閺V播數(shù)據(jù)有數(shù)量大小限制奸汇,數(shù)據(jù)比較少。不過(guò)目前我們只是發(fā)現(xiàn)了這個(gè)設(shè)備往声,假設(shè)該設(shè)備已經(jīng)是我們感興趣的設(shè)備擂找,你可以通過(guò)[self.centralManager stopScan]來(lái)停止掃描,也可以繼續(xù)掃描浩销。

  1. 連接發(fā)現(xiàn)的外設(shè)
    - (IBAction)connect:(id)sender {
    [self.centralManager connectPeripheral: [self.discoverdPeriparals firstObject] options:nil];
    }
    假設(shè)第一個(gè)是我們需要的外設(shè)贯涎,連接它。

     /*
      Invoked whenever a connection is succesfully created with the peripheral.
      Discover available services on the peripheral
      */
     - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
     {
         NSLog(@"Did connect to peripheral: %@", peripheral);
         peripheral.delegate = self;
         [central stopScan];
         [peripheral discoverServices:nil];
     }
    

當(dāng)連接成功后調(diào)用該方法慢洋。這個(gè)時(shí)候我們?cè)O(shè)置該peripheral的代理我們自己塘雳,讓peripheral給我們返回所有服務(wù)陆盘。
[peripheral discoverServices:@[[CBUUID UUIDWithString:@"FFE0"]]];
這個(gè)方法也是傳入nil返回所有服務(wù),如果是傳入特定的服務(wù)id,只返回該服務(wù) 這里我們傳入nil來(lái)返回所有服務(wù)
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if (error)
{
NSLog(@"Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
return;
}

        for (CBService *service in peripheral.services)
        {
            NSLog(@"Service found with UUID: %@", service.UUID);
            if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]])
            {
                 [peripheral discoverCharacteristics:nil forService:service];
            }   
        }
    }

這里看到返回了兩個(gè)服務(wù)败明,因?yàn)樾枰狥FE0,所以讓該服務(wù)返回對(duì)應(yīng)的characteristics.
[peripheral discoverCharacteristics:nil forService:service];

    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
    {
        if (error)
        {
            NSLog(@"Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
            return;
        }
        for (CBCharacteristic * characteristic in service.characteristics)
        {
            DLog(@"%@",characteristic);
            if( [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]])
            {
                self.p = peripheral;
                self.c = characteristic;

                //read
                //[testPeripheral readValueForCharacteristic:characteristic];
                NSLog(@"Found a Device Manufacturer Name Characteristic - Read manufacturer name");
            }
        }
    }

上面的方法是找到FEE0服務(wù)的所有特征隘马,這里的只有一個(gè),也就藍(lán)牙小票機(jī)FFE0寫(xiě)服務(wù)的寫(xiě)特征. 獲取到該特征妻顶。進(jìn)行寫(xiě)服務(wù)酸员,具體的log就不寫(xiě)了
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSString *RStr = @"2764";
NSMutableString *str = [NSMutableString new];
[str appendFormat:@"%c", 28];
[str appendFormat:@"%c", 33];
[str appendFormat:@"%c", 8];

        [self.p writeValue:[str dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
        RStr = @"吳彥祖 你好呀!!!\n\n\n\n\n\n\n\n";
        [self.p writeValue:[RStr dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
    }

這里我對(duì)藍(lán)牙小票機(jī)提供的寫(xiě)特征進(jìn)行寫(xiě)服務(wù)。成功.

補(bǔ)充: 如果該特征是可以讀特征讳嘱,你可以對(duì)該特征進(jìn)行訂閱幔嗦。

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

該方法回調(diào)peripheral:didUpdateValueForCharacteristic:error:方法

當(dāng)你訂閱成功后,如果數(shù)據(jù)有更新沥潭,則回調(diào)該方法邀泉。 你就可以去讀取你想要的數(shù)據(jù)了。

如果想要了解更多叛氨,建議查看iOS官方文檔提供的CoreBluetooth programming guid呼渣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市寞埠,隨后出現(xiàn)的幾起案子屁置,更是在濱河造成了極大的恐慌,老刑警劉巖仁连,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓝角,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饭冬,警方通過(guò)查閱死者的電腦和手機(jī)使鹅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)昌抠,“玉大人患朱,你說(shuō)我怎么就攤上這事〈渡唬” “怎么了裁厅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)侨艾。 經(jīng)常有香客問(wèn)我执虹,道長(zhǎng),這世上最難降的妖魔是什么唠梨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任袋励,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茬故。我一直安慰自己盖灸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布均牢。 她就那樣靜靜地躺著糠雨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徘跪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天琅攘,我揣著相機(jī)與錄音垮庐,去河邊找鬼。 笑死坞琴,一個(gè)胖子當(dāng)著我的面吹牛哨查,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剧辐,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼寒亥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了荧关?” 一聲冷哼從身側(cè)響起溉奕,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忍啤,沒(méi)想到半個(gè)月后加勤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡同波,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年鳄梅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片未檩。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡戴尸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冤狡,到底是詐尸還是另有隱情孙蒙,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布筒溃,位于F島的核電站马篮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怜奖。R本人自食惡果不足惜浑测,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迁央,春花似錦掷匠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蜂科,卻和暖如春顽决,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背导匣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工才菠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贡定。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓赋访,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親缓待。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚓耽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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