iOS开发—蓝牙4.0(BLE)与外设连接及收发数据的流程
2017-04-08 06:13
585 查看
苹果在iOS 6系统之后开始支持BLE 4.0,iPhone4s,iPod 5,iPad 3等之后的机型开始内嵌BLE4.0硬件,因此在开发前请先确认你的开发环境符合上述要求,并且苹果在BLE4.0之后,对外部的连接设备已经不再需要MFI认证了,当然你的外设肯定得要有蓝牙4.0模块。
开发BLE4.0的App,你需要在你的项目里面导入框架:
在需要使用到蓝牙的文件里面导入头文件,并且在你的蓝牙类里面实现两个协议,CBCentralManagerDelegate ,CBPeripheralDelegate
现在我们需要有两个实例对象CBCentralManager和CBPeripheral,第一个是蓝牙中心管理器,主要用来搜索外设,连接外设以及处理外设断开的情况;第二个主要用于在蓝牙中心管理器成功连接外设之后的一系列动作,如:读取外设的服务号CBService,特征值号CBCharacteristic以及对这些特征值号进行读写操作等,下面我们来看一下中心管理器和外设连接的一个大概流程:
1):蓝牙中心管理器开始扫描广播包(扫描的时长可以自己写一个定时器控制,并且可以设定扫描的具体条件)
2):外设开始广播(当然外设的广播时长也是可以设定的)
3):中心管理器发现有广播包,就请求连接外设
4):连接成功之后就可以读取外设的相关信息了,比如服务号CBService,特征值号CBCharacteristic,还有外设的一些硬件信息,电池电量,信号强度RSSI什么的
5):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和程序里对于连接断开的处理代码了
编程代码:
创建BluetoothEquipment类,然后在BluetoothEquipment.h里
#define PERIPHERAL_NAME @"KL940704079"
#import <Foundation/Foundation.h>#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager* centralManager;@property(nonatomic,strong)CBPeripheral* myPeripheral;
@property(nonatomic,strong)CBCharacteristic* lockUnlockCharacteristic;//上锁和解锁的characteristic@property(nonatomic,strong)CBCharacteristic* readPowerCharacteristic;//电量的characteristic
-(void)initCentralManager;//初始化中心设备管理器-(void)setLockInstruction:(NSString*)lockInstruction;//传入上锁指令-(void)setUnlockInstruction:(NSString *)unlockInstruction;//传入解锁指令
@end
在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) { //扫描外设 [_centralManager scanForPeripheralsWithServices:nil options:nil];//如果你将第一个参数设置为nil,Central Manager就会开始寻找所有的服务。 }}
//执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了- (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
开发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):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和程序里对于连接断开的处理代码了
编程代码:
创建BluetoothEquipment类,然后在BluetoothEquipment.h里
#define PERIPHERAL_NAME @"KL940704079"
#import <Foundation/Foundation.h>#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager* centralManager;@property(nonatomic,strong)CBPeripheral* myPeripheral;
@property(nonatomic,strong)CBCharacteristic* lockUnlockCharacteristic;//上锁和解锁的characteristic@property(nonatomic,strong)CBCharacteristic* readPowerCharacteristic;//电量的characteristic
-(void)initCentralManager;//初始化中心设备管理器-(void)setLockInstruction:(NSString*)lockInstruction;//传入上锁指令-(void)setUnlockInstruction:(NSString *)unlockInstruction;//传入解锁指令
@end
在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) { //扫描外设 [_centralManager scanForPeripheralsWithServices:nil options:nil];//如果你将第一个参数设置为nil,Central Manager就会开始寻找所有的服务。 }}
//执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了- (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
相关文章推荐
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- iOS开发之仿微博视频边下边播之自定义AVPlayer播放器, 边下边播解剖。视频处理流程,建立连接-请求数据-统筹数据-解码数据-视频呈现
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- 开发低功耗蓝牙4.0血压计连接与收发数据
- 【投稿】iOS 蓝牙开发(二)iOS 连接外设的代码实现
- iOS开发中如何实现app作为外设被连接的功能?
- ios蓝牙开发(二)ios连接外设的代码实现
- iOS蓝牙4.0(BLE)-开发
- iOS蓝牙开发(三):App作为外设被连接的实现
- iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发
- iOS开发之音频口通信-通过方波来收发数据
- ios蓝牙开发(三)app作为外设被连接的实现
- Android 蓝牙4.0BLE开发实现对蓝牙的写入数据和读取数据
- iOS 蓝牙开发(二)iOS 连接外设的代码实现
- iOS 蓝牙开发(二)iOS 连接外设的代码实现
- iOS 蓝牙4.0(BLE)后台或者锁屏也可以接收数据的方法
- iOS 蓝牙4.0收发数据 报Error Domain=CBErrorDomain Code=0 这个错
- iOS 蓝牙开发(三)app作为外设被连接的实现
- iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发