API Reference
CoreBluetooth中辩棒,需要用到的類和協(xié)議(完整導圖):
基礎知識
藍牙分類中心端和外設端(完整導圖)负拟。
中心端(接收端)
1 .創(chuàng)建中心端控制器(CBCentralManager)
2 .掃描設備(Discover)
3 .連接 (Connect)
4 .獲取Service和Characteristic
- 掃描Service (一個service中包含一個或多個Characteristic)
- 獲取Service中Characteristic
- 獲取Characteristic的值
5 . 數(shù)據(jù)交互(explore and interact)
- 訂閱Characteristic的通知
6 . 斷開鏈接
外設端(發(fā)送端)
- 創(chuàng)建Peripheral管理對象
- 創(chuàng)建Service和Characteristic樹
- 發(fā)送廣告
- 處理讀寫請求和訂閱
藍牙狀態(tài)
typedef NS_ENUM(NSInteger, CBManagerState) {
CBManagerStateUnknown = 0,
CBManagerStateResetting,
CBManagerStateUnsupported, //不支持
CBManagerStateUnauthorized, //未授權(quán)
CBManagerStatePoweredOff, //關(guān)閉
CBManagerStatePoweredOn, //藍牙打開狀態(tài)
} NS_ENUM_AVAILABLE(NA, 10_0);
連接狀態(tài)
/*!
* @enum CBPeripheralState
*
* @discussion Represents the current connection state of a CBPeripheral.
*
*/
typedef NS_ENUM(NSInteger, CBPeripheralState) {
CBPeripheralStateDisconnected = 0,
CBPeripheralStateConnecting,
CBPeripheralStateConnected,
CBPeripheralStateDisconnecting NS_AVAILABLE(NA, 9_0),
} NS_AVAILABLE(NA, 7_0);
CBCentralManagerDelegate
@required
// 更新CentralManager狀態(tài),參數(shù)central就是當前的Manager股淡。
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;
@optional
// 藍牙狀態(tài)的保存和恢復瘤泪,進入后臺和重新啟動有關(guān)
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary<NSString *, id> *)dict;
//掃描外部設備
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;
//與外設完成連接
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;
//連接失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;
//斷開連接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;
CBPeripheralDelegate
@optional
//peripheral更新
- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0);
//服務更新時觸發(fā)
- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices NS_AVAILABLE(NA, 7_0);
//更新RSSI掠械,過時用下一代替
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error NS_DEPRECATED(NA, NA, 5_0, 8_0);
// RSSI值
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error NS_AVAILABLE(NA, 8_0);
//發(fā)現(xiàn)服務
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error;
//發(fā)現(xiàn)嵌套服務
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(nullable NSError *)error;
//發(fā)現(xiàn)服務中的Characteristic
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error;
//更新Characteristic
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error;
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error;
CBPeripheralManagerDelegate
@required
//類似CBCentralManager
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;
@optional
- (void)peripheralManager:(CBPeripheralManager *)peripheral willRestoreState:(NSDictionary<NSString *, id> *)dict;
//開始廣播
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error;
//添加服務
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(nullable NSError *)error;
//訂閱
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;
//未訂閱
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic;
//接收讀取請求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request;
//接收寫入請求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;
//更新訂閱
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;
中心端(接收端)
從上面了解了藍牙開發(fā)的基本流程和API結(jié)構(gòu)微王,那下面我們一起看看中心端的開發(fā)步驟累提。
創(chuàng)建CentralManager
//創(chuàng)建CentralManager
- (void)startUpCentralManager {
_centralManager = [[CBCentralManager alloc] initWithDelegate: self queue: nil];
_peripherals = [NSMutableArray array]; //用于存放掃描的外設
}
創(chuàng)建CentralManager會調(diào)用Delegate方法:
#pragma mark - CBCentralManagerDelegate
// 實現(xiàn): 確保支持BL和有效的Central設備
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
switch (central.state) {
case CBManagerStatePoweredOn:
//只有此狀態(tài)下才可以進行掃描設備
[self scan];
break;
case CBManagerStateUnknown:
break;
case CBManagerStateResetting:
break;
case CBManagerStateUnsupported:
break;
case CBManagerStateUnauthorized:
break;
case CBManagerStatePoweredOff:
break;
default:
break;
}
}
掃描外部設備
- (void)scan {
[self.centralManager scanForPeripheralsWithServices: nil options: nil];
NSLog(@"Scanning started");
}
serviceUUIDs: 是一個CBUUID類型的數(shù)組,每個CBUUID代表一個service的UUID。使用這個參數(shù)可以限制掃描內(nèi)容已卸,如果設置為nil,則表示搜索全部外設硼一。
options: 定義掃描 累澡,字典。
- CBCentralManagerScanOptionAllowDuplicatesKey : 布爾值般贼,無重復過濾的掃描愧哟。默認是NO。如果設置為YES哼蛆,對電池有不利影響蕊梧。
- CBCentralManagerScanOptionSolicitedServiceUUIDsKey 想要掃描的Service UUIDs數(shù)組(NSArray)。
另外腮介,在
bluetooth-central
后臺模式下肥矢,option將被忽略。這個問題后面會詳細講解叠洗。
當啟動掃描后甘改,每次掃描到一個外設就會調(diào)用delegate方法:centralManager: didDiscoverPeripheral: advertisementData: RSSI:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(@"%@", peripheral.name);
//查找到設備并持有它,否則不會保存
[self.peripherals addObject: peripheral];
}
- peripheral : 掃描到的設備
- advertisementData: 字典包含所有的廣告數(shù)據(jù)
- RSSI:received signal strength indicator灭抑,單位分貝十艾。表示信號強度。
到這一步我們掃描到外部設備腾节,那接下來就是建立連接了忘嫉。
建立連接
通過掃描,我們發(fā)現(xiàn)了目標外設案腺,接下來建立連接庆冕。
- (void)startUpConnect {
[self.centralManager connectPeripheral: self.peripheral options: nil];
}
self.peripheral : 目標外設
options :字典,用來定制連接行為
- CBConnectPeripheralOptionNotifyOnConnectionKey
- CBConnectPeripheralOptionNotifyOnDisconnectionKey
- CBConnectPeripheralOptionNotifyOnNotificationKey
進行連接通常會出現(xiàn)兩種情況:成功劈榨、失敗愧杯。
連接成功
本地連接成功,會調(diào)用方法:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"鏈接設備名稱為:%@", peripheral.name);
// 設置代理
peripheral.delegate = self;
//發(fā)現(xiàn)服務
[peripheral discoverServices: nil];
}
連接失敗
//鏈接失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"連接名稱:%@ 失敗鞋既,原因:%@", peripheral.name, error.localizedDescription);
}
另外力九,既然可以建立連接,那么肯定可以斷開連接邑闺。
** 斷開連接**
//斷開鏈接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"與外設斷開鏈接:%@跌前, %@", peripheral.name, error.localizedDescription);
}
如果斷開連接不是由
cancelPeripheralConnection:
發(fā)起的,error會給出詳細信息陡舅。需要注意的是抵乓,當斷開連接,所有的services, characteristics和Characteristic descriptions都是無效的。
獲取服務
創(chuàng)建連接成功后灾炭,在delegate方法中
// 設置代理
peripheral.delegate = self;
//發(fā)現(xiàn)服務
[peripheral discoverServices: nil];
可以通過
CBUUID
指定的服務茎芋。
CBPeripheralDelegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
if (error) {
NSLog(@"發(fā)現(xiàn)服務錯誤:%@", error.localizedDescription);
return;
}
// 一個外設會發(fā)送多個服務
for (CBService *service in peripheral.services) {
//掃描每個service的Characteristic,通過Characteristic的UUID來指定查找那個Characteristic蜈出。
[peripheral discoverCharacteristics: nil forService: service];
}
}
注:一個外設包含多個Service田弥,可以通過Service的UUID來區(qū)分。一個Service包含多個Characteristic铡原,通過Characteristic的UUID來區(qū)分偷厦。
獲取特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
if (error) {
NSLog(@"發(fā)現(xiàn)特征錯誤:%@", error.localizedDescription);
return;
}
for (CBCharacteristic *characteristic in service.characteristics) {
//直接讀取Characteristic值,此時調(diào)用peripheral: didUpdateValueForCharacteristic: error:
[peripheral readValueForCharacteristic: characteristic];
//另一種情況燕刻,訂閱特征只泼。此時調(diào)用 peripheral: didUpdateNotificationStateForCharacteristic: error:
[peripheral setNotifyValue:YES forCharacteristic: characteristic];
}
}
訂閱Characteristic
//給指定的特征設置通知
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {
NSLog(@"Error changing notification state : %@", error.localizedDescription);
}
if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:@""]]) {
return;
}
if (characteristic.isNotifying) {
NSLog(@"Notification began on :%@", characteristic);
} else {
NSLog(@"Notification stoped on : %@ Disconnecting", characteristic);
[self.centralManager cancelPeripheralConnection: peripheral];
}
}
獲取特征值
//readValueCharacteristic時調(diào)用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
//打印出characteristic的UUID和值
//!注意,value的類型是NSData卵洗,具體開發(fā)時请唱,會根據(jù)外設協(xié)議制定的方式去解析數(shù)據(jù)
NSLog(@"特性ID::%@ 值:%@",characteristic.UUID, characteristic.value);
}
數(shù)據(jù)交互
- (void)writeValue {
NSData *data = [@"Test" dataUsingEncoding:NSUTF8StringEncoding];
[self.peripheral writeValue: data forCharacteristic: self.characteristic type: CBCharacteristicWriteWithResponse];
}
發(fā)送數(shù)據(jù)
- value: 寫入值
- characteristic : 被寫入的特征
- type: 寫入類型,是否有應答
typedef NS_ENUM(NSInteger, CBCharacteristicWriteType) {
CBCharacteristicWriteWithResponse = 0,
CBCharacteristicWriteWithoutResponse,
};
當type為CBCharacteristicWriteWithResponse時过蹂,調(diào)用delegate方法:
peripheral: didWriteValueForCharacteristic: error:
籍滴。
外設端(發(fā)送端)
創(chuàng)建PeripheralManager
//創(chuàng)建PeripheralManager
- (void)startUpPeripheralManager {
_peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue: nil];
}
//唯一@required方法
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
switch (peripheral.state) {
case CBManagerStatePoweredOn:
// 創(chuàng)建服務和特征
[self buildService];
break;
case CBManagerStateUnknown :
break;
case CBManagerStateResetting:
break;
case CBManagerStateUnsupported:
break;
case CBManagerStateUnauthorized:
break;
case CBManagerStatePoweredOff:
break;
default:
break;
}
}
創(chuàng)建服務和特征
- (void)buildService {
//創(chuàng)建Characteristic
self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify value: nil permissions:CBAttributePermissionsReadable];
//創(chuàng)建服務
CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES];
//將特征添加到服務中
transferService.characteristics = @[self.transferCharacteristic];
//將服務添加到PeripheralManager中,調(diào)用delegate方法: peripheralManager: didAddService: error:
[self.peripheralManager addService: transferService];
}
創(chuàng)建Characteristic
創(chuàng)建Characteristic
- UUID : 唯一標識
- properties:屬性
- value : 設置nil榴啸, 動態(tài)設置孽惰。
- permission : 權(quán)限
屬性
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
//特征值可以使用特征描述廣播
CBCharacteristicPropertyBroadcast = 0x01,
//特征值可以被讀取,通過readValueForCharacteristic: 來讀取
CBCharacteristicPropertyRead = 0x02,
// 可以被讀寫鸥印,通過writeValue: forCharacteristic: type: 寫入特征值勋功,無應答標識寫入成功。
CBCharacteristicPropertyWriteWithoutResponse = 0x04,
// 可以被寫入库说,有應答標識寫入成功
CBCharacteristicPropertyWrite = 0x08,
//允許通知特征值狂鞋,無應答表示接收
CBCharacteristicPropertyNotify = 0x10,
//允許通知特征值,有應答表示接收
CBCharacteristicPropertyIndicate = 0x20,
CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
CBCharacteristicPropertyExtendedProperties = 0x80,
//只有信任的設備接收特征值通知
CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,
CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200
};
屬性特征潜的,可以組合使用骚揍。
權(quán)限
typedef NS_OPTIONS(NSUInteger, CBAttributePermissions) {
// 可讀
CBAttributePermissionsReadable = 0x01,
// 可寫
CBAttributePermissionsWriteable = 0x02,
// 信任可讀
CBAttributePermissionsReadEncryptionRequired = 0x04,
// 信任可寫
CBAttributePermissionsWriteEncryptionRequired = 0x08
} NS_ENUM_AVAILABLE(NA, 6_0);
創(chuàng)建Service
UUID : 唯一標識
isPrimary:YES:主服務;NO:次服務
添加特征到characteristics數(shù)據(jù)
調(diào)用delegate方法: peripheralManager: didAddService: error:
發(fā)送廣告
//開始廣告
- (void)startAdvertise {
[self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]}];
}
//停止廣告
- (void)stopAdvertise {
[self.peripheralManager stopAdvertising];
}
開始廣告
advertisementData: 可選字典啰挪,包含想要廣告的數(shù)據(jù)信不。兩種類型:
- CBAdvertisementDataLocalNameKey :對應名稱
- CBAdvertisementDataServiceUUIDsKey : 對應UUID
調(diào)用delegate方法:peripheralManagerDidStartAdvertising: error:
處理訂閱
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
NSLog(@"當前Characteristic被訂閱");
}
當characteristic配置為notify或indicate,將喚起次方法亡呵。
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
NSLog(@"Central unsubscribed from characteristic");
}
當central移除特征的notification/indications時調(diào)用抽活,取消訂閱回調(diào)。
數(shù)據(jù)交互
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests {
}
當接收到中心端的讀寫請求式锰什,會觸發(fā)這個方法下硕。
在該方法被調(diào)用時丁逝,可以在方法內(nèi)通過PeripheralManager調(diào)用:respondToRequest: withResult:
來響應中心端的讀寫請求。
藍牙的后臺模式
執(zhí)行模式
plist文件中梭姓,設置UIBackgroundModes:
- bluetooth-central
- bluetooth-peripheral
bluetooth-central 執(zhí)行模式
當設置為此模式霜幼,允許APP切入后臺后還能進行藍牙服務。依然能進行掃描誉尖,連接罪既,交互數(shù)據(jù)等。
進入后臺CBCentralManagerScanOptionAllowDuplicatesKey
掃描被忽略释牺。
bluetooth-peripheral 執(zhí)行模式
當設置為此模式萝衩,允許APP進行讀寫回挽,連接中心端等没咙。
CBAdvertisementDataLocalNameKey
被忽略,本地外設名不在廣播千劈。
實現(xiàn)代碼
PeripheralManager
#import "LQPeripheralManager.h"
#import <CoreBluetooth/CoreBluetooth.h>
static NSString *const ServiceUUID1 = @"FFF0";
static NSString *const notifyCharacteristicUUID = @"FFF1";
static NSString *const readwriteCharacteristicUUID = @"FFF2";
static NSString *const ServiceUUID2 = @"FFE0";
static NSString *const readCharacteristicUUID = @"FFE1";
static NSString *const LocalNameKey = @"Owenli";
@interface LQPeripheralManager ()<CBPeripheralManagerDelegate>
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSInteger index;
@end
@implementation LQPeripheralManager
+ (instancetype)shareInstance {
static LQPeripheralManager *peripheral;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
peripheral = [[self alloc] init];
});
return peripheral;
}
- (instancetype)init {
if (self = [super init]) {
_peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
_index = 0;
}
return self;
}
/**
* @Description 初始化化UUID和服務信息
*/
- (void)setup {
//characteristic字段描述
CBUUID *cbuuidCharacteristicUserDescriptionStringUUID = [CBUUID UUIDWithString:CBUUIDCharacteristicUserDescriptionString];
/*
可以通知的Characteristic
properities : CBCharacteristicPropertyNotify
permissions : CBAttributePermissionsReadable
*/
CBMutableCharacteristic *notifyCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:notifyCharacteristicUUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
/*
可讀寫的characteristic
prperitise: CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead
permisssions : CBAttributePermissionsReadable | CBAttributePermisssionWriteable
*/
CBMutableCharacteristic * readwriteCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:readwriteCharacteristicUUID] properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable];
// 設置descriptor
CBMutableDescriptor *readwriteCharacteristicDescription1 = [[CBMutableDescriptor alloc] initWithType:cbuuidCharacteristicUserDescriptionStringUUID value:@"name"];
[readwriteCharacteristic setDescriptors:@[readwriteCharacteristicDescription1]];
/*
只讀Characteristic
properties: CBCharacteristicPropertyRead
permisssions: CBAttributePermissionsReadable
*/
CBMutableCharacteristic *readCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:readCharacteristicUUID] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable];
// 第一個Service
CBMutableService *service1 = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:ServiceUUID1] primary:YES];
[service1 setCharacteristics:@[notifyCharacteristic, readwriteCharacteristic]];
//第二個Service
CBMutableService *service2 = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:ServiceUUID2] primary:YES];
[service2 setCharacteristics:@[readCharacteristic]];
//添加到periperal此時會調(diào)用祭刚,peripheralManager: didAddService: error:
[self.peripheralManager addService:service2];
[self.peripheralManager addService:service1];
}
#pragma mark - PeripherManagerDelegate
//檢測藍牙狀態(tài),
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
switch (peripheral.state) {
case CBManagerStatePoweredOn:
//初始化
[self setup];
break;
case CBManagerStatePoweredOff:
NSLog(@"powered off");
break;
default:
break;
}
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error {
if (error) {
NSLog(@"%@", error.localizedDescription);
return;
}
//添加服務后墙牌,開始廣播
//自動回調(diào): peripheralManagerDidStartAdvertising: error:
[self.peripheralManager startAdvertising:@{
CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:ServiceUUID1], [CBUUID UUIDWithString:ServiceUUID2]],
CBAdvertisementDataLocalNameKey : LocalNameKey
}];
}
//通知發(fā)送廣播
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error {
if (error) {
NSLog(@"%@", error.localizedDescription);
}
NSLog(@"start advert");
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
NSLog(@"subscribe data of : %@", characteristic.UUID);
//分配定時任務
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendData:) userInfo:characteristic repeats:YES];
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
NSLog(@"unsubscrible: %@", characteristic.UUID);
[self.timer invalidate];
}
- (void)sendData:(NSTimer *)timer {
CBMutableCharacteristic *characteristic = timer.userInfo;
if ([self.peripheralManager updateValue:[[NSString stringWithFormat:@"send data : %ld", _index] dataUsingEncoding: NSUTF8StringEncoding] forCharacteristic:characteristic onSubscribedCentrals:nil]) {
NSLog(@"發(fā)送成功");
_index ++;
} else {
NSLog(@"發(fā)送數(shù)據(jù)錯誤");
}
}
//中心設備讀取請求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
NSLog(@"readRequest");
if (request.characteristic.properties & CBCharacteristicPropertyRead) {
NSData *data = [[NSString stringWithFormat:@"by characteristic request"] dataUsingEncoding:NSUTF8StringEncoding];
[request setValue:data];
//對請求作出成功響應
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
} else {
[self.peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted];
}
}
//寫入請求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests {
NSLog(@"writeRequest");
CBATTRequest *request = requests.firstObject;
if (request.characteristic.properties & CBCharacteristicPropertyWrite) {
CBMutableCharacteristic *charateristic = (CBMutableCharacteristic *)request.characteristic;
charateristic.value = request.value;
NSLog(@"receive data :%@", [[NSString alloc] initWithData:charateristic.value encoding:NSUTF8StringEncoding]);
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
} else {
[self.peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted];
}
}
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral {
NSLog(@"peripheralManagerIsReadyToUpdateSubscribers");
}
@end
使用LighBlue測試外設端
備注
命令行生成UUID
方法:uuidgen
涡驮。
Mac測試軟件:LighBlue,可以用來測試iOS端外設喜滨。