最近由于项目需要, 一直在研究蓝牙4.0,在这儿分享给大家, 望共同进步.

一、关于蓝牙开发的一些重要的理论概念:

1.当前ios中开发蓝牙所运用的系统库是<CoreBluetooth/CoreBluetooth.h>。

2.蓝牙外设必须为4.0及以上(2.0需要MFI认证),否则无法开发,蓝牙4.0设备因为低耗电,所以也叫做BLE。

3.CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外设和中心,就是你的苹果手机就是中心,外部蓝牙称为外设。

4.服务和特征(service and characteristic):简而言之,外部蓝牙中它有若干个服务service(服务你可以理解为蓝牙所拥有的能力),而每个服务service下拥有若干个特征characteristic(特征你可以理解为解释这个服务的属性)。

5.Descriptor(描述)用来描述characteristic变量的属性。例如,一个descriptor可以规定一个可读的描述,或者一个characteristic变量可接受的范围,或者一个characteristic变量特定的单位。

6.我们使用的蓝牙模块是在淘宝买的, 大概十多元一个, ios大概每次可以接受90个字节, 安卓大概每次可以接收20个字节, 具体数字可能会浮动, 应该是与蓝牙模块有关。

二、蓝牙连接的主要步骤

     1、创建一个CBCentralManager实例来进行蓝牙管理;2、搜索扫描外围设备;3、连接外围设备;4、获得外围设备的服务;5、获得服务的特征;6、从外围设备读取数据;7、给外围设备发送(写入)数据。

三、代码

// 加入权限访问, 否则上传AppStore会因为权限不足失败

1. 初始化

#import <CoreBluetooth/CoreBluetooth.h>
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

2. 搜索扫描外围设备

/***  --  初始化成功自动调用*  --  必须实现的代理,用来返回创建的centralManager的状态。*  --  注意:必须确认当前是CBCentralManagerStatePoweredOn状态才可以调用扫描外设的方法:scanForPeripheralsWithServices*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{switch (central.state) {case CBCentralManagerStateUnknown:NSLog(@">>>CBCentralManagerStateUnknown");break;case CBCentralManagerStateResetting:NSLog(@">>>CBCentralManagerStateResetting");break;case CBCentralManagerStateUnsupported:NSLog(@">>>CBCentralManagerStateUnsupported");break;case CBCentralManagerStateUnauthorized:NSLog(@">>>CBCentralManagerStateUnauthorized");break;case CBCentralManagerStatePoweredOff:NSLog(@">>>CBCentralManagerStatePoweredOff");break;case CBCentralManagerStatePoweredOn:{NSLog(@">>>CBCentralManagerStatePoweredOn");// 开始扫描周围的外设。/*-- 两个参数为Nil表示默认扫描所有可见蓝牙设备。-- 注意:第一个参数是用来扫描有指定服务的外设。然后有些外设的服务是相同的,比如都有FFF5服务,那么都会发现;而有些外设的服务是不可见的,就会扫描不到设备。-- 成功扫描到外设后调用didDiscoverPeripheral*/[self.centralManager scanForPeripheralsWithServices:nil options:nil];}break;default:break;}
}
#pragma mark 发现外设
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{NSLog(@"Find device:%@", [peripheral name]);if (![_deviceDic objectForKey:[peripheral name]]) {NSLog(@"Find device:%@", [peripheral name]);if (peripheral!=nil) {if ([peripheral name]!=nil) {if ([[peripheral name] hasPrefix:@"根据设备名过滤"]) {[_deviceDic setObject:peripheral forKey:[peripheral name]];// 停止扫描, 看需求决定要不要加
//                    [_centralManager stopScan];// 将设备信息传到外面的页面(VC), 构成扫描到的设备列表if ([self.delegate respondsToSelector:@selector(dataWithBluetoothDic:)]) {[self.delegate dataWithBluetoothDic:_deviceDic];}}}}}
}

3.连接外围设备

// 连接设备(.h中声明出去的接口, 一般在点击设备列表连接时调用)
- (void)connectDeviceWithPeripheral:(CBPeripheral *)peripheral
{[self.centralManager connectPeripheral:peripheral options:nil];
}
#pragma mark 连接外设--成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{//连接成功后停止扫描,节省内存
    [central stopScan];peripheral.delegate = self;self.peripheral = peripheral;//4.扫描外设的服务/**--     外设的服务、特征、描述等方法是CBPeripheralDelegate的内容,所以要先设置代理peripheral.delegate = self--     参数表示你关心的服务的UUID,比如我关心的是"FFE0",参数就可以为@[[CBUUID UUIDWithString:@"FFE0"]].那么didDiscoverServices方法回调内容就只有这两个UUID的服务,不会有其他多余的内容,提高效率。nil表示扫描所有服务--     成功发现服务,回调didDiscoverServices*/[peripheral discoverServices:@[[CBUUID UUIDWithString:@"你要用的服务UUID"]]];if ([self.delegate respondsToSelector:@selector(didConnectBle)]) {// 已经连接[self.delegate didConnectBle];}
}
#pragma mark 连接外设——失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{NSLog(@"%@", error);
}
#pragma mark 取消与外设的连接回调
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{NSLog(@"%@", peripheral);
}

4. 获得外围设备的服务

#pragma mark 发现服务回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{//NSLog(@"didDiscoverServices,Error:%@",error);CBService * __nullable findService = nil;// 遍历服务for (CBService *service in peripheral.services){//NSLog(@"UUID:%@",service.UUID);if ([[service UUID] isEqual:[CBUUID UUIDWithString:@"你要用的服务UUID"]]){findService = service;}}NSLog(@"Find Service:%@",findService);if (findService)[peripheral discoverCharacteristics:NULL forService:findService];
}

5、获得服务的特征

#pragma mark 发现特征回调
/**--  发现特征后,可以根据特征的properties进行:读readValueForCharacteristic、写writeValue、订阅通知setNotifyValue、扫描特征的描述discoverDescriptorsForCharacteristic。**/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{for (CBCharacteristic *characteristic in service.characteristics) {if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"你要用的特征UUID"]]) {/**-- 读取成功回调didUpdateValueForCharacteristic*/self.characteristic = characteristic;// 接收一次(是读一次信息还是数据经常变实时接收视情况而定, 再决定使用哪个)
//            [peripheral readValueForCharacteristic:characteristic];// 订阅, 实时接收
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];// 发送下行指令(发送一条)NSData *data = [@"硬件工程师给我的指令, 发送给蓝牙该指令, 蓝牙会给我返回一条数据" dataUsingEncoding:NSUTF8StringEncoding];// 将指令写入蓝牙
                [self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];}/**-- 当发现characteristic有descriptor,回调didDiscoverDescriptorsForCharacteristic*/[peripheral discoverDescriptorsForCharacteristic:characteristic];}
}

6.从外围设备读取数据

#pragma mark - 获取值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{// characteristic.value就是蓝牙给我们的值(我这里是json格式字符串)NSData *jsonData = [characteristic.value dataUsingEncoding:NSUTF8StringEncoding];NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];// 将字典传出去就可以使用了
}#pragma mark - 中心读取外设实时数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{if (characteristic.isNotifying) {[peripheral readValueForCharacteristic:characteristic];} else { NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);NSLog(@"%@", characteristic);[self.centralManager cancelPeripheralConnection:peripheral];}
}

7. 给外围设备发送(写入)数据

// 上文中发现特征之后, 发送下行指令的时候其实就是向蓝牙中写入数据
// 例:
// 发送检查蓝牙命令
- (void)writeCheckBleWithBle
{_style = 1;// 发送下行指令(发送一条)NSData *data = [@"硬件工程师提供给你的指令, 类似于5E16010203...这种很长一串" dataUsingEncoding:NSUTF8StringEncoding];[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
}
#pragma mark 数据写入成功回调
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{NSLog(@"写入成功");if ([self.delegate respondsToSelector:@selector(didWriteSucessWithStyle:)]) {[self.delegate didWriteSucessWithStyle:_style];}
}

8. 另外

// 扫描设备
- (void)scanDevice
{if (_centralManager == nil) {self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];[_deviceDic removeAllObjects];}
}
#pragma mark - 断开连接
- (void)disConnectPeripheral{/**-- 断开连接后回调didDisconnectPeripheral-- 注意断开后如果要重新扫描这个外设,需要重新调用[self.centralManager scanForPeripheralsWithServices:nil options:nil];*/[self.centralManager cancelPeripheralConnection:self.peripheral];
}
#pragma mark - 停止扫描外设
- (void)stopScanPeripheral{[self.centralManager stopScan];
}

由于硬件方面刚开始用蓝牙2.0跟我对接, 导致程序一直搜索不到设备.希望小伙伴们注意一下这个问题. 如果有不清楚的地方欢迎留言探讨.

iOS蓝牙开发(4.0)详解相关推荐

  1. iOS开发 蓝牙技术4.0详解

    前言 前端时间,同学在做项目过程中遇到关于蓝牙方面的问题,今天我就给大家进行详细的进行讲解下蓝牙在iOS开发中的具体实现.在介绍蓝牙前,大家要搞清楚什么是蓝牙? 什么是蓝牙? 随着蓝牙低功耗技术BLE ...

  2. iOS BLE蓝牙开发数据传输协议详解 常用算法(AES加密 HMAC_hash PRF)

    前言 这段时间参与了一款与蓝牙外设交互的项目, 以前没有涉及过数据传输方面的开发, 踩了不少坑, 同时也学到了很多东西. 此时, 项目也即将进入尾声, 有时间把这些记录一二. 本人才疏学浅, 如有错误 ...

  3. iOS 蓝牙开发BLE4.0的资料收集,基于原生Core Bluetooth

    (一)从0基础到现在可以写出一个完整的接收数据和发送数据的蓝牙程序,我从以下的博客里面学到很到东西,特别也感谢在QQ群里面为我解答的各位大神们,是时候回馈社会啦. 1.首先是写的很详细,并带有demo ...

  4. iOS开发证件要点详解

    iOS开发证书要点详解 引言 关于开发证书配置(Certificates&Identifiers&Provisioning Profiles),相信做iOS开发的同学没少被折腾.对于一 ...

  5. iOS蓝牙开发---CoreBluetooth[BLE 4.0] 初级篇[内附Demo地址]

    一.蓝牙基础知识 (一)常见简称 1.MFI  make for ipad ,iphone, itouch 专们为苹果设备制作的设备,开发使用ExternalAccessory 框架(认证流程貌似挺复 ...

  6. iOS 证书与签名 解惑详解

    iOS 证书与签名 解惑详解 分类: iPhone2012-06-06 19:57 9426人阅读 评论(1) 收藏 举报 iosxcodecryptographyappleiphone测试 目录(? ...

  7. STM32开发 -- 低功耗模式详解

    很多单片机都有低功耗模式,STM32 也不例外.当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗. 这部分不是我负责,但是也是有必要看一下的. 参看: STM32F1开发指南-库函数版本_ ...

  8. NRF52x开发环境搭建详解

    NRF52x开发环境搭建详解 准备 环境搭建 了解内存布局 Bootloader工程 APP工程 JFlash下载 打印log 准备 以下是项目开发环境搭建的一些文档或工具链接: 项目 链接 CPU ...

  9. iOS 原生级别后台下载详解

    怎样才能并发地下载一堆文件,并且能够在后台全部下载完成后再执行其他操作? 当然,这个问题其实很简单,解决方案也有很多.但我第一时间想到的是,目前是否存一个非常权威,非常流行.稳定可靠,并且是用 Swi ...

  10. 微信小程序开发登录界面mysql_微信小程序 欢迎界面开发的实例详解

    微信小程序 欢迎界面 市面上大多数的app都会有一个欢迎界面,下面将演示如何通过微信小程序实现一个欢迎界面. 下面将会按照以下的顺序介绍: 布局的实现 逻辑的实现 样式的实现 1.布局的实现 整个布局 ...

最新文章

  1. python建立访客记录
  2. c 输出空格_Python编程:案例详解输出函数print
  3. word公式编辑器_论文查重算公式吗 公式怎样避免查重?
  4. PyQt4(简单界面)
  5. webdriver高级应用- 右键另存为下载文件
  6. 在你的网站中使用 AdSense广告
  7. BigData | 一文带你搞清楚“数据倾斜”
  8. codesys编程_明晚20:00,CODESYS教您制作可编程控制器
  9. Oracle数据库的学习
  10. 使用Cisco思科模拟器进行三层交换机配置
  11. yolov3训练步骤
  12. C语言数组制作拼图游戏,C语言例子自制拼图游戏
  13. ECCV 2020 best paper: RAFT算法解析
  14. 关联性——相关性分析
  15. 吉他“和弦”是什么?
  16. 递归算法转换成非递归算法
  17. 7-2 程序改错题4 (5 分)
  18. 那些年,我们一起做过的 Java 课后练习题(26 - 30)
  19. 性能测试报告,实例讲解
  20. Docker容器安装最快最简单__编程小黑马

热门文章

  1. 目前数据可视化工具软件的排名
  2. 电脑主机前置耳机插孔没声音——解决办法
  3. Matlab读取显示图像顺序
  4. android国际化多语言对照
  5. 寻找影响免疫浸润细胞的基因(一)
  6. ut-890/485-usb驱动 FOR Linux
  7. C语言指针申请与释放
  8. 硬件与分析-音速小子
  9. 用友nc 文件服务器,用友NC软件财务部分完整版操作手册(附图片).pdf
  10. php 制作通讯录,PHP 制作通讯录(五)