当下蓝牙开发可谓是越来越火,不论是智能穿戴的兴起还是蓝牙家具,车联网蓝牙等等,很多同学也会接触到蓝牙的项目,我从事蓝牙开发也有一段时间了,经手了两个项目。废话不多说了,先向大家简单的介绍有关蓝牙开发的知识。蓝牙低能耗(BLE),以下介绍的都是围绕iOS的框架展开的。

蓝牙开发分为中心者模式和管理者模式:1.常用的(其实99.99%)就是使用中心者模式作为开发,就是我们手机作为主机,连接蓝牙外设;2.管理者模式,这个基本用到的比较少,我们手机自己作为外设,自己创建服务和特征,然后有其他的设备连接我们的手机。

在做蓝牙开发之前,最好先了解一些概念:
服务(services):蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口;
特征(characteristic):存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位;
UUID:可以理解成蓝牙上的唯一标识符(硬件上肯定不是这个意思,但是这样理解便于我们开发),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征。

蓝牙连接可以大致分为以下几个步骤
1.建立一个Central Manager实例进行蓝牙管理
2.搜索外围设备
3.连接外围设备
4.获得外围设备的服务
5.获得服务的特征
6.从外围设备读数据
7.给外围设备发送数据
其他:提醒

首先我们先导入系统的BLE的框架

#import必须遵守2个协议/* 中心管理者 /
@property (nonatomic, strong) CBCentralManager *cMgr;/* 连接到的外设 /
@property (nonatomic, strong) CBPeripheral *peripheral;

1.建立一个Central Manager实例进行蓝牙管理

-(CBCentralManager *)cmgr
{if (!_cmgr) {_cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];}return _cMgr;
}//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{switch (central.state) {case 0:NSLog(@"CBCentralManagerStateUnknown");break;case 1:NSLog(@"CBCentralManagerStateResetting");break;case 2:NSLog(@"CBCentralManagerStateUnsupported");//不支持蓝牙break;case 3:NSLog(@"CBCentralManagerStateUnauthorized");break;case 4:{NSLog(@"CBCentralManagerStatePoweredOff");//蓝牙未开启}break;case 5:{NSLog(@"CBCentralManagerStatePoweredOn");//蓝牙已开启// 在中心管理者成功开启后再进行一些操作// 搜索外设[self.cMgr scanForPeripheralsWithServices:nil // 通过某些服务筛选外设options:nil]; // dict,条件// 搜索成功之后,会调用我们找到外设的代理方法- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外设}break;default:break;}
}

2.搜索外围设备 (我这里为了举例,采用了自己身边的一个手环)

// 发现外设后调用的方法

- (void)centralManager:(CBCentralManager *)central // 中心管理者didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设advertisementData:(NSDictionary *)advertisementData // 外设携带的数据RSSI:(NSNumber *)RSSI // 外设发出的蓝牙信号强度
{//NSLog(@"%s, line = %d, cetral = %@,peripheral = %@, advertisementData = %@, RSSI = %@", __FUNCTION__, __LINE__, central, peripheral, advertisementData, RSSI);/*peripheral = , advertisementData = {kCBAdvDataChannel = 38;kCBAdvDataIsConnectable = 1;kCBAdvDataLocalName = OBand;kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;kCBAdvDataServiceUUIDs =     (FEE7);kCBAdvDataTxPowerLevel = 0;}, RSSI = -55根据打印结果,我们可以得到运动手环它的名字叫 OBand-75*/// 需要对连接到的外设进行过滤// 1.信号强度(40以上才连接, 80以上连接)// 2.通过设备名(设备字符串前缀是 OBand)// 在此时我们的过滤规则是:有OBand前缀并且信号强度大于35// 通过打印,我们知道RSSI一般是带-的if ([peripheral.name hasPrefix:@"OBand"]) {// 在此处对我们的 advertisementData(外设携带的广播数据) 进行一些处理// 通常通过过滤,我们会得到一些外设,然后将外设储存到我们的可变数组中,// 这里由于附近只有1个运动手环, 所以我们先按1个外设进行处理// 标记我们的外设,让他的生命周期 = vcself.peripheral = peripheral;// 发现完之后就是进行连接[self.cMgr connectPeripheral:self.peripheral options:nil];NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);}
}

3.连接外围设备

// 中心管理者连接外设成功
- (void)centralManager:(CBCentralManager *)central // 中心管理者didConnectPeripheral:(CBPeripheral *)peripheral // 外设
{NSLog(@"%s, line = %d, %@=连接成功", __FUNCTION__, __LINE__, peripheral.name);// 连接成功之后,可以进行服务和特征的发现//  设置外设的代理self.peripheral.delegate = self;// 外设发现服务,传nil代表不过滤// 这里会触发外设的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error[self.peripheral discoverServices:nil];
}
// 外设连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);
}// 丢失连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);
}

4.获得外围设备的服务 & 5.获得服务的特征

// 发现外设服务里的特征的时候调用的代理方法(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);for (CBCharacteristic *cha in service.characteristics) {//NSLog(@"%s, line = %d, char = %@", __FUNCTION__, __LINE__, cha);}
}

6.从外围设备读数据

// 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法) 你可以判断是否
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);if (characteristic == @"你要的特征的UUID或者是你已经找到的特征") {//characteristic.value就是你要的数据}
}

7.给外围设备发送数据(也就是写入数据到蓝牙)
这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦

[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];//第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
// 需要注意的是特征的属性是否支持写数据
- (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{/*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};打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式*/
//    NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);// 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
}

其他:提醒
有那么多的特征,我们怎么知道哪些特征是用来读数据的,哪些是用来写入的,哪些是需要订阅之后再读的呢?
如果你们硬件工程师事先告诉你了,或者有完成的开发文档,那么就可以直接知道了,否则你就需要自己去查看特征的属性,推介可以使用下第三方的app——LightBlue,让你更能清楚的看到你蓝牙里面的服务,特征,特征的属性。

转载自大神原文章

iOS蓝牙开发:蓝牙连接和数据读写相关推荐

  1. Android Bluetooth蓝牙开发\蓝牙协议\蓝牙通信例子_Android支持蓝牙4.0版本_BLE开发

    一.Android Bluetooth现状 在android官网可以了解到android4.2新增了部分新功能,但是对于BT熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针 ...

  2. 蓝牙开发|蓝牙技术介绍

    蓝牙技术介绍 1. 蓝牙概述 蓝牙,是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话.PDA.无线耳机.笔记本电脑.相关外设等众多设备之间进行无线信息交换.利用"蓝牙& ...

  3. Android bluetooth 蓝牙开发/蓝牙协议/蓝牙通信

    一.Android Bluetooth现状 在android官网可以了解到android4.2新增了部分新功能,但是对于BT熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针 ...

  4. Android Bluetooth蓝牙开发\蓝牙协议\蓝牙通信

    一.Android Bluetooth现状 在android官网可以了解到android4.2新增了部分新功能,但是对于BT熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针 ...

  5. Android 蓝牙开发——蓝牙连接(六)

    一.APP端调用 //Android的SSP(协议栈默认)的UUID private String SPP_UUID = "00001101-0000-1000-8000-00805F9B3 ...

  6. 从零开始的nrf52832蓝牙开发--蓝牙BLE主函数分析

    关注.星标公众号,直达精彩内容 来源:https://blog.csdn.net/solar_Lan/article/details/88964043 工程目录中大部分文件都是官方 SDK 库中提供好 ...

  7. Android 蓝牙开发——蓝牙配对(五)

    一.APP端调用 //配对 try {Method method = BluetoothDevice.class.getMethod("createBond");method.in ...

  8. iOS 蓝牙开发资料记录

    一.蓝牙基础认识:   1.iOS蓝牙开发:   iOS蓝牙开发:蓝牙连接和数据读写   iOS蓝牙后台运行  iOS关于app连接已配对设备的问题(ancs协议的锅)          iOS蓝牙空 ...

  9. ios获取新数据要不要关_iOS开发之数据读写

    iOS进阶 1:数据处理之数据读写 1):获取当前应用程序的沙盒根目录 NSString*rootPath = NSHomeDirectory(); NSLog(@"%@",roo ...

最新文章

  1. Caffe下自己的数据训练和测试
  2. LambdaMART的源码分析:一(MART:回归树)
  3. 面向睡眠阶段分类的自适应时空图卷积神经网络
  4. 学习Java的三十三个建议
  5. mybatis-plus的 mapper.xml 路径配置的坑
  6. Runtime.getRuntime().exec()----记录日志案例
  7. 社区发现(一)--算法综述
  8. 如何在没有域的环境中搭建AlwaysOn(一)
  9. Mysql基本语句(个人笔记)
  10. OpenCV3.1.0安装在ubuntu16.40(Linux)步骤(电赛AM5708板子可用)
  11. 网站被封申诉通道方式方法
  12. 使用优盘为龙芯电脑安装系统
  13. C语言 简单走迷宫小游戏
  14. 生物信息学仿真软件SInC的初步使用教程
  15. AutoJs学习-实现坦克大战
  16. 好看的常用背景色RGB数值
  17. Watir数据驱动 - Excel
  18. SSM框架常用注解总结(持续更新)
  19. LG-P2657 [SCOI2009]windy数
  20. 全国多地新冠病例0增长,教你用Python画出当下疫情最火玫瑰图!

热门文章

  1. Android5.0 6.0 7.0新特性
  2. windos10本地安装git工具并使用
  3. 百度文库文档(文字和图片)
  4. ubuntu安装支持极点中文 支持拼音五笔混输的方法
  5. 如何在Excel中使用COUNTIF,COUNTIFS和SUMPRODUCT工作表功能
  6. Linux的远程终端连不上,Linux系统远程连接终端连接不上怎么办
  7. Quartus II三种方式实现D触发器及时序仿真
  8. 【fluent】fluent 2022R1找不到场景scene功能,找不到一些图标或功能怎么办?
  9. 判断一个数是否是素数(Java版)
  10. Redis哨兵Sentinel的搭建和原理说明