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 | 第七章:分布式配置中心的使用
前言 介绍完服务的容错保护处理,接下来我们来了解下关于分布式配置中心的相关知识和使用.众所周知,随着项目的越来越多,日益庞大,每个子项目都会伴随着不同的配置项,于此也就多了很多的配置文件.倘若某些配置 ...
随机推荐
- SurfaceView的使用
1.概念 SurfaceView是View类的子类,可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图视图.它的特性是:可以在主线程之外的 线程中向屏幕绘图上.这样可以避免画图任务繁重 ...
- C语言细节总结笔记
C语言细节总结笔记 */--> C语言细节总结笔记 Table of Contents 1. 三步异或法交换数字 2. 做差法交换数字 3. 按n位置位 4. 求余求商求积 5. 辗除法求最大公 ...
- 如何在ios手机端的Safari浏览器 中“查看网页源代码”
在这里给大家分享一个很简单的用苹果手机无需越狱就可以查看网页源代码的方法,不过这个方法只用于苹果手机自带的Safari浏览器 随便添加一个safari 书签 (用于一会改为查看源码功能书签)进入书签 ...
- VSPackge插件系列:常用IDE功能的封装
继上一篇VSPackge插件系列简单介绍如何正确的获取DTE之后,就一直没发VSPackge插件系列的文章了,最近同事也想了解如何在代码中与VS交互,特发一篇文章示例一些简单功能是如何调用,也以备以后 ...
- JAXB - Annotations, The Annotation XmlElement
The basic annotation for a field that's intended to be an element is XmlElement. It permits you to d ...
- Lua - 基础语法
Hello World 交互式编程 Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用: [huey@huey-K42JE lua]$ lua Lua 5.1.4 Copyright ...
- android apk 防止反编译技术第一篇-加壳技术
做android framework方面的工作将近三年的时间了,现在公司让做一下android apk安全方面的研究,于是最近就在网上找大量的资料来学习.现在将最近学习成果做一下整理总结.学习的这些成 ...
- JQuery弹出层,实现弹层切换,可显示可隐藏。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...
- 安装oracle 12c遇到问题
安装前步骤:更改用户账户控制设置:从不通知 出现 "SEVERE: [FATAL] [INS-30014] 无法检查指定的位置是否位于 CFS 上" 解决办法:重新设置hosts ...
- 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记19 为Demo添加手势
在这一话中我们将应用上一话学到的知识来为Demo添加手势识别,首先添加一个缩放的功能,其次添加一个拖动功能,使得小人的表情可以随着我们的手指改变. 首先来添加一个缩放手势的识别器,我们来到FaceVi ...