iOS关于蓝牙框架BLE的开发--基础用法(上)

2017-03-06  本文已影响794人  左眼见到肠

基础用法先说明一下,自己创建一个叫BluetoothManager的单例,在头文件BluetoothManager.h导入系统蓝牙框架,分别创建几个数组,在使用时调用:
#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothManager : NSObject
@property (nonatomic, strong) NSMutableArray *findPeripherals; //查找到设备(不包含用户列表里的设备)
@property (nonatomic, strong) NSMutableArray *connectPeripherals; //连接上的设备
@property (nonatomic, strong) CBCentralManager *cbCentralManager;

/**
 单例实现方法
 */
+ (BluetoothManager *)share;
@end

在.m文件里面创建单例,并且添加蓝牙模块的协议,并为签订代理:
#import "BluetoothManager.h"

@interface BluetoothManager()<CBCentralManagerDelegate,CBPeripheralDelegate,CBPeripheralManagerDelegate>
@property (nonatomic, strong) NSMutableArray *offlineperipherals;
@property (nonatomic, strong) NSMutableArray *tempLists;
@property (nonatomic, strong) CBPeripheral *peripheral;
@property (nonatomic, strong) CBPeripheralManager *peripheralmanager;
@implementation BlueInfo
@end

@implementation BluetoothManager

//单例生成
+(BluetoothManager *)share {
  static BluetoothManager *shareInstance_ = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      shareInstance_ = [[self alloc] init];
  });
  return shareInstance_;
}
 //初始化中心设备CBCentraManager(管理者)和CBPeripheralManager(外设管理者)
 -(id) init {
  self = [super init];
  if (self) {
    _cbCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    _peripheralmanager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
  }
  return self;
}
-(void) setDelegate:(id<BluetoothManagerDelegate>)delegate
{
  if (!_delegate) {
      _delegate = delegate;
  }
}

下面是中心设备的代理方法,步骤基本要按照下面的走:

1.检查设备蓝牙服务是否打开(可用),关于中心设备的状态central.state有以下6个枚举
- (void) centralManagerDidUpdateState:(CBCentralManager *)central{
  BOOL    state = false;
  NSString *msg = @"";
  switch (central.state) {
    case CBCentralManagerStatePoweredOn:{
        msg = @"Bluetooth is currently powered on";
        state = YES;
    }
    break;
    case CBCentralManagerStatePoweredOff:{
        msg = @"Bluetooth is currently powered off.";
    }
        break;
    case CBCentralManagerStateUnauthorized:{
        msg = @"The application is not authorized to use the Bluetooth Low Energy Central/Client role.";
    }
        break;
    case CBCentralManagerStateUnsupported:{
        msg = @"The platform doesn't support the Bluetooth Low Energy Central/Client role.";
    }
        break;
    case CBCentralManagerStateResetting:{
        msg = @"The connection with the system service was momentarily lost, update imminent.";
    }
        break;
    case CBCentralManagerStateUnknown:{
        msg = @"State unknown, update imminent.";
    }
        break;
  }
}
  NSLog(@"%@",msg);

只有在CBCentralManagerStatePoweredOn的状态下,才可以进行下步操作——其他状态,可以根据自身情况做相应的提示高告诉用户;

2.搜索中心设备周边的外设:

在上面代理方法的CBCentralManagerStatePoweredOncase下写搜索方法,可以直接把系统方法写到该case,此处把系统的搜索方法封装到一个自定义方法,代码更整洁(创建布尔值state,用于标记设备蓝牙成功与否)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
BOOL state = false;
NSString *msg = @"";
switch (central.state) {
case CBCentralManagerStatePoweredOn:{
msg = @"Bluetooth is currently powered on";
[self scanDevice];//搜索设备方法
state = YES;
}
break;
// ...... 下面的状态省略......
}
}

下面是搜索设备封装方法:

-(void) scanBlueServes {
  NSDictionary *optionsDict = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
  [self.cbCentralManager scanForPeripheralsWithServices:nil options:optionsDict];
//CBUUID *uuid = [CBUUID UUIDWithString:@"FFF0"];
//[self.cbCentralManager scanForPeripheralsWithServices:@[uuid] options:optionsDict];

}

方法中,需要注意的是:

  • A Boolean value that specifies whether the scan should run without duplicate filtering.
    The value for this key is an NSNumber object. If true, filtering is disabled and a discovery event is generated each time the central receives an advertising packet from the peripheral. Disabling this filtering can have an adverse effect on battery life and should be used only if necessary. If false, multiple discoveries of the same peripheral are coalesced into a single discovery event. If the key is not specified, the default value is false.
3.检测到外设后,进入下面的代理方法,连接设备(这里开始加入了一些个人的方法)
if (peripheral.state == CBPeripheralStateConnected) {
  return;
}
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    if (peripheral.state == CBPeripheralStateConnected) {
        return;
    }
  NSData *data = [advertisementData objectForKey:@"kCBAdvDataManufacturerData"];
  if ((peripheral.name && ([peripheral.name hasPrefix:@"BBCare"]) ||  [self checkMacAddress]){
    [self.findPeripherals addObject:peripheral];
}
4.通过界面方法,实现蓝牙类方法;

一般情况下,我们(其实是我)会在tableView通过BluetoothManager单例获取到findPeripherals数组,展示到界面,然后在tableview的协议方法:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
里面获取要连接的设备peripheral,传入如下方法实现连接设备:
[[BluetoothManager share].cbCentralManager connectPeripheral:peripheral options:nil];

5.连接后的处理(划重点了!)
  -(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@">>>连接到名称为(%@)的设备-失败,原因:%@",[peripheral name],[error localizedDescription]);
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
  NSLog(@">>>连接到设备(%@ >> %@)-- 成功",peripheral.name,peripheral.identifier.UUIDString);
  if (self.connectperipherals == nil) {
      self.connectperipherals = [NSMutableArray array];
  }
  if (![self.connectperipherals containsObject:peripheral]) {
      [self.connectperipherals addObject:peripheral];
  }
  [peripheral setDelegate:self];
  [peripheral discoverServices:nil];
}
//完整代码
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
  NSLog(@">>>扫描到服务:%@",peripheral.services);
  if (error){
      NSLog(@">>>发现服务 %@ 错误: %@", peripheral.name, [error localizedDescription]);
      return;
  }
  for (CBService *service in peripheral.services) {
      NSLog(@">>>扫描到服务 = %@",service.UUID);
      [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFF1"]] forService:service];
  }
}
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
CBCharacteristicPropertyBroadcast                                               = 0x01,
CBCharacteristicPropertyRead                                                    = 0x02,
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
};

在我的项目中用到的分别是:

CBCharacteristicPropertyWrite,                 //可写入
CBCharacteristicPropertyWriteWithoutResponse,  //可写入并带回执
CBCharacteristicPropertyRead,                  //可读
CBCharacteristicPropertyNotify,                //可订阅1
CBCharacteristicPropertyIndicate               //可订阅2

会一点英文的同学看看类型后面大概能猜到,第一二个是写入,一个带回执,一个不带;第三个是可读;第四第五个是骚骚不同的两种订阅,具体根据不同的情况使用,其他的好像我也没用到过...不过看后缀的话好像能发现些什么吧?

setNotifyValue forCharacteristic        //订阅方法`;
writeValue: forCharacteristic: type:    //写入方法,其中type类型有无回执
peripheral readValueForCharacteristic:  //读取方法

整段的代码如下:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
  if (error) {
      NSLog(@"%s,%@",__PRETTY_FUNCTION__,error);
  }
  else{
      for (CBCharacteristic *characteristic in service.characteristics{
        NSLog(@"特征码 == %@",characteristic.UUID);
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]]){
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF3"]]){
            [peripheral writeValue:[NSData data] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
        }
     }
  }
}

不知不觉写了这么多,还是分开上下部说吧...
iOS关于蓝牙框架BLE的开发--基础用法(下)

上一篇下一篇

猜你喜欢

热点阅读