藍牙庫( 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];
}
如有疑問可以探討窍荧,如有錯誤可以指正辉巡,歡迎補充,感謝支持??