CoreBluetooth - 中心模式
BLE中心模式流程-coding
BLE中心模式流程
- 1.建立中心角色
- 2.扫描外设(Discover Peripheral)
- 3.连接外设(Connect Peripheral)
- 4.扫描外设中的服务和特征(Discover Services And Characteristics)
* 4.1 获取外设的services
* 4.2 获取外设的Characteristics,获取characteristics的值,,获取Characteristics的Descriptor和Descriptor的值
- 5.利用特征与外设做数据交互(Explore And Interact)
- 6.订阅Characteristic的通知
- 7.断开连接(Disconnect)
## 准备环境
- 1.Xcode7.0
- 2.手机
- 3.外设(手机+LightBlue)
#import "CentralViewController.h"
// BLE 框架
#import <CoreBluetooth/CoreBluetooth.h> @interface CentralViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate> /** 中心管理者 */
PROPERTYSTRONG(CBCentralManager, cMgr)
/** 连接到的外设 */
PROPERTYSTRONG(CBPeripheral, cPeriphery) @end @implementation CentralViewController
/**
* 懒加载
*
* @ 需要调用完成对象初始化
*/
- (CBCentralManager *)cMgr
{
if (!_cMgr) {
_cMgr = [[CBCentralManager alloc] initWithDelegate:self
queue:dispatch_get_main_queue()
options:nil];
}
return _cMgr;
} - (void)viewDidLoad {
[super viewDidLoad]; self.title = @"CentralViewController"; // 在ios5之前, 再通过以下方法设置背景时, 有闪屏bug
// self.view.backgroundColor = [UIColor colorWithPatternImage:<#(nonnull UIImage *)#>];
// // 解决方案
// self.view.layer.contents = (id)[UIColor colorWithPatternImage:[UIImage imageNamed:xxx]];
// 0. 创建管理者对象
#pragma mark -
#pragma mark - - 1.建立中心角色
[self cMgr]; } // 通常在此需要 断开连接外设
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated]; // 此处断开连接外设
[self yf_dismissConnectedWithPeripheral:self.cPeriphery];
} #pragma mark - CBCentralManagerDelegate
/**
* @1 只要中心管理者初始化, 就会触发此方法
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) { // 开启
case CBCentralManagerStateUnknown: { // 未知
LogRed(@"CBCentralManagerState--- Unknown");
break;
}
case CBCentralManagerStateResetting: { // 重置
LogRed(@"CBCentralManagerState--- Resetting");
break;
}
case CBCentralManagerStateUnsupported: { // 不支持
LogRed(@"CBCentralManagerState--- Unsupported");
break;
}
case CBCentralManagerStateUnauthorized: { // 未授权
LogRed(@"CBCentralManagerState--- Unauthorized");
break;
}
case CBCentralManagerStatePoweredOff: { // 关闭
LogRed(@"CBCentralManagerState---- PoweredOff");
break;
}
case CBCentralManagerStatePoweredOn: { // 开启
LogRed(@"CBCentralManagerState--- PoweredOn");
#pragma mark -
#pragma mark - - 2.扫描外设(Discover Peripheral)
// 1. 搜索外设
[self.cMgr scanForPeripheralsWithServices:nil // 通过某些服务, 筛选外设
options:nil];
break;
}
}
} /*!
* @method centralManager:willRestoreState:
**/
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary<NSString *, id> *)dict{ } /*! *****@2 常用方法 - 发现外设触发此方法
* @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
*
*/
- (void)centralManager:(CBCentralManager *)central // 中心管理者
didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设
advertisementData:(NSDictionary<NSString *, id> *)advertisementData // 外设携带的数据
RSSI:(NSNumber *)RSSI // 外设信号强度
{
/**
peripheral - <CBPeripheral: 0x1666faa0, identifier = E57942BE-7941-DC11-1CD9-CEA1725456DF, name = (null), state = disconnected>
advertisementData - {
kCBAdvDataIsConnectable = 0;
kCBAdvDataManufacturerData = <75004204 018020fc 8f90a492 9bfe8f90 a4929a01 00000000 0000>;
}
*/
LogYellow(@"%@\n -- %@\n --%@\n --%@\n", central, peripheral, advertisementData, RSSI);
// 需要对连接到的设备进行过滤
// 1. 信号强度(大于35)
// 2. 设备名(前缀 "0") [peripheral.name hasPrefix:@"0"] &&
if((ABS(RSSI.integerValue) > 35)){
// 在此处对我们的 advertisementData, 进行处理 // 此处应该讲得到的外设存储到可变数组中
// 以下对一个外设处理:
// 让外设的生命周期 == VC
self.cPeriphery = peripheral;
#pragma mark -
#pragma mark - - 3.连接外设(Connect Peripheral)
// 发现外设之后进行连接
[self.cMgr connectPeripheral:self.cPeriphery options:nil];
}
} /*! *****@3 中心管理者成功连接外设后, 会触发此方法
* @method centralManager:didConnectPeripheral:
*
*/
- (void)centralManager:(CBCentralManager *)central // 中心管理者
didConnectPeripheral:(CBPeripheral *)peripheral // 外设
{ LogBlue(@"%@\n --- %@", central, peripheral);
// 连接成功后可以进行数据交互
// 3.1 获取外设的服务
self.cPeriphery.delegate = self;
#pragma mark -
#pragma mark - - 4.扫描外设中的服务和特征(Discover Services And Characteristics)
// 3.2 外设发现所有服务, nil代表不过滤
// 触发: - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
[self.cPeriphery discoverServices:nil];
} /*! *** 外设连接失败
* @method centralManager:didFailToConnectPeripheral:error: */
- (void)centralManager:(CBCentralManager *)central
didFailToConnectPeripheral:(CBPeripheral *)peripheral
error:(nullable NSError *)error{
LogGreen(@"error - %@ ", error);
} /*! *** 断开连接
* @method centralManager:didDisconnectPeripheral:error:
*
*/
- (void)centralManager:(CBCentralManager *)central
didDisconnectPeripheral:(CBPeripheral *)peripheral
error:(nullable NSError *)error{
LogGreen(@"error - %@ ", error);
} #pragma mark - CBPeripheryDelegate
/**
* 外设发现服务 触发此代理方法
*/
#warning 以下方法中只要error, 都要容错处理
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error
{
// 容错处理
[self dealError:error];
#pragma mark - - * 4.1 获取外设的services
// 遍历外设的所有服务
for (CBService *service in peripheral.services) {
// 发现服务后, 让外设发现服务内部 特征
// 触发: - (void)peripheral: didDiscoverCharacteristicsForService: error:
[peripheral discoverCharacteristics:nil forService:service];
}
LogGreen(@"%@", peripheral);
} /**
* 发现外设服务里面特征后 触发此代理方法
*
* @param peripheral 外设
* @param service 服务
* @param error 错误
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error
{
[self dealError:error];
#pragma mark - - * 4.2 获取外设的Characteristics和Descriptor for (CBCharacteristic *character in service.characteristics) {
// 获取特征对应的描述
// 触发: - didUpdateValueForDescriptor
[peripheral discoverDescriptorsForCharacteristic:character];
// 获取特征的值
// 触发: - didUpdateValueForCharacteristic:
[peripheral readValueForCharacteristic:character]; #warning 在此处调用写入数据方法
// [self yf_peripheral:peripheral didWriteData:<#(NSData *)#> forCharacteristic:character];
} } /**
* 更新特征的时候就会 触发此方法
*
* @param peripheral 外设
* @param characteristic 对应的服务的特征
* @param error 错误
*/
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
LogRed(@"%s", __FUNCTION__);
[self dealError:error]; for (CBDescriptor *descriptor in characteristic.descriptors) {
// 获取特征描述值
// 触发: - didDiscoverDescriptorsForCharacteristic
[peripheral readValueForDescriptor:descriptor];
}
} /**
* 更新特征的描述的值时, 触发此方法
*
* @param peripheral 外设
* @param descriptor 外设对应服务的特征的描述
* @param error 错误
*/
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForDescriptor:(CBDescriptor *)descriptor
error:(NSError *)error
{ LogRed(@"%s", __FUNCTION__);
[self dealError:error]; // 当前描述更新时, 直接调用此方法
[peripheral readValueForDescriptor:descriptor];
} /**
* 发现外设服务特征中的描述, 触发此方法
*
* @param peripheral 外设
* @param characteristic 服务对应的特征
* @param error 错误
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
LogRed(@"%s", __FUNCTION__);
[self dealError:error];
// 此处读取描述即可
for (CBDescriptor *descriptor in characteristic.descriptors) {
[peripheral readValueForDescriptor:descriptor];
}
} // 容错处理
- (void)dealError:(NSError *)error
{
if (error) {
LogRed(@"error - %@", error.localizedDescription);
return;
}
} #pragma mark 自定义方法
#pragma mark -
#pragma mark - - 5.利用特征与外设做数据交互(Explore And Interact)
/**
* 外设 写数据到特征中
* [注意]: 需要判断, 特征的属性是否支持写入
*/
- (void)yf_peripheral:(CBPeripheral *)peripheral
didWriteData:(NSData *)data
forCharacteristic:(nonnull CBCharacteristic *)charcteristic
{
/**
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
};
*/
LogYellow(@"char.pro = %d", charcteristic.properties);
// 由于枚举属性是 NS_OPTIONS类型, 所有一个枚举可能对应多个类型, 判断不能用 = , 应该用&(包含)
if (charcteristic.properties & CBCharacteristicPropertyWrite) {
// 核心代码 ---
[peripheral writeValue:data // 写入的数据
forCharacteristic:charcteristic // 特征
type:CBCharacteristicWriteWithResponse]; // 通过此响应记录是否成功写入
}
} #pragma mark -
#pragma mark - - 6.订阅Characteristic的通知
// 订阅通知和取消订阅
// [注意]: 一般根据项目的具体需求确定, 以下方法在哪调用
- (void)yf_peripheral:(CBPeripheral *)peripheral regNotifyWithCharacteristic:(nonnull CBCharacteristic *)charcteristic
{
// 外设为特征 订阅通知
// 触发: - didUpdateValueForCharacteristic:方法
[peripheral setNotifyValue:YES forCharacteristic:charcteristic];
} - (void)yf_peripheral:(CBPeripheral *)peripheral cancelNotifyWithCharacteristic:(nonnull CBCharacteristic *)charcteristic
{
// 外设为特征 取消订阅通知
// 触发: - didUpdateValueForCharacteristic:方法
[peripheral setNotifyValue:NO forCharacteristic:charcteristic];
} #pragma mark -
#pragma mark - - 7.断开连接(Disconnect)
- (void)yf_dismissConnectedWithPeripheral:(CBPeripheral *)peripheral
{
// 停止扫描
[self.cMgr stopScan]; // 断开连接
[self.cMgr cancelPeripheralConnection:peripheral];
} @end
demo时刻我的github
CoreBluetooth - 中心模式的更多相关文章
- 蓝牙(CoreBluetooth)-中心设备(客户端)
蓝牙(CoreBluetooth)-中心设备(客户端) 蓝牙客户端-中心设备 主要内容 1. 创建`中央管理器` 2. 发现并且连接外设 3. 寻找连接上的外设数据 4. 发送读或写`特征值`的请求 ...
- CoreBluetooth Central模式 Swift版
也是醉了,CB这个API到现在也没有Swift的文档.最新的文档还是3年前还是4年前的OC版的,被雷的外焦里嫩的.自己一点一点写成Swift还各种报错,最坑的是这些错误压根找不到解决方案.索性自己做个 ...
- SOFARPC模式下的Consul注册中心
Consul大家不陌生,就是和Zookeeper.Nacos一伙的,能够作为微服务基础架构的注册中心,算是比较成熟的组件,和Springcloud集成顺滑, 考虑到Eureka已经停止更新,所以有必要 ...
- 蓝牙 CoreBluetooth
baseK(相关基础知识)蓝牙常见名称和缩写 BLE:(Bluetooth low energy)蓝牙4.0设备因为低耗电,也叫BLEperipheral,central:外设和中心设备,发起链接的是 ...
- iOS之蓝牙开发—CoreBluetooth详解
CoreBluetooth的API是基于BLE4.0的标准的.这个框架涵盖了BLE标准的所有细节.仅仅只有新的iOS设备和Mac是和BLE标准兼容.在CoreBluetooth框架中,有两个主要的角色 ...
- Confluence 6 针对站点维护使用只读模式
如果你需要对 Confluence 进行维护,但是 Confluence 还是在运行或者你计划将站点合并到一个新的站点,你可以将你的 Confluence 站点设置为只读模式来限制用户在你站点中可以使 ...
- 服务注册中心Eureka vs Zookeeper vs Consul
前言 在现在云计算和大数据快速发展的今天,业务快速发展和变化.我们以前的单一应用难以应对这种快速的变化, 因此我们需要将以前单一的大应用不断进行差分,分成若干微小的应用或者服务,这就是微服务的思想.但 ...
- 白话SpringCloud | 第八章:分布式配置中心的服务化及动态刷新
前言 上一章节,简单介绍了分布式配置中心Spring Cloud Config的使用.同时,我们也遗漏了一些问题,比如如何配置实时生效,当服务端地址变更或者集群部署时,如何指定服务端地址?回想,在服务 ...
- 白话SpringCloud | 第七章:分布式配置中心的使用
前言 介绍完服务的容错保护处理,接下来我们来了解下关于分布式配置中心的相关知识和使用.众所周知,随着项目的越来越多,日益庞大,每个子项目都会伴随着不同的配置项,于此也就多了很多的配置文件.倘若某些配置 ...
随机推荐
- ArcGIS Desktop 与 Excel(转)
来自:http://blog.csdn.net/kikitamoon/article/details/19043161 微软 OFFICE 产品中,Excel是很强大,并且平民化的表格制作工具.Arc ...
- Base64 编码
Base64 字母表 Base64 编码将一个 8 位字节序列拆成 6 位的片段,并为每个 6 位的片段分配一个字符,这个字符是 Base64 字母表中的 64 个字符之一. Wert Zeichen ...
- Hive over HBase和Hive over HDFS性能比较分析
http://superlxw1234.iteye.com/blog/2008274 环境配置: hadoop-2.0.0-cdh4.3.0 (4 nodes, 24G mem/node) hbase ...
- oracle数据库常用操作命令
查看Oracle的版本: select * from product_component_version; 查看当前用户所具有的权限: SELECT * FROM DBA_SYS_PRIVS WHER ...
- Android屏幕保持唤醒状态
我们程序偶尔会有需要屏幕一直或较长时间的保持唤醒状态,而用户的睡眠时间又设置的比较短.这时可能会对程序以及用户的使用造成一定的影响.在Android中有两种方法,可以让我们在我们需要保持唤醒的页面长时 ...
- tomcat 6 不支持jsf2.2,仅支持jsf2.0及以下版本
tomcat 6 不支持jsf2.2,仅支持jsf2.0及以下版本 安装tomcat8即可.
- Sophos UTM WebAdmin存在未明漏洞
...
- WCF编程系列(五)元数据
WCF编程系列(五)元数据 示例一中我们使用了scvutil命令自动生成了服务的客户端代理类: svcutil http://localhost:8000/?wsdl /o:FirstServic ...
- ###Canny边缘检测算子
开源中国. #@date: 2014-06-20 #@author: gerui #@email: forgerui@gmail.com 一.一阶微分边缘算子 1. 一阶微分边缘检测算子也称梯度边缘算 ...
- Java实战之02Hibernate-06处理并发
十三.处理并发 1.事务的隔离级别 不考虑隔离级别出现的问题: 脏读:一个线程中的事务读到了另外一个线程中未提交的数据. 不可重复读:一个线程中的事务读到了另外一个线程中提交的update(更新)的数 ...