本文主要介紹基于藍(lán)牙4.0的智能硬件開發(fā)。藍(lán)牙4.0主要基于<CoreBluetooth/CoreBluetooth.h>這個(gè)庫文件菌湃,下面將以此介紹每個(gè)類的作用.并提供自己對(duì)這些類封裝问拘,最后附有代碼的連接。
CBCentralManager:負(fù)責(zé)查詢用戶藍(lán)牙的狀態(tài)惧所、掃描周圍可見的外設(shè)骤坐、停止掃描、連接指定的外設(shè)等方法通過該類提供下愈,并且通過代理的形式回調(diào)當(dāng)前藍(lán)牙的狀態(tài);
-(void)centralManagerDidUpdateState:(CBCentralManager *)central {
}
掃描到的外設(shè)纽绍;
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
}
連接指定外設(shè)
[centralManager connectPeripheral:peripheral options:nil];
以及連接外設(shè)的狀態(tài)。
//斷開連接
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
}
//連接失敗
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
}
//連接成功
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
}
CBCentralManager的掃描和連接通過其.h文件我們都能一目了然看出势似,說一下查詢用戶狀態(tài)這方法拌夏,這個(gè)方法的觸發(fā)時(shí)機(jī)其實(shí)在初始化CBCentralManager的時(shí)候,系統(tǒng)內(nèi)部會(huì)進(jìn)行相應(yīng)Api的調(diào)用履因,我們只要在對(duì)應(yīng)的回調(diào)中監(jiān)聽即可障簿。
[[CBCentralManager alloc] initWithDelegate:self queue:nil];
對(duì)于queue這個(gè)參數(shù)我在最后會(huì)做一些介紹,一般只需要給nil代表所有回調(diào)會(huì)在主線程中栅迄。
對(duì)于作過藍(lán)牙相關(guān)開發(fā)的卷谈,有可能會(huì)對(duì)這一系列類進(jìn)行一些封裝,夠后面使用霞篡,而對(duì)于CBCentralManager以懶加載的形式提供世蔗,這樣容易造成一個(gè)問題--->用戶藍(lán)牙狀態(tài)的查詢加只會(huì)進(jìn)行一次查詢,在切換另一個(gè)業(yè)務(wù)頁面的時(shí)候無法獲取當(dāng)前用戶藍(lán)牙狀態(tài)朗兵,造成用戶體驗(yàn)不佳污淋。下面介紹CBPeripheral
CBPeripheral:一種對(duì)外設(shè)的抽象,一個(gè)CBPeripheral對(duì)應(yīng)一個(gè)外設(shè)余掖,它最重要的兩個(gè)特性是外設(shè)的服務(wù)地址和特性地址寸爆,通過服務(wù)地址我們可以找到特性地址,找到特性地址我們就可以寫數(shù)據(jù)了盐欺。下面來介紹具體流程赁豆。
在何時(shí)查找服務(wù),當(dāng)然是在連接外設(shè)成功的時(shí)候了
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
self.currentperipheral = peripheral;//保存起來冗美,后面用的到
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
}
從方法字面意思我們也可以看出大概delegate用來回調(diào)服務(wù)地址的查找情況魔种,其中的services:是一個(gè)外設(shè)服務(wù)地的數(shù)組,可以傳nil粉洼,則會(huì)查找外設(shè)的所有服務(wù)地址节预。
//發(fā)現(xiàn)的服務(wù)地址
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
}
到了這一步我們就可以比照相應(yīng)硬件的協(xié)議文檔了叶摄,如果協(xié)議文檔中的服務(wù)地址被發(fā)現(xiàn)了,可以繼續(xù)下一步了-->該服務(wù)地址下的特性地址安拟。
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
for (CBService *service in peripheral.services) {
if ([service.UUID isEqual:[CBUUID UUIDWithString:addresString]]) {//協(xié)議文檔提供的服務(wù)地址
[peripheral discoverCharacteristics:nil forService:service];
} else continue;
}
}
//對(duì)應(yīng)服務(wù)地址下的特性值蛤吓,特性值一般包含讀和寫,讀用來接收外設(shè)的信息糠赦,寫:向外設(shè)寫數(shù)據(jù)会傲。
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:charactDict[BlueCharacteristicRead]]]) {
#ifdef DEBUG
//NSLog(@"the charact read address:%@",charactDict[BlueCharacteristicRead]);
#endif
[peripheral setNotifyValue:YES forCharacteristic:characteristic];//接收外設(shè)的數(shù)據(jù)
}
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:charactDict[BlueCharacteristicWrite]]]) {
#ifdef DEBUG
// NSLog(@"the charact write address:%@",charactDict[BlueCharacteristicWrite]);
#endif
self.characteristic = characteristic;//把寫的特征值保存起來,用來向外設(shè)寫值拙泽、
}
}
}
到這里我們就可以向外設(shè)寫值和接收數(shù)據(jù)了
寫:
[self.currentperipheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
通過回調(diào)可知道寫入是否失敗(一般不需要處理)
-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
}
外設(shè)發(fā)送的數(shù)據(jù)是通過下面方法來接收
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
}
iOS藍(lán)牙開發(fā)的大致流程介紹到此了淌山,前面說過centralManager初始化之后還有個(gè)queue參數(shù),該參數(shù)可以的作用就是把上面涉及到的一些回調(diào)都加入到該隊(duì)列中奔滑,加入到該隊(duì)列中好處就是可以控制代碼的執(zhí)行順序艾岂,我們只要把鏈接,掃描等操作也加入到該隊(duì)列朋其,就達(dá)到順序的控制王浴,不過這個(gè)沒很大必要。
下面我給一個(gè)我自己封裝的一個(gè)藍(lán)牙庫梅猿。提供了Mac地址的讀取氓辣,和搜索同一類型的外設(shè),斷開重新連接袱蚓,使用起來不難钞啸。
[YYBlueManger sharedManger].delegate = self;
[[YYBlueManger sharedManger] scan];
#pragma mark - YYBlueMangerDelegate
-(void)blueManagerFailedState:(YYBlueManger *)manager statu:(YYBlueManagerState)statu{
//用戶藍(lán)牙狀態(tài)不正常時(shí)候調(diào)用。
}
-(void)blueManagerblescanBluDevice:(YYBlueManger *)manager andTheDevice:(CBPeripheral *)peripheral {
//NSLog(@"%@",peripheral.name);
if ([peripheral.name isEqualToString:@"你想連接的外設(shè)名字"]) {
if ([YYBlueManger sharedManger].connectState == YYBlueConnectStateConnected || [YYBlueManger sharedManger].connectState ==YYBlueConnectStateConnecting) {
return;
}
[[YYBlueManger sharedManger] connect:peripheral orTheDeviceName:nil];
}
}
-(NSArray *)blueManagerServerAdrres:(YYBlueManger *)manager peripheral:(CBPeripheral *)peripheral {
return @[@"0xxxx"];
}
-(NSDictionary *)blueManagerCharacteristicsAdrres:(YYBlueManger *)manager peripheral:(CBPeripheral *)peripheral {
return @{BlueCharacteristicWrite:@"0xxxxx",BlueCharacteristicRead:@"0xxxxx"};
}
-(void)blueManagerdidConnectSuccees:(YYBlueManger *)manager peripheral:(CBPeripheral *)peripheral {
NSLog(@"連接成功");
[[YYBlueManger sharedManger] stop];
}
-(void)blueManagerFailedConnect:(YYBlueManger *)manager peripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"連接失敗");
[[YYBlueManger sharedManger] scan];
}
-(void)blueManagerCutConnect:(YYBlueManger *)manager peripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"斷開連接");
[[YYBlueManger sharedManger] scan];
}
[[YYBlueManger sharedManger] writeDataToDevice:nil writeHandle:nil];
github連接:https://github.com/jsonsnow/CoreBlue.git
好久沒接觸智能硬件了喇潘,這幾天又開始智能硬件的開發(fā)体斩,用自己寫的庫也發(fā)現(xiàn)其中存在幾個(gè)問題
在resetConnect的時(shí)候,發(fā)現(xiàn)維持的connect狀態(tài)混亂颖低,因?yàn)樵谌∠耙粋€(gè)已經(jīng)連接的外設(shè)的時(shí)候會(huì)調(diào)用disConnect方法絮吵,導(dǎo)致connectSate = connectSateCut,此事發(fā)現(xiàn)同名字設(shè)備的時(shí)候,因?yàn)閏onnectSate == connectSateCut,因此會(huì)進(jìn)行連接忱屑,解決方法:增加一個(gè)cancelSate 蹬敲,在disConnect中如果connectSate = cancelSate,則直接返回
增加一個(gè)打斷協(xié)議莺戒,在將要連接外設(shè)的時(shí)候調(diào)用willConntetn方法伴嗡,如果實(shí)現(xiàn)方返回YES,則不進(jìn)行此次連接从铲,主要針對(duì)多設(shè)備綁定而設(shè)計(jì)
取消Mac地址讀取瘪校,以及不把已經(jīng)連接的設(shè)備加入數(shù)據(jù)源中
增加一個(gè)搜索外設(shè)的方法,可以給定 @"xxx1,xxx2",則會(huì)搜索名字為xxx1和xxx2的外設(shè)食店,這個(gè)場(chǎng)景主要是針對(duì)外設(shè)名字不同但是其服務(wù)地址和特許值都相同的情形
目前最新的版本還沒上傳渣淤,如有需要可以留下郵箱