苹果在iOS 6系统之后开始支持BLE 4.0,iPhone4s,iPod 5,iPad 3等之后的机型开始内嵌BLE4.0硬件,因此在开发前请先确认你的开发环境符合上述要求,并且苹果在BLE4.0之后,对外部的连接设备已经不再需要MFI认证了,当然你的外设肯定得要有蓝牙4.0模块。
开发BLE4.0的App,你需要在你的项目里面导入框架:
在需要使用到蓝牙的文件里面导入头文件,并且在你的蓝牙类里面实现两个协议,CBCentralManagerDelegate ,CBPeripheralDelegate
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
现在我们需要有两个实例对象CBCentralManager和CBPeripheral,第一个是蓝牙中心管理器,主要用来搜索外设,连接外设以及处理外设断开的情况;第二个主要用于在蓝牙中心管理器成功连接外设之后的一系列动作,如:读取外设的服务号CBService,特征值号CBCharacteristic以及对这些特征值号进行读写操作等,下面我们来看一下中心管理器和外设连接的一个大概流程:
1):蓝牙中心管理器开始扫描广播包(扫描的时长可以自己写一个定时器控制,并且可以设定扫描的具体条件)
2):外设开始广播(当然外设的广播时长也是可以设定的)
3):中心管理器发现有广播包,就请求连接外设
4):连接成功之后就可以读取外设的相关信息了,比如服务号CBService,特征值号CBCharacteristic,还有外设的一些硬件信息,电池电量,信号强度RSSI什么的
5):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和程序里对于连接断开的处理代码了
示例代码
1.创建BluetoothEquipment类,然后在BluetoothEquipment.h里
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#define PERIPHERAL_NAME @"KL940704079"
@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager *centralManager;
@property(nonatomic,strong)CBPeripheral *myPeripheral;
///上锁和解锁的characteristic
@property(nonatomic,strong)CBCharacteristic *lockUnlockCharacteristic;
///电量的characteristic
@property(nonatomic,strong)CBCharacteristic *readPowerCharacteristic;
///初始化中心设备管理器
-(void)initCentralManager;
///传入上锁指令
-(void)setLockInstruction:(NSString*)lockInstruction;
///传入解锁指令
-(void)setUnlockInstruction:(NSString *)unlockInstruction;
@end
2.在BluetoothEquipment.m里
#import "BluetoothEquipment.h"
@implementation BluetoothEquipment
//传入上锁指令
- (void)setLockInstruction:(NSString *)lockInstruction{
if (_lockUnlockCharacteristic) {
NSData* lockValue = [self dataWithString:lockInstruction];
NSLog(@"上锁的指令lockValue= %@",lockValue);
[_myPeripheral writeValue:lockValue forCharacteristic:_lockUnlockCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
//传入解锁指令
-(void)setUnlockInstruction:(NSString *)unlockInstruction{
if (_lockUnlockCharacteristic) {
NSData* unlockValue = [self dataWithString:unlockInstruction];
NSLog(@"解锁的指令unlockValue= %@",unlockValue);
[_myPeripheral writeValue:unlockValue forCharacteristic:_lockUnlockCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
//初始化中心设备管理器
- (void)initCentralManager{
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
//创建完成CBCentralManager对象之后会回调的代理方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
if (central.state == CBCentralManagerStatePoweredOff) {
NSLog(@"系统蓝牙关闭了,请先打开蓝牙");
}
if (central.state == CBCentralManagerStateUnauthorized) {
NSLog(@"系统蓝未被授权");
}
if (central.state == CBCentralManagerStateUnknown) {
NSLog(@"系统蓝牙当前状态不明确");
}
if (central.state == CBCentralManagerStateUnsupported) {
NSLog(@"系统蓝牙设备不支持");
}
if (central.state == CBCentralManagerStatePoweredOn) {
//扫描外设:如果你将第一个参数设置为nil,Central Manager就会开始寻找所有的服务。
[_centralManager scanForPeripheralsWithServices:nil options:nil];
}
}
//执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
//根据名字有选择性地连接蓝牙设备
if([peripheral.name isEqualToString:PERIPHERAL_NAME]){
_myPeripheral = peripheral;
_myPeripheral.delegate = self;
//连接外设
[_centralManager connectPeripheral:_myPeripheral options:nil];
}
}
//如果连接成功,就会回调下面的协议方法了
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
//停止中心管理设备的扫描动作,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为iOS BLE4.0是支持一对多连接的),导致数据的混乱。
[_centralManager stopScan];
//一次性读出外设的所有服务
[_myPeripheral discoverServices:nil];
}
//掉线
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"掉线");
}
//连接外设失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"连接外设失败");
}
//一旦我们读取到外设的相关服务UUID就会回调下面的方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
//到这里,说明你上面调用的 [_peripheral discoverServices:nil]; 方法起效果了,我们接着来找找特征值UUID
NSLog(@"发现服务");
for (CBService *s in [peripheral services]) {
[peripheral discoverCharacteristics:nil forService:s];
}
}
//如果我们成功读取某个特征值UUID,就会回调下面的方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
for(int i=0; i < service.characteristics.count; i++) {
CBCharacteristic *c = [service.characteristics objectAtIndex:i];
NSLog(@"特征 UUID: %@ (%@)", c.UUID.data, c.UUID);
if ([[c UUID] isEqual:[CBUUID UUIDWithString:@"0000fff6-0000-1000-8000-00805f9b34fb"]]){
_lockUnlockCharacteristic = c;
NSLog(@"找到可写特征lockUnlockCharacteristic : %@", c);
}
//读取蓝牙4.0设备电量的特征值
if ([[c UUID] isEqual:[CBUUID UUIDWithString:@"0000fff4-0000-1000-8000-00805f9b34fb"]]){
self.readPowerCharacteristic = c;
NSLog(@"找到可读特征readPowerCharacteristic : %@", c);
[self.myPeripheral setNotifyValue:YES forCharacteristic:_readPowerCharacteristic];
}
}
}
//向peripheral中写入数据后的回调函数
- (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(@"write value success(写入成功) : %@", characteristic);
}
//获取外设发来的数据,不论是read和notify,获取数据都从这个方法中读取
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
[peripheral readRSSI];
NSNumber* rssi = [peripheral RSSI];
//读取BLE4.0设备的电量
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"0000fff4-0000-1000-8000-00805f9b34fb"]]){
NSData* data = characteristic.value;
NSString* value = [self hexadecimalString:data];
NSLog(@"characteristic(读取到的) : %@, data : %@, value : %@", characteristic, data, value);
}
}
//将传入的NSData类型转换成NSString并返回
- (NSString*)hexadecimalString:(NSData *)data{
NSString* result;
const unsigned char* dataBuffer = (const unsigned char*)[data bytes];
if(!dataBuffer){
return nil;
}
NSUInteger dataLength = [data length];
NSMutableString* hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for(int i = 0; i < dataLength; i++){
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
}
result = [NSString stringWithString:hexString];
return result;
}
//将传入的NSString类型转换成ASCII码并返回
- (NSData*)dataWithString:(NSString *)string{
unsigned char *bytes = (unsigned char *)[string UTF8String];
NSInteger len = string.length;
return [NSData dataWithBytes:bytes length:len];
}
@end