ios 蓝牙4.0开发(CoreBlueTooth)
2016-04-29 18:18
786 查看
一、蓝牙开发引入
情景 : 蓝牙(Center)监听心跳仪(Peripheral)发送数据,发送到服务器。
心跳仪->外设(被连接的设备),蓝牙->中心(发起连接)
类似,客户端和服务器之间的关系(ios设备和非ios设备之间的交互)。
二、关于蓝牙的一些术语
1、Center : 中心 (发起连接的是中心)
2、Peripheral:外设(被链接的设备称之为外设)
3、service and characteristic (服务和特征)
每个设备都会提供服务和特征。每个外设都会提供很多服务,每个服务都会包含很多字段,这些字段都是有权限的,权限大致为:read/write/notify,就是我们链接设备后具体需要操作的内容.
4、Description : 每个characteristic可以对应一个或多个Description,用于描述特征(characteristic)的信息或属性。
5、BLE: blue low energy 蓝牙4.0低耗电
6、4.0 BLE : 开发使用CoreBluetooth 框架 (ios6.0以上)
7、MFL认证: make for ipad /iphone/ itouch (专门为苹果设备制作的设备)
三、蓝牙的中心模式、外设模式、工作状态
1、中心模式流程
主设备(手机去扫描连接外设,发现外设服务和属性,操作服务和属性的应用。一般来说,外设(蓝牙设备,比如智能手环之类的东西), 会由硬件工程师开发好,并定义好设备提供的服务,每个服务对于的特征,每个特征的属性(只读,只写,通知等等),本文例子的业务场景,就是用一手机app去读写蓝牙设备。
( 1 ) 建立中心角色
( 2 ) 扫描外设(scan)
( 3 ) 链接外设 (connect)
( 4 ) 获取外设中的服务和特征
获取外设的server
获取外设的characteristic,获取characteristic的Description值
( 5 ) 与外设做数据交互
( 6 ) 订阅 characteristic 通知
( 7 ) 断开链接(disconnect)
2、外设模式流程
( 1 ) 启动 Peripheral 管理对象
( 2 ) 设置 Peripheral的 服务、特征、描述、权限
( 3 ) 设置处理订阅、取消订阅、读写characteristic(特征)委托方法
3、工作状态
( 1 ) 准备
( 2 ) 广播
( 3 ) 监听扫描
( 4 ) 发起连接
( 5 ) 已经连接
四、Center模式代码解析
1、准备工作
导入
2、建立中心角色,并监听蓝牙设备状态,扫描外设
查看作为center 的蓝牙的状态,并当蓝牙打开的时候,扫描外设
以下方法,分别是扫描外设,并连接外设成功、失败、外设断开连接的代理方法
3、当连接成功,扫描外设的服务和特征(也就是遵循外设的几个代理方法)
5、与外设进行交互(UE)
6、订阅Characteristic通知(订阅和取消)
7、与外设断开连接
提醒 : 关于 4.0BLE,github有人专门进行了二次封装,可通过cocoapods进行下载
情景 : 蓝牙(Center)监听心跳仪(Peripheral)发送数据,发送到服务器。
心跳仪->外设(被连接的设备),蓝牙->中心(发起连接)
类似,客户端和服务器之间的关系(ios设备和非ios设备之间的交互)。
二、关于蓝牙的一些术语
1、Center : 中心 (发起连接的是中心)
2、Peripheral:外设(被链接的设备称之为外设)
3、service and characteristic (服务和特征)
每个设备都会提供服务和特征。每个外设都会提供很多服务,每个服务都会包含很多字段,这些字段都是有权限的,权限大致为:read/write/notify,就是我们链接设备后具体需要操作的内容.
4、Description : 每个characteristic可以对应一个或多个Description,用于描述特征(characteristic)的信息或属性。
5、BLE: blue low energy 蓝牙4.0低耗电
6、4.0 BLE : 开发使用CoreBluetooth 框架 (ios6.0以上)
7、MFL认证: make for ipad /iphone/ itouch (专门为苹果设备制作的设备)
三、蓝牙的中心模式、外设模式、工作状态
1、中心模式流程
主设备(手机去扫描连接外设,发现外设服务和属性,操作服务和属性的应用。一般来说,外设(蓝牙设备,比如智能手环之类的东西), 会由硬件工程师开发好,并定义好设备提供的服务,每个服务对于的特征,每个特征的属性(只读,只写,通知等等),本文例子的业务场景,就是用一手机app去读写蓝牙设备。
( 1 ) 建立中心角色
( 2 ) 扫描外设(scan)
( 3 ) 链接外设 (connect)
( 4 ) 获取外设中的服务和特征
获取外设的server
获取外设的characteristic,获取characteristic的Description值
( 5 ) 与外设做数据交互
( 6 ) 订阅 characteristic 通知
( 7 ) 断开链接(disconnect)
2、外设模式流程
( 1 ) 启动 Peripheral 管理对象
( 2 ) 设置 Peripheral的 服务、特征、描述、权限
( 3 ) 设置处理订阅、取消订阅、读写characteristic(特征)委托方法
3、工作状态
( 1 ) 准备
( 2 ) 广播
( 3 ) 监听扫描
( 4 ) 发起连接
( 5 ) 已经连接
四、Center模式代码解析
1、准备工作
导入
#import <CoreBluetooth/CoreBluetooth.h>,声明系统蓝牙设备管理者和保存外设动态数组,遵循代理
<CBCentralManagerDelegate,CBPeripheralDelegate>,当连接外设成功后,不仅要保留外设,而且之后要与外设交互,就必须也遵循外设的一些代理方法,并设置外设对象的代理对象。
//系统狼牙设备管理者 CBCentralManager *manager; // 用于保存被发现的设备(外设) NSMutableArray *peripherals;
2、建立中心角色,并监听蓝牙设备状态,扫描外设
/* * 1和2和3、建立角色中心,并确定蓝牙打开状态下,扫描外设 * 注意一个细节: 请特别注意,扫描到目标外设一定要保存! * 如果不保存,会影响到后面的方法执行, * 导致无法连接和对外设后续的操作。 * */
- (void)viewDidLoad { [super viewDidLoad]; self.title = @"4.0 BLE "; //初始化,并设置委托和线程队列 manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()]; }//视图加载
查看作为center 的蓝牙的状态,并当蓝牙打开的时候,扫描外设
- (void)centralManagerDidUpdateState:(CBCentralManager *)central { switch (central.state) { case CBCentralManagerStateUnknown: break; case CBCentralManagerStateResetting: break; case CBCentralManagerStateUnsupported: break; case CBCentralManagerStateUnauthorized: break; case CBCentralManagerStatePoweredOff: NSLog(@"蓝牙关闭"); break; case CBCentralManagerStatePoweredOn: NSLog(@"蓝牙打开"); //扫描外设备(第一个参数为nil就是扫描所有的设备) [manager scanForPeripheralsWithServices:nil options:nil]; break; default: break; } }//蓝牙状态
以下方法,分别是扫描外设,并连接外设成功、失败、外设断开连接的代理方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"发现附近蓝牙:%@---%@",peripheral.name,peripheral.identifier); if ([peripheral.name hasPrefix:@"C"]) { /* 找到设备,并持有他,否则CBCentralManager不会保存peripheral, 那么CBPeripheralDelegate中的代理方法也不会被调用 */ [peripherals addObject:peripheral]; /* 一个主设别最多链接7个外设,每个外设最多只能给一个主设链接 链接成功、失败、断开就会进入各自的委托 */ //链接设备 [manager connectPeripheral:peripheral options:nil]; } }//扫描到设备并过滤外设,进而建立连接
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"链接外设%@成功",peripheral.name); // 设置外设代理 [peripheral setDelegate:self]; // 扫描外设的 services [peripheral discoverServices:nil]; }// 与外设链接成功
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@">>>连接到名称为(%@)的设备-失败,原因:%@",[peripheral name],[error localizedDescription]); }//链接失败
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@">>>外设连接断开连接 %@: %@\n", [peripheral name], [error localizedDescription]); }// 外设断开连接
3、当连接成功,扫描外设的服务和特征(也就是遵循外设的几个代理方法)
/* 设备连接成功后,就可以扫描设备的服务了,同样是通过委托形式,扫描到结果后会进入委托方法。但是这个委托已经不再是主设备的委托(CBCentralManagerDelegate),而是外设的委托(CBPeripheralDelegate),这个委托包含了主设备与外设交互的许多 回叫方法,包括获取services,获取characteristics,获取characteristics的值,获取characteristics的Descriptor,和Descriptor的值,写数据,读rssi,用通知的方式订阅数据等等 */
pragma mark - Peripheral 代理方法
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { NSLog(@">>>扫描到服务:%@",peripheral.services); if (error) { NSLog(@"%@",[error localizedDescription]); return; } for (CBService *service in peripheral.services) { /* * 扫描每个服务的 service 进而获取 characteristics 调用下面的代理方法 * * -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error */ [peripheral discoverCharacteristics:nil forService:service]; } }//扫描到服务 -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { NSLog(@"%@",[error localizedDescription]); } /* * 读取Characteristic 的值 * 进入下面代理方法 * - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error * */ for (CBCharacteristic *Characteristic in service.characteristics) { //NSLog(@"%@----%@",service.UUID,Characteristic.UUID); [peripheral readValueForCharacteristic:Characteristic]; } /* * 读取 Characteristic 的 Descriptors * */ for (CBCharacteristic *Characteristic in service.characteristics) { [peripheral discoverDescriptorsForCharacteristic:Characteristic]; } }//每个服务的特征值 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { // characteristic 的value值是NSData NSLog(@"%@",characteristic.value); }//获取的charateristic的值 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error { for (CBDescriptor *des in characteristic.descriptors) { NSLog(@"%@",des.UUID); } }//搜索到Characteristic的Descriptors -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error { //这个descriptor都是对于characteristic的描述,一般都是字符串,所以这里我们转换成字符串去解析 NSLog(@"characteristic uuid:%@ value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value); }//获取 Descriptors的值
5、与外设进行交互(UE)
-(void)writeCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic value:(NSData *)value { //打印出 characteristic 的权限,可以看到有很多种,这是一个NS_OPTIONS,就是可以同时用于好几个值,常见的有read,write,notify,indicate,知知道这几个基本就够用了,前连个是读写权限,后两个都是通知,两种不同的通知方式。 /* 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 }; */ NSLog(@"%lu", (unsigned long)characteristic.properties); //只有 characteristic.properties 有write的权限才可以写 if(characteristic.properties & CBCharacteristicPropertyWrite){ /* 最好一个type参数可以为CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,区别是是否会有反馈 */ [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; }else{ NSLog(@"该字段不可写!"); } }//写数据
6、订阅Characteristic通知(订阅和取消)
-(void)notifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic { //设置通知,数据通知会进入:didUpdateValueForCharacteristic方法 [peripheral setNotifyValue:YES forCharacteristic:characteristic]; }//设置通知 -(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic { [peripheral setNotifyValue:NO forCharacteristic:characteristic]; }//取消通知
7、与外设断开连接
-(void)disconnectPeripheral:(CBCentralManager *)centralManager peripheral:(CBPeripheral *)peripheral { //停止扫描 [centralManager stopScan]; //断开连接 [centralManager cancelPeripheralConnection:peripheral]; }// 停止扫描和断开连接
提醒 : 关于 4.0BLE,github有人专门进行了二次封装,可通过cocoapods进行下载
pod 'BabyBluetooth','~> 0.6.0' 开发导入 #import "BabyBluetooth.h"
相关文章推荐
- 知问前端——工具提示UI
- 远程服务器返回了意外相应:(413) Request Entity Too Large。
- POJ 1679:The Unique MST 次小生成树
- iOS9用UICollectionViewController实现启动引导图
- CCS3 @media实现响应式布局
- UISegmentedControl使用方法
- DVFS User Guide
- 探秘Java中String、StringBuilder以及StringBuffer
- NGUI与UGUI制作Loading条
- 评价网站UI--北京邮电大学首页
- 分布式Unique ID的生成方法一览
- Android 属性文件build.prop,获取属性以及设置属性
- CoreThink主题开发(一)使用H-ui开发博客主题之搭建目录结构
- iOS当UITableViewCell被选中或者高亮的时候,它的所有子view的颜色都会改变
- leetcode——300—— Longest Increasing Subsequence
- poj2524 Ubiquitous Religions
- java1.7集合源码阅读:ArrayBlockingQueue
- StringBuilder在高性能场景下的正确用法
- UVA-348 Optimal Array Multiplication Sequence
- 如何给Core Data添加UNIQUENESS约束