iOS 的藍牙分為中心設備(Central)和外設或邊設(Peripheral)。
Central 處于主動地位,可主動發起搜索,連接,發送數據等動作,本篇主要講述的就是 iOS 藍牙做為 Central 時的使用方法。
在使用講解前,我們首先要理解兩個特有名詞——服務與特征。服務與特征對應的是 Peripheral 中的 CBService
和 CBCharacteristic
。在一個外設中,服務可以有多個;在一個服務中,特征可以有多個。
1、做為 Central 時的開發流程
1) 導入 CoreBluetooth/CoreBluetooth.h
2) 遵守 CBCentralManagerDelegate,CBPeripheralDelegate 協議
3) 建立中心角色
4) 掃描外設(discover)
5) 連接外設(connect)
6) 斷開連接
7) 獲取外設的服務與特征
8) 與外設交換數據(讀寫數據)
9) 必須實現centralManagerDidUpdateState:(CBCentral *)central這個require的方法
2、定義全局變量
{
CBManagerCentral *_central;
CBPeripheral *_periperal;
}
3、初始化中心變量
/** 初始化中心角色 */
dispatch_queue_t centralQueue = dispatch_queue_create(@“identify”,DISPATCH_QUEUE_SERIAL);
_central = [[CBManagerCentral alloc] initWithDelegate:self queue:centralQueue];
4、掃描外設
/*
掃描外設,services是外設服務的CBUUID,如果為空則掃描所有的外設
*/
[_central scanForPeripheralsWithServices:@[] option:options];
如果掃描到外設,則調用CBCentralManagerDelegate
中的-(void)centralManager:didDescoverPeripheral:advertisementData:RSSI:
-(void)centralManager:(CBCentralManager *)central didDescoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:):(NSNumber *)RSSI{
If(!peripheral || !peripheral.name || [peripheral.name isEqualToString:@””]){
return;
}
if(“符合條件的peripheral”){
}
}
5、連接外設、查找外設服務與特征
/*
連接外設
options中可以設置一些連接設備的初始屬性鍵值如下
//對應NSNumber的bool值,設置當外設連接后是否彈出一個警告
NSString *const CBConnectPeripheralOptionNotifyOnConnectionKey;
//對應NSNumber的bool值,設置當外設斷開連接后是否彈出一個警告
NSString *const CBConnectPeripheralOptionNotifyOnDisconnectionKey;
//對應NSNumber的bool值,設置當外設暫停連接后是否彈出一個警告
NSString *const CBConnectPeripheralOptionNotifyOnNotificationKey;
*/
[_central connectPeripheral:_peripheral
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
forKey:CBConnectPeripheralOptionNotifyOnNotificationKey]];
連接成功后回調 CBCentralManagerDelegate
的 - (void)centralManager:didConnectPeripheral:
方法
- (void)centralManager:(CBCentralManager *)central
didConnectPeripheral:(CBPeripheral *)peripheral {
peripheral.delegate = self;
_peripheral = peripheral;
// 查找外設服務,serviceUUIDs 為空時查找所有服務
[peripheral discoverServices:@[]];
}
發現服務后調用 CBPeripheralDelegate
的 - (void)peripheral:didDiscoverServices:
方法
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error {
if (error) {
return;
}
for (CBService *service in peripheral.services) {
if ([service.UUID.UUIDString isEqualToString:@"符合條件的 UUIDString"]) {
// 查詢服務對應的特征,characteristicUUIDs 為空時查詢所有特征
[peripheral discoverCharacteristics:@[]
forService:service];
}
}
}
發現特征后調用 CBPeripheralDelegate
的 -(void)peripheral:didDiscoverCharacteristicsForService:error:
方法
-(void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error {
if (error) {
return;
}
// 遍歷特征
for (CBCharacteristic *cha in service.characteristics) {
if ([cha.UUID.UUIDString isEqualToString:kR_UUID]) {
// 特征判斷
}
}
}
特征的屬性 properties
有很多種,不同的屬性標明特征的用途。比如說,現有一特征的 properties
僅為 CBCharacteristicPropertyWrite
,那么這個特征只能用于 Central 端發送數據;而又有一特征的 properties
僅為 CBCharacteristicPropertyRead
那么這個特征只能用于 Central 讀數據
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
CBCharacteristicPropertyBroadcast, //允許廣播特征
CBCharacteristicPropertyRead, //可讀屬性
CBCharacteristicPropertyWriteWithoutResponse, //可寫并且接收回執
CBCharacteristicPropertyWrite, //可寫屬性
CBCharacteristicPropertyNotify, //可通知屬性
CBCharacteristicPropertyIndicate, //可展現的特征值
CBCharacteristicPropertyAuthenticatedSignedWrites, //允許簽名的特征值寫入
CBCharacteristicPropertyExtendedProperties,
CBCharacteristicPropertyNotifyEncryptionRequired,
CBCharacteristicPropertyIndicateEncryptionRequired
};
6、斷開連接
[_centralr cancelPeripheralConnection:_peripheral];
斷開連接后調用 CBCentralManagerDelegate
的 -(void)centralManager:didDisconnectPeripheral:error:
方法
7、發送數據
[_peripheral writeValue:data
forCharacteristic:@"特征的屬性必須含有 CBCharacteristicPropertyWrite 或 CBCharacteristicPropertyWriteWithoutResponse"
type:@"視特征屬性而定"];
數據發送完成調用 CBPeripheralDelegate
的 -(void)peripheral:didWriteValueForCharacteristic:error:
方法
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(nullable NSError *)error {
// 數據發送完成
}
8、讀數據
讀數據有兩種方法:
1、只讀一次數據,讀一次調用一次 - (void)readValueForCharacteristic:
,要確保調用在數據發出來之前,否則會讀不到數據
[_peripheral readValueForCharacteristic:@"特征要包含 CBCharacteristicPropertyRead 屬性"];
2、監聽數據,當數據開啟監聽后,只要有數據發送到客戶端,就會讀到數據
[_peripheral setNotifyValue:YES
forCharacteristic:@"特征要包含 CBCharacteristicPropertyNotify 屬性"];
監聽開啟后會回調 CBPeripheralDelegate
的 -(void)peripheral:didUpdateNotificationStateForCharacteristic:error:
方法
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error) {
NSLog(@"監聽錯誤: %@ -- isNotifiying: %d",
error,characteristic.isNotifying);
return;
}
}
讀到數據回調 CBPeripheralDelegate
的 -(void)peripheral:didUpdateValueForCharacteristic:error:
方法
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic
error:(nullable NSError *)error {
if (error) {
NSLog(@"接收錯誤: %@",error);
[self jmDisconnectWithError:error];
return;
}
}
這兩種方法須要特征的支持。也就是說,如果你的特征為 CBCharacteristicPropertyNotify
時才可以使用監聽讀數據
9、實現代理
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
// 狀態改變
}