iOS BLE开发
同Android BLE开发的原理是一样的.手机做中心设备,iOS开发BLE:
蓝牙权限
在info.polist中添加权限Privacy - Bluetooth Peripheral Usage Description
封装单例
@interface XBBleHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic,copy) BTDiscoverCompletion discoverComplection;
@property (nonatomic,copy) BTDevConnectedCompletion devConnectedComplection;
@property (nonatomic,copy) BTDevDisConnectedCompletion devDisconnectedComplection;
//中心管理者
@property (nonatomic,strong) CBCentralManager *centralMgr;
//检测到的所有设备
@property (nonatomic,strong) NSMutableArray *allPeripherals;
//是否系统蓝牙打开
@property (nonatomic,assign) BOOL isLocalBleOpen;
//读数据的特征
@property (nonatomic,strong) CBCharacteristic *readCharacteristic;
//写数据的特征
@property (nonatomic,strong) CBCharacteristic *writeCharacteristic;
@end
@implementation XBBleHelper
//是否连接成功
static bool isConnected = false;
//单例
static XBBleHelper *bleHelper = nil;
+ (instancetype)shareBleHelper{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
bleHelper = [[XBBleHelper alloc]init];
});
return bleHelper;
}
- (instancetype)init
{
self = [super init];
if (self) {
self.isLocalBleOpen = NO;
self.centralMgr =[[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue() options:nil];
self.peripheralArray = [NSMutableArray array];
}
return self;
}
//开始扫描
- (void)startSearch{
if (!self.isLocalBleOpen) {
return;
}
[self stopSearch];
[self.centralMgr scanForPeripheralsWithServices:nil options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil]];
}
//开始扫描
-(void)startSearchBTDevice:(BTDiscoverCompletion)discoverCompletion connectedCompletion:(BTDevConnectedCompletion)devConnected disconnectedCompletion:(BTDevDisConnectedCompletion)devDisconnect
{
if (!self.isLocalBleOpen) {
return;
}
//每次开始扫描之前先停止上一次的扫描,并将回调函数清空
[self stopSearch];
self.discoverComplection = discoverCompletion;
self.devConnectedComplection = devConnected;
self.devDisconnectedComplection = devDisconnect;
[self.centralMgr scanForPeripheralsWithServices:nil options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil]];
}
//停止扫描
- (void)stopSearch{
[self.centralMgr stopScan];
[self.peripheralArray removeAllObjects];
self.discoverComplection = nil;
self.devDisconnectedComplection = nil;
self.devConnectedComplection = nil;
}
//是否连接成功
-(BOOL) isConnected
{
return isConnected;
}
//是否本地蓝牙打开
- (BOOL)isLocalBleOpen{
return _isLocalBleOpen;
}
//连接外设
- (void)connectPeripheralAtIndex:(NSUInteger)aIndex{
if(self.peripheralArray.count < aIndex+1)
return;
CBPeripheral * peripheral = [self.peripheralArray objectAtIndex:aIndex];
self.currentPeripheral = peripheral;
if (peripheral.state == CBPeripheralStateConnected) {
[self.centralMgr cancelPeripheralConnection:peripheral];
}else{
[self.centralMgr connectPeripheral:peripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
[[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_START_BTCONNECT object:nil];//蓝牙开始连接
}
}
//断开蓝牙外设
- (void)disconnectCurrentBTDevice{
if (self.currentPeripheral.state == CBPeripheralStateConnected ) {
[self.centralMgr cancelPeripheralConnection:self.currentPeripheral];
}
}
//设置通知
- (void)setCharacteristic:(CBCharacteristic *)characteristic toNotifyValue:(BOOL)enabled {
[self.currentPeripheral setNotifyValue:enabled forCharacteristic:characteristic];
}
- (void)sendData:(NSData *)data{
[self.currentPeripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
}
#pragma mark --- CBCentralManagerDelegate
//centralMgr状态改变,只有设备打开后才会能扫描设备
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
switch (central.state) {
case CBCentralManagerStateUnknown:
HT_LLog(@">>>>>>>CBCentralManagerStateUnknown");
//break;
case CBCentralManagerStateResetting:
HT_LLog(@">>>>>>>CBCentralManagerStateResetting");
//break;
case CBCentralManagerStateUnsupported:
HT_LLog(@">>>>>>>CBCentralManagerStateUnsupported");
//break;
case CBCentralManagerStateUnauthorized:
HT_LLog(@">>>>>>>CBCentralManagerStateUnauthorized");
//break;
case CBCentralManagerStatePoweredOff:
HT_LLog(@">>>>>>>CBCentralManagerStatePoweredOff");
self.isLocalBleOpen = NO;
break;
case CBCentralManagerStatePoweredOn:
HT_LLog(@">>>>>>>CBCentralManagerStatePoweredOn");
self.isLocalBleOpen = YES;
//在此时开始扫描设备
break;
default:
break;
}
}
//当扫描到外设的时候,会进入到该方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{
if([self.peripheralArray containsObject:peripheral] || ![peripheral.name containsString:@"--"])
{
return;
}
[self.peripheralArray addObject:peripheral];
if (self.discoverComplection){
self.discoverComplection();//扫描到外设
}
}
//外设连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
if (self.devConnectedComplection){
self.devConnectedComplection();
}
self.currentPeripheral = peripheral;
if (self.delegate) {
[self.delegate bleDidConnect];
}
isConnected = true;
peripheral.delegate = self;
[peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
}
//外设连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
self.currentPeripheral = nil;
isConnected = false;
}
//外设断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
self.currentPeripheral = nil;
isConnected = false;
if (self.devDisconnectedComplection) {
self.devDisconnectedComplection();
}
if (self.delegate) {
[self.delegate bleDidDisconnect];
}
}
#pragma mark --- CBPeripheralDelegate
//扫描外设的所有服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
if (error){
HT_LLog(@"error:%@",[error localizedDescription]);
return;
}
for (CBService *service in peripheral.services) {
if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
//
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(nullable NSError *)error{
}
//扫描特定服务的所有特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
if (error)
{
HT_LLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
return;
}
//搜索第一个服务
if([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]){
for (CBCharacteristic *characteristic in service.characteristics) {
HT_LLog(@"service:%@ characteristic:%@",service.UUID,characteristic);
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristerUUID]]) {
if (characteristic.properties & 2) {
self.readCharacteristic = characteristic;
//通知的方式,读取这个特征的value
[self setCharacteristic:characteristic toNotifyValue:YES];
}
if (characteristic.properties & 4) {
self.writeCharacteristic = characteristic;
}
}
}
}
}
//读取特征的值,或者通知的方式读取特征的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
//接收到数据
if(self.delegate){
[self.delegate bleDidReceivedData:characteristic.value];
}
}
//向特征写入值后的反馈
- (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{
}
- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0){
}
- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices NS_AVAILABLE(NA, 7_0){
}
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error NS_DEPRECATED(NA, NA, 5_0, 8_0){
}
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error NS_AVAILABLE(NA, 8_0){
}
@end