iOS 蓝牙4.0开发使用
嗨大家好,我是iOS开发一枚大帅比,过去的几年项目涉及到蓝牙比较多,抽空之余,把使用的小知识点归纳起来,一是方便自己对知识做很好的总结和复习,二是希望能帮助到琅琊开发的朋友们。
一、简介(什么是BLE4.0?哪里使用它?)
现在的互联网时代,智能硬件设备越来越多样化,这些设备中,有多是通过手机来控制硬件设备,来达到控制的效果,这中间少不了要使用到蓝牙功能,通过蓝牙来通信来控制设备。也就是我们说的“设备中心和外设的故事”。
蓝牙版本介绍:
每个人对于蓝牙都不陌生,近距离数据传输,方便;可是当你的业务需求需要你第一次接触蓝牙开发的时候,却会发现你对它并不了解;首先,蓝牙发展至今经历了8个版本的更新。1.1、1.2、2.0、2.1、3.0、4.0、4.1、4.2。那么在1.x~3.0之间的我们称之为传统蓝牙,4.x开始的蓝牙我们称之为低功耗蓝牙也就是蓝牙ble,当然4.x版本的蓝牙也是向下兼容的。android手机必须系统版本4.3及以上才支持BLE API。低功耗蓝牙较传统蓝牙,传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等等优点。(现在的穿戴设备都是使用BLE蓝牙技术的)
传统蓝牙与低功耗蓝牙通信方式也有所不同,传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现。
本文章目的便是介绍BLE 4.0的使用以及相关问题的解决,本文采用简要模式介绍BLE4.0的核心类的使用以及蓝牙开发的简介,如需了解蓝牙知识的详细知识点,百度可搜索其他大神的文章进行学习,下文通用BLE代为蓝牙4.0。
二、BLE的核心模式
BLE的两种模式分为CBCentralMannager 中心模式 和CBPeripheralManager 外设模式,在这里主要和大家分享CBCentralMannager 中心模式的开发和使用。
CBCentralMannager 中心模式
以手机(app)作为设备中心,连接其他外设(硬件)的场景。详细流程如下:
1、建立中心角色
2、扫描外设
3、发现外设
4、连接外设:
1.连接失败
2. 连接断开
3.连接成功
5、扫描外设中的服务
1.发现并获取外设中的服务Service
6、扫描外设对应服务的特征
1.发现并获取外设对应服务的特征Characteristic
2.给对应特征写数据
3.订阅特征的通知 7.1 根据特征读取数据
说明:Service,Characteristic是每个硬件设备出厂设定的设备服务和特征值,用UUID作为唯一标识符。UUID为这种格式:0000ffe1-0000-1000-8000-00805f9b34fb。比如有3个Service,那么就有三个不同的UUID与Service对应。这些UUID都写在硬件里,我们通过BLE提供的API可以读取到,一个BLE终端可以包含多个Service, 一个Service可以包含多个Characteristic,一个Characteristic包含一个value和多个Descriptor,一个Descriptor包含一个Value。Characteristic是比较重要的,是手机与BLE终端交换数据的关键,读取设置数据等操作都是操作Characteristic的相关属性。说白了,我们可以把每个服务特征值看成是我们网络请求的api接口,我们和蓝牙的交互,是要连接到对应的service和对应的Characteristic才可以正确读取到和硬件文档以及出厂定制好的服务和数据。
三、CBPeriphera
暂且把这个小可爱理解为你所能发现搜索到的外设(硬件)对象,蓝牙硬件的信息都包含在它里面
下面我们看下这个类所包含的内容:
CB_EXTERN_CLASS @interface CBPeripheral : CBPeer
//代理
@property(weak, nonatomic, nullable) id
delegate; //我们所能搜索到的外设名称
@property(retain, readonly, nullable) NSString *name;
//信号强度
@property(retain, readonly, nullable) NSNumber *RSSI;
//设备状态,包含以下4种状态
@property(readonly) CBPeripheralState state;
typedef NS_ENUM(NSInteger, CBPeripheralState) {
CBPeripheralStateDisconnected = 0,
CBPeripheralStateConnecting,
CBPeripheralStateConnected,
CBPeripheralStateDisconnecting
}
//服务群组
@property(retain, readonly, nullable) NSArray
*services; 由于函数和属性太多,我只列举主要的几个,其他的可在代码中点击查看即可
四、使用步骤概要
1、导入:#import
2、遵守CBCentralManagerDelegate,CBPeripheralDelegate协议
3、初始化中心Manager,创建中心角色
为了方便引用,一般把manager声明为一个属性对象:
@property (nonatomic, strong) CBCentralManager * centralManager;
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
注:queue为你想把蓝牙初始化放到哪个队列,一般默认主队列
options传nil即可,具体使用可查看策略含义
4、检查当前设备中心的蓝牙状态
// 状态更新时调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
case CBManagerStateUnknown:{
NSLog(@"为知状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateResetting:
{
NSLog(@"重置状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateUnsupported:
{
NSLog(@"不支持的状态");
self.peripheralState = central.state;
}
break;
case CBManagerStateUnauthorized:
{
NSLog(@"未授权的状态");
self.peripheralState = central.state;
}
break;
case CBManagerStatePoweredOff:
{
NSLog(@"关闭状态");
self.peripheralState = central.state;
}
break;
case CBManagerStatePoweredOn:
{
NSLog(@"开启状态-可用状态");
self.peripheralState = central.state;
NSLog(@"%ld",(long)self.peripheralState);
}
break;
default:
break;
}
}
5、开始扫描
if (self.peripheralState == CBManagerStatePoweredOn){
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
6、发现外设
/**
扫描到设备
@param central 中心管理者
@param peripheral 扫描到的设备
@param advertisementData 广告信息
@param RSSI 信号强度
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary
*)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(@"%@",[NSString stringWithFormat:@"发现设备,设备名:%@",peripheral.name]);
}
7、连接外设
[self.centralManager connectPeripheral:peripheral options:nil];
连接状态
/**
@param central 中心管理者
@param peripheral 连接失败的设备
@param error 错误信息
*/
** 连接失败 **
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@"%@",@"连接失败");
}
** 连接断开 **
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(@"%@",@"断开连接");
}
** 连接成功 **
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"连接设备:%@成功",peripheral.name);
[self.centralManager stopScan];
}
8、扫描外设服务Service
// 设置设备的代理
peripheral.delegate = self;
// services:传入nil 代表扫描所有服务
[peripheral discoverServices:nil];
/**
扫描到服务
@param peripheral 服务对应的设备
@param error 扫描错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
// 遍历所有的服务
for (CBService *service in peripheral.services)
{
NSLog(@"服务:%@",service.UUID.UUIDString);
}
}
9、扫描service特征值
kWriteServerUUID 为和厂家协定好的,
例:读取电量的UUID:08B07DCB-13DD-435C-8BDA-04DA65BDC6AA
// 获取对应的服务
if (![service.UUID.UUIDString isEqualToString:kWriteServerUUID])
{
return;
}
// 根据服务去扫描特征
[peripheral discoverCharacteristics:nil forService:service];
10、给特征值写数据(就是发送指令)
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
11、订阅特征值通知(订阅后可收到回应的数据)
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]){
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
12、根据特征值读取数据(注:应把之前发送数据和订阅通知的peripheral和characteristic定义为全局属性)
*该处即为接收到外设发送的数据的方法
/**
根据特征读到数据
@param peripheral 读取到数据对应的设备
@param characteristic 特征
@param error 错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error
{
if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
{
NSData *data = characteristic.value;
NSLog(@"%@",data);
}
}
到这里,整个蓝牙使用的核心流程就基本介绍完了,鉴于写博客文章太累,太耗时,我决定先睡觉去,回头把文章慢慢细化一下,查漏补缺,格式可能也不是很完美,请读者们见谅,多提宝贵意见,喜欢的老铁们,可以点下喜欢或者收藏!
打个广告
本人github地址:shLuckySeven
欢迎去点star