iOS 蓝牙4.0 开发体会
来源:互联网 发布:seo常用的工具 编辑:程序博客网 时间:2024/05/29 04:41
- 前言
从刚接触到BLE到开发使用接近一个月了,从项目中学到不少新的东西,了解BLE之前推荐看下
蓝牙官方文档
或者参考
蓝牙官方文档翻译
因为我所要用的是 模式是手机端是中心设备,蓝牙设备是外围设备。所有协议部分中用到了 CBCentralManagerDelegate和CBPeripheralDelegate 。而且是全局 监控蓝牙状态 所以有必要把蓝牙管理类封装出来 ,并制定协议 ,以便把相关蓝牙的协议给抛给自己的代理。
先看BLECentralManager .h部分
extern BOOL IsBlueToothOpen;/** * 设备连接状态 */typedef NS_ENUM(NSInteger, BleManagerState) { /** * 未连接 */ BleManagerStateDisconnect = 0, /** * 已连接 */ BleManagerStateConnect,};@protocol CentralManagerDelegate;@interface CentralManager : NSObject{ CBPeripheral *_devicePeripheral; //设备 CBCharacteristic *_deviceCharacteristic; //设备服务特征 (用来发送指令) CBCentralManager *_manager; // NSMutableArray *_deviceArray;}+ (BOOL)isBlueOpen;/** * 设备管理 单利 */+ (CentralManager *)sharedManager;/** * 验证蓝牙是否可用 */- (BOOL)verifyCentralManagerState;/** * 连接状态 */@property (assign, nonatomic) BleManagerState deviceBleState;@property (assign,nonatomic) CBPeripheral *deviceTied;@property CTCallCenter *callCentter;/** * 添加监听 */- (void)addEventListener:(id <CentralManagerDelegate>)listener;/** * 删除监听 */- (void)removeEventListener:(id <CentralManagerDelegate>)listener;/** * 删除所有监听 */- (void)removeAllEventListener;/** * 取消所有蓝牙连接 */- (void)cancelPeripheralConnection;/** * 取消蓝牙搜索 */- (void)stopManagerScan;//***************************//****设备//***************************/** * 搜索设备 */- (void)searchDeviceModule;/** * 连接设备 * * @param peripheral 设备 */- (void)connectDevicePeripheralWithPeripheral:(CBPeripheral *)peripheral;/** * 开始扫描服务 * * @param peripheral 设备 */- (void)startdiscoverSerVices:(CBPeripheral*)peripheral WithUUID:(NSArray<CBUUID*>*)aryUUID;- (void)startdiscoverSerVices:(CBPeripheral*)peripheral;@end@protocol CentralManagerDelegate <NSObject>@optional/** * 蓝牙未开启 或 不可用 */- (void)centralManagerStatePoweredOff;//***************************//****设备//***************************/** * 发现设备 */- (void)didDiscoverDevicePeripheral:(CBPeripheral *)peripheral devices:(NSMutableArray *)deviceArray; //发现设备/** * 开始连接 */- (void)didStartConnectDevicePeripheral;/** * 断开连接 */- (void)didCancelDevicePeripheralConnection;/** * 发现的特征值 */- (void)didDiscoverDevicePeripheral:(CBPeripheral *)peripheral service:(CBService *)service;/** * 连接成功 */- (void)didConnectDevicePeripheral:(CBPeripheral *)peripheral;/** * 连接失败 */- (void)didFailToConnectDevicePeripheral:(CBPeripheral *)peripheral;/** * 断开连接 */- (void)didDisconnectDevicePeripheral:(CBPeripheral *)peripheral;/** * 连接超时 */- (void)didConnectionDeviceTimeOut;- (void)didDiscoverCharacteristicsForperipheral:(CBPeripheral *)peripheral Service:(CBService *)service error:(NSError *)error;/** * 接收到数据 */- (void)didUpdateDeviceValueForCharacteristic:(CBCharacteristic *)characteristic ; // deviceData:(NSData *)deviceData;/** * 如果一个特征的值被更新,然后周边代理接收 * * @param characteristic */- (void)didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic;
.m 部分
BOOL IsBlueToothOpen = NO;@interface CentralManager ()<CBCentralManagerDelegate, CBPeripheralDelegate,CentralManagerDelegate>{// short ecgNum[500];// unsigned char hr;}@end@implementation CentralManager{ NSMutableArray *_listener; //观察者 //设备数组}#pragma mark - 单例+ (CentralManager *)sharedManager { static CentralManager *sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedManager = [[self alloc] init]; }); return sharedManager;}- (instancetype)init { if (self = [super init]) { [self customInit]; } return self;}- (void)customInit { _listener = [NSMutableArray array]; _deviceArray = [NSMutableArray array]; _deviceBleState = BleManagerStateDisconnect; //建立中心角色 _manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; }//添加监听- (void)addEventListener:(id <CentralManagerDelegate>)listener { [_listener addObject:listener];}//删除监听- (void)removeEventListener:(id <CentralManagerDelegate>)listener { [_listener removeObject:listener];}/** * 删除所有监听 */- (void)removeAllEventListener { [_listener removeAllObjects];}/** * 取消所有蓝牙连接 */- (void)cancelPeripheralConnection { if (self.deviceTied) { [_manager cancelPeripheralConnection:self.deviceTied]; self.deviceTied = nil; } _deviceBleState = BleManagerStateDisconnect; [self stopManagerScan]; for (id listener in _listener) { if ([listener respondsToSelector:@selector(didCancelDevicePeripheralConnection)]) { [listener didCancelDevicePeripheralConnection]; } }}/** * 取消蓝牙搜索 */- (void)stopManagerScan { if (_manager) { [_manager stopScan]; }}+ (BOOL)isBlueOpen{ return IsBlueToothOpen;}- (void)centralManagerDidUpdateState:(CBCentralManager *)central { NSString *stateStr; switch (central.state) { case CBCentralManagerStateUnknown : IsBlueToothOpen = NO; stateStr = @"当前蓝牙状态未知,请重试"; break; case CBCentralManagerStateUnsupported: IsBlueToothOpen = NO; stateStr = @"当前设备不支持蓝牙设备连接"; break; case CBCentralManagerStateUnauthorized: IsBlueToothOpen = NO; stateStr = @"请前往设置开启蓝牙授权并重试"; break; case CBCentralManagerStatePoweredOff: IsBlueToothOpen = NO; stateStr = @"蓝牙关闭,请开启"; break; case CBCentralManagerStateResetting: IsBlueToothOpen = NO; break; case CBCentralManagerStatePoweredOn: { IsBlueToothOpen = YES; stateStr = @"正常"; //扫描外设(discover) DDLog(@"扫描外设");// NSDictionary *options = @{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:YES]}; //开始扫描设备 [self searchDeviceModule];// [_manager scanForPeripheralsWithServices:nil options:nil]; } break; default: stateStr = [NSString stringWithFormat:@"蓝牙异常 %d",(int)central.state]; break; }}/** * 验证蓝牙是否可用 */- (BOOL)verifyCentralManagerState { if (_manager.state != CBCentralManagerStatePoweredOn) { for (id listener in _listener) { if ([listener respondsToSelector:@selector(centralManagerStatePoweredOff)]) { [listener centralManagerStatePoweredOff]; } } return NO; } return YES;}//***************************//****设备//***************************//搜索设备- (void)searchDeviceModule {// if (![self verifyCentralManagerState]) {// return;// } DDLog(@"搜索设备"); [_manager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:NO]}]; //}//连接蓝牙设备- (void)connectDevicePeripheralWithPeripheral:(CBPeripheral *)peripheral { if (![self verifyCentralManagerState]) { return; } if (peripheral == nil) { return; } self.deviceTied = peripheral; [_manager connectPeripheral:peripheral options:@{ CBConnectPeripheralOptionNotifyOnConnectionKey : @YES}];}#pragma mark - *******************/** * 这里开始蓝牙的代理方法 */#pragma mark - >> 发现蓝牙设备- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI { if (!peripheral.name) { return; } NearbyPeripheralInfo *infoModel = [[NearbyPeripheralInfo alloc] init]; infoModel.peripheral = peripheral; infoModel.advertisementData = advertisementData; infoModel.RSSI = RSSI; //设备 DDLog(@"蓝牙管理者 发现设备Device:%@, %.2f", peripheral.name, RSSI.floatValue); if (_deviceArray.count == 0) { [_deviceArray addObject:infoModel]; }else { BOOL isExist = NO; for (int i = 0; i < _deviceArray.count; i++) { NearbyPeripheralInfo *model = _deviceArray[i]; if ([model.peripheral isEqual:peripheral]) { isExist = YES; _deviceArray[i] = infoModel; } } if (!isExist) { [_deviceArray addObject:infoModel]; } } for (id listener in _listener) { if ([listener respondsToSelector:@selector(didDiscoverDevicePeripheral:devices:)]) { [listener didDiscoverDevicePeripheral:peripheral devices:_deviceArray]; } }}#pragma mark - >> 连接成功- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"连接成功:%@", peripheral.name); AppDelegate *myDelegate = [[UIApplication sharedApplication]delegate]; myDelegate.devicesTied = peripheral; [self stopManagerScan]; //停止扫描设备 _deviceBleState = BleManagerStateConnect; self.deviceTied = peripheral; for (id listener in _listener) { if ([listener respondsToSelector:@selector(didConnectDevicePeripheral:)]) { [listener didConnectDevicePeripheral:peripheral]; } } //因为在后面我们要从外设蓝牙那边再获取一些信息,并与之通讯,这些过程会有一些事件可能要处理,所以要给这个外设设置代理 peripheral.delegate = self; //找到该设备上的指定服务 调用完该方法后会调用代理CBPeripheralDelegate(现在开始调用另一个代理的方法了)// [peripheral discoverServices:nil];}- (void)startdiscoverSerVices:(CBPeripheral *)peripheral WithUUID:(NSArray<CBUUID *> *)aryUUID{ [peripheral discoverServices:aryUUID];}- (void)startdiscoverSerVices:(CBPeripheral*)peripheral{// [peripheral discoverServices:nil];}#pragma mark - >> 连接失败- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { _deviceBleState = BleManagerStateDisconnect; for (id listener in _listener) { if ([listener respondsToSelector:@selector(didFailToConnectDevicePeripheral:)]) { [listener didFailToConnectDevicePeripheral:peripheral]; } } NSLog(@"连接失败:%@", peripheral.name);}#pragma mark - >> 断开连接- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"断开连接:%@", peripheral.name); for (id listener in _listener) { if ([listener respondsToSelector:@selector(didDisconnectDevicePeripheral:)]) { [listener didDisconnectDevicePeripheral:peripheral]; } } // 重连// [self connectDevicePeripheralWithPeripheral:peripheral];}#pragma mark - >> CBPeripheralDelegate#pragma mark - >> 发现服务- (void)peripheral:(CBPeripheral *)peripheraldidDiscoverServices:(NSError *)error{ if (error) { DDLog(@" 发现服务时发生错误: %@",error); return; } NSLog(@" 发现服务 .."); for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:nil forService:service]; }}//- (void)didDiscoverCharacteristicsForServiceperipheral:(CBPeripheral *)peripheral :(CBService *)service error:(NSError *)error;#pragma mark - >> 发现特征值- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{ DDLog(@" 蓝牙管理页面 》》》》》 发现服务 %@, 特性数: %ld", service.UUID, [service.characteristics count]);// for (id listener in _listener) {// if ([listener respondsToSelector:@selector(didDiscoverCharacteristicsForperipheral:Service:error:)]) {// [listener didDiscoverCharacteristicsForperipheral:peripheral Service:service error:error];// }// } for (CBCharacteristic *c in service.characteristics) {// [peripheral readValueForCharacteristic:c]; 这句话千万不要写,会出错 //在这里 打开蓝牙外设的某些功能的notify通道 DDLog(@" 蓝牙管理页面特征UUID:%@", [c.UUID UUIDString]); if([[c.UUID UUIDString] isEqualToString:HEART_READ_UUID]) { [peripheral setNotifyValue:YES forCharacteristic:c]; } NSLog(@"特性值: %@",c.UUID); }}#pragma mark - >> 如果一个特征的值被更新,然后周边代理接收- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ DDLog(@"蓝牙管理页面 》》》》》 update Notification"); for (id listener in _listener) { if ([listener respondsToSelector:@selector(didUpdateNotificationStateForCharacteristic:)]) { [listener didUpdateNotificationStateForCharacteristic:characteristic]; } }}#pragma mark - >> 读数据-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ for (id listener in _listener) { if ([listener respondsToSelector:@selector(didUpdateDeviceValueForCharacteristic:)]) { [listener didUpdateDeviceValueForCharacteristic:characteristic]; } }}- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { DDLog(@"did write value For Characteristic"); DDLog(@"value:%@ error:%@", characteristic.value,error);}- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error { DDLog(@"did Write Value For Descriptor");}
2、具体的步骤
1)、先连接外设
[self connectDevicePeripheralWithPeripheral:peripheral];
连接成功后会响应CBCentralManagerDelegate的方法
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;
2)、扫描外设中的服务
[peripheral discoverServices:nil];
或者
[peripheral discoverServices:aryUUID];//扫描指定的服务
之后便会调用CBPeripheralDelegate 的代理
方法 :已经发现服务
- (void)peripheral:(CBPeripheral *)peripheraldidDiscoverServices:(NSError *)error;
在 这里调用
[peripheral discoverCharacteristics:nil forService:service];
发现服务中的特征值
找到特征值之后便会调用CBPeripheralDelegate 的代理的
方法:已经发现特征值
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;
在这里 打开通道
[peripheral setNotifyValue:YES forCharacteristic:c];
这个时候就可以进行对外设的写入操作:
+ (void)writeToperipheral:(CBPeripheral *)peripheral Service:(NSString *)serviceUUID characteristic:(NSString *)characteristicUUID data:(NSData *)data{ CBUUID *servUUID = [CBUUID UUIDWithString:serviceUUID]; CBUUID *charUUID = [CBUUID UUIDWithString:characteristicUUID]; CBService *service = nil; CBCharacteristic *characteristic = nil; for (CBService *ser in peripheral.services) { if ([ser.UUID isEqual:servUUID]) { service = ser; break; } } if (service) { for (CBCharacteristic *charac in service.characteristics) { if ([charac.UUID isEqual:charUUID]) { characteristic = charac; break; } } } if (characteristic) { [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; } else{ NSLog(@"not found that characteristic"); }}
当外设中的数据发生变化 也就是写入值以后会触发CBPeripheralDelegate 的代理的方法:
#pragma mark - >> 如果一个特征的值被更新,然后周边代理接收- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
若有数据从蓝牙中广播的时候
触发
#pragma mark - >> 读数据-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
3、这个是本人的一点心得体会,新手刚接触有关蓝牙4.0的开发,若有哪些言论有误,还请各路大神不吝赐教,谢谢。
By:帅哥
0 0
- iOS 蓝牙4.0 开发体会
- iOS 蓝牙 4.0 开发
- iOS蓝牙4.0开发
- iOS蓝牙4.0开发
- iOS 蓝牙4.0开发
- iOS 蓝牙4.0开发
- iOS开发: iOS蓝牙4.0开发例子
- iOS蓝牙4.0开发例子
- iOS蓝牙4.0开发例子
- iOS蓝牙4.0(BLE)-开发
- iOS蓝牙4.0开发流程
- iOS蓝牙4.0开发例子
- iOS蓝牙4.0开发例子
- iOS蓝牙4.0(BLE)-开发
- ios 蓝牙4.0开发(CoreBlueTooth)
- iOS:蓝牙BLE 4.0 开发
- iOS蓝牙4.0开发流程
- iOS开发 CoreBluetooth 蓝牙4.0
- 【选择图片Jar】结束语以及简单的使用教程(十一)
- 设置session用memcache来存储
- poj1984 Navigation Nightmare(并查集)
- 欢迎使用CSDN-markdown编辑器
- 解决a标签中的href="#"跳转到首页问题
- iOS 蓝牙4.0 开发体会
- 【JQuery】标签页效果
- 用provider获取手机联系人信息
- 使用eclipse的Hibernate插件创建session完成对数据库的记录追加
- EFI基本概念之PPI
- php Session存储到Redis的方法
- FFmpeg在iOS上完美编译
- 回文树(Palindrome Tree)/回文自动机(Palindrome Automaton)学习小记
- 重构——注册——存储过程+事务