iOS CoreBluetooth的使用

import

导入框架,本文仅介绍以下功能:

  • 蓝牙状态回调
  • 扫描设备
  • 连接设备
  • 查找服务
  • 查找特征
  • 订阅特征
  • 写入数据
  • 读取RSSI值
  • 断开重连
  • 后台持续使用蓝牙

即只说明如何使用该框架。

初始化ble对象

遵循代理,顺便带上后面会用到

@property(nonatomic,strong) CBCentralManager *centralManager;
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

蓝牙状态检测

当蓝牙状态发生变化时,会回调该函数

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBManagerStateUnknown: {
            NSLog(@"CBManagerStateUnknown");  //状态未知
            break;
        }
        case CBManagerStateResetting: {
            NSLog(@"CBManagerStateResetting");  //重置
            break;
        }
        case CBManagerStateUnsupported: {
            NSLog(@"CBManagerStateUnsupported");  //不支持
            break;
        }
        case CBManagerStateUnauthorized: {
            NSLog(@"CBManagerStateUnauthorized");  //未授权
            break;
        }
        case CBManagerStatePoweredOff: {
            NSLog(@"CBManagerStatePoweredOff");  //关闭
            break;
        }
        case CBManagerStatePoweredOn: {
            NSLog(@"CBManagerStatePoweredOn");  //开启
            break;
        }
    }
}

扫描设备

serviceUUIDs:只扫描出含有该UUID的设备,即过滤设备
options:扫描模式,一般有两种:
CBCentralManagerScanOptionAllowDuplicatesKey:是否重复扫描已扫描到的设备
CBCentralManagerScanOptionSolicitedServiceUUIDsKey:蓝牙未打开时是否显示弹框

if (self.centralManager.state == CBManagerStatePoweredOn) {
  [self.centralManager scanForPeripheralsWithServices:serviceUUIDs options:options];
}
//options的写法为
NSDictionary *option = @{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO],CBCentralManagerOptionShowPowerAlertKey:YES};

停止扫描

[self.centralManager stopScan];

扫描设备成功后回调函数

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    //peripheral: 设备
    //advertisementData: 广播包
    //RSSI:RSSI信号值
}

连接设备

/*
 options:
 CBConnectPeripheralOptionNotifyOnConnectionKey —— 在连接成功后,程序被挂起,给出系统提示。
 CBConnectPeripheralOptionNotifyOnDisconnectionKey —— 在程序挂起,蓝牙连接断开时,给出系统提示。
 CBConnectPeripheralOptionNotifyOnNotificationKey —— 在程序挂起后,收到 peripheral 数据时,给出系统提示。
*/
[self.centralManager connectPeripheral:peripheral options:options];

断开设备:

[self.centralManager cancelPeripheralConnection:peripheral];

代理回调

//连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    //    NSLog(@"didConnectPeripheral...");
    [self.centralManager stopScan];
}

//连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    //    NSLog(@"didFailToConnectPeripheral");
}

//连接断开
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    //    NSLog(@"didDisconnectPeripheral");
}

查找服务

连接设备后可以查找该设备支持的服务,遵循代理。
serviceUUIDs:扫描指定服务,为nil时说明扫描所有服务

peripheral.delegate = self;
[peripheral discoverServices:serviceUUIDs];

代理回调

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
    //    NSLog(@"didDiscoverServices...");
}

查找特征

characteristicUUIDs:扫描指定特征的UUID
service:传入服务对象

[peripheral discoverCharacteristics:characteristicUUIDs forService:service];

代理回调

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    //    NSLog(@"didDiscoverCharacteristicsForService");
}

订阅特征

enabled:特征有消息时是否进行通知

[peripheral setNotifyValue:enabled forCharacteristic:characteristic];

代理回调

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    //    NSLog(@"didUpdateValueForCharacteristic");
  //NSData *data = characteristic.value;  //回调值
}

写入数据

写入数据到ble设备
data:要写入的数据
characteristic:通过该特征写入
type:哪一种类型的写入,有一下两种,默认填第一个:
CBCharacteristicWriteWithResponse = 0,
CBCharacteristicWriteWithoutResponse,
在选择哪一种类型之前,可以先判断特征Characteristic.properties属性,尝试进去看他的API,会发现

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(10_9, 6_0)   = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(10_9, 6_0) = 0x200
};

当你发现写入不成功时,查看下是否对应上该特征的写入类型。

[peripheral writeValue:data forCharacteristic:characteristic type:type];

代理回调

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    //    NSLog(@"didWriteValueForCharacteristic");
}

读取RSSI值

RSSI值表示蓝牙信号强度,可以通过该值大致判断设备与自身的距离,不过计算不是很准确罢了,RSSI转距离可以参考该链接

[peripheral readRSSI];

代理回调

- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {

}

断开重连

这里说一下,iOS是无法获取ble设备的mac地址的,要实现重连,可以记录扫描到的设备的UUID,然后在重新开始扫描的时候,在扫到设备中判断UUID值即可。

记录设备的UUID:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {    
    [self.centralManager stopScan];
    //在连接成功的时候记录UUID
    NSLog(@"设备UUID: %@",peripheral.identifier.UUIDString);
}
//在扫描设备的时候检测重连
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    if ([peripheral.identifier.UUIDString isEqualToString:@"记录的UUID"]) {
        //连接...
    }
}

后台持续使用蓝牙

iOS是提供后台使用蓝牙的。
默认情况下,iOS程序在后台时还会运行5-10秒,之后就会被系统冻结,不会再运行。如果要让蓝牙在后台依旧能够使用,需要在info.plist中添加UIBackgroundModes这个Key,这个一个数组,然后在这个数组内添加:
bluetooth-central —— 即 Central。
bluetooth-peripheral —— 即 Peripheral。
从上面可以看出,添加的是对应角色,如果你的ble设备两者皆是的话就都添加吧。


屏幕快照 2018-02-01 10.51.10.png

此时当你的程序进入后台后且被系统冻结后,当系统蓝牙检测到已连接过的蓝牙发生变化,如ble设备断电、断开、发送数据给应用等,都会将相应的被冻结住的应用进行激活,激活时间同样是5-10秒,在这点时间内已经可以做到足够多的事了,但是有时候5-10秒依旧不足以应对需求,那么我们可以在这5-10秒内向系统提交一个申请,请求多一段后台使用时间,大概是10-20分钟,这样就更加足够做需求了,关于申请后台运行时间可以参考该链接

上面的代码我进行了block封装
github地址

你可能感兴趣的:(iOS CoreBluetooth的使用)