在iOS开发中,实现蓝牙通信有两种方式,一种是使用传统的GameKit.framework,另一种就是使用在iOS 5中加入的CoreBluetooth.framework。

利用CoreBluetooth框架,我们可以轻松实现两个iOS设备、iOS设备与非iOS蓝牙设备的交互。要注意的一点是目前这个框架只能支持蓝牙4.0BLE标准,所以对硬件上是有一定要求的,iPhone 4S及以后的设备,第三代iPad及以后的设备是支持这一标准的。

术语解释

我们首先看一下CoreBluetooth框架的结构。这是CoreBluetooth/CoreBluetooth.h文件中的声明。

1
2
3
4
#ifndef _CORE_BLUETOOTH_H_
#define _CORE_BLUETOOTH_H_
#endif
#import #import #import #import #import #import #import #import #import #import #import

其中,CBCentral开头的都是中心设备类,CBPeripheral开头的都是外设类。这就要讲到蓝牙设备的两个角色了。

  • 中心设备:中心设备可以理解为是处理数据的iOS设备,比如你的 iPhone、iPad 等。

  • 外设:外设顾名思义,就是产生数据的外部设备。这个外部设备可以是单片机、嵌入式设备甚至是另一个iOS设备等等。外设可以通过其传感器等产生有用数据,数据后通过蓝牙传给中心设备使用。

在建立连接的之前,外设向外发出广播数据(advertisementData,官方描述“A dictionary containing any advertisement and scan response data.”),广播数据是一个字典类数据,中心设备可以获取一定范围内的外设发出的广播数据。

现在开始

初始化

为了使用CoreBluetooth框架中的回调方法,我们要使用CBCentralManagerDelegate、CBPeripheralDelegate这两个协议。

我们先要初始化一个CBCentralManager类的对象。代码如下:

1
2
3
4
5
6
7
@interface SKBluetoothManager : NSObject{
    CBCentralManager *manager;
    id delegate;
}
manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
manager.delegate = self;

扫描外设

初始化完成,我们就可以让管理器开始扫描外设了:

1
[manager scanForPeripheralsWithServices:nil options:nil];

在设备发现周围外设的advertisementData后,会回调这个方法:

1
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;

其中参数central指回调这个方法的中心设备,peripheral指发现的外设对象CBPeripheral,advertisementData就是前面说的字典类型广播数据,RSSI是当前外设的信号强度,单位是dbm。

刚开始对陌生的蓝牙设备调试时,建议我们先用一个数组NSArray将所扫描到的外设进行保存:

1
[_peripherals addObject:peripheral];

连接外设

保存后,可根据设备的UUID来确定该设备是否为我们需要进行操作的蓝牙设备,在确认外设身份后,即可发起对外设的连接操作:

1
2
3
4
5
6
if ([peripheral.identifier.UUIDString isEqualToString:kPeripheralUUID]) {
    [manager stopScan];
    [manager connectPeripheral:peripheral options:nil];
    NSLog(@"连接外设:%@",peripheral.description);
    self.peripheral = peripheral;
}

在此步操作后,我们完成了对蓝牙设备的扫描工作,接下来的回调方法分为两种情况:

连接到外设后

1
2
3
4
5
6
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"已经连接到:%@", peripheral.description);
    peripheral.delegate = self;
    [central stopScan];
    [peripheral discoverServices:nil];
}

一旦连接好外设,我们就可以马上停止扫描。然后发起对服务的搜索:

1
- (void)discoverServices:(NSArray *)serviceUUIDs;

此处参数位需要扫描的服务的UUID的数组。文档中特别提到,若该参数为nil,将会扫描所有的服务。

连接失败后

在连接外设失败的回调方法中,提供了error参数,可根据实际需要来做异常处理,在此不做过多说明

1
2
3
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"连接%@失败",peripheral);
}

在搜索到蓝牙设备的服务后,将会回调

1
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error

若有错误发生,通过NSError异常处理。

扫描服务

由于服务在peripheral里是以NSArray的形式存在的,所以我们要对peripheral中的所有服务进行遍历:

1
2
3
4
5
6
7
8
for (CBService *service in peripheral.services) {
    //发现服务
    if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
        NSLog(@"发现服务:%@", service.UUID);
        [peripheral discoverCharacteristics:nil forService:service];
        break;
    }
}

扫描特征值

在遍历中,趁热打铁,直接对其特征值进行扫描,

1
[peripheral discoverCharacteristics:nil forService:service];

这里与扫描service是相同的,若扫描所有的特征值,直接传入nil作为参数即可。

这里的kServiceUUID是我们根据蓝牙设备的具体情况,提前设置好的UUID常量。本文所有kXxxxxUUID均为预设的UUID常量。

同样的,characteristics也是一个数组,我们利用像遍历services一样的方式来遍历所有的特征值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        NSLog(@"搜索特征%@时发生错误:%@", service.UUID, [error localizedDescription]);
        return;
    }
    NSLog(@"服务:%@",service.UUID);
    for (CBCharacteristic *characteristic in service.characteristics) {
//        NSLog(@"特征:%@",characteristic);
        //发现特征
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicWriteUUID]]) {
            _writeCharacteristic = characteristic;
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicNotifyUUID]]) {
            NSLog(@"监听特征:%@",characteristic);//监听特征
            [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
            _isConnected = YES;
        }
    }
}

特别要提到的是,我们不同的蓝牙设备有不同的服务和特征值。我的蓝牙模块的说明文档中已经说清楚了,write特征、read特征、notify特征,所以在此根据自身需要,来对不同的特征值进行操作。

设置监听

我在此要解释一下,当我们试图去读取蓝牙外设发过来的数据时,一定要找准特征值,用这个方法进行订阅。每次特征值变化的时候,就会有回调方法执行,从而达到读取数据的目的。容易出错误,一定分清楚到底哪个特征值该被订阅。

在订阅了特征值后,我们尝试用蓝牙外设发送一些数据出来,即可回调下一阶段的方法:

1
2
3
4
5
6
7
8
9
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"更新特征值%@时发生错误:%@", characteristic.UUID, [error localizedDescription]);
        return;
    }
// 收到数据
    [delegate didGetDataForString:[self hexadecimalString:characteristic.value]];
//    NSLog(@"%@",[self hexadecimalString:characteristic.value]);
}

数据的转换

我们接收到的数据,正是characteristic.value,这是一个NSData类数据,我们可以通过UTF8StringEncoding来转化为NSString,为了代码结构清晰,我专门把NSData和NSString互转写成了两个方法:

1
2
3
4
5
6
7
8
9
10
//将传入的NSData类型转换成NSString并返回
- (NSString*)hexadecimalString:(NSData *)data{
    NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return result;
}
//将传入的NSString类型转换成NSData并返回
- (NSData*)dataWithHexstring:(NSString *)hexstring{
    NSData *aData;
    return aData = [hexstring dataUsingEncoding: NSASCIIStringEncoding];
}

在拿到字符串后,通过各种回调方法,处理UI变动。

封装的 SKBluetooth 的地址:SKBluetooth

转载于:https://www.cnblogs.com/weiboyuan/p/6101296.html

iOS蓝牙开发CoreBluetooth快速入门相关推荐

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

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

  2. ios蓝牙开发 ------ CoreBluetooth 教程lt;转gt;

    原文地址:http://blog.csdn.net/jimoduwu/article/details/8917104 去App Store搜索并下载"LightBlue"这个App ...

  3. 小米手环iOS开发实战(一):iOS蓝牙框架CoreBluetooth

    小米手环iOS开发实战(一):iOS蓝牙框架CoreBluetooth 本项目为对小米手环进行二次开发,利用了小米手环蓝牙连接并不安全的特性,连接后可以获取手环数据,并可修改数据. 本实例使用Swif ...

  4. iOS 蓝牙开发 BabyBluetooth蓝牙库介绍

    BabyBluetooth 是一个最简单易用的蓝牙库,基于CoreBluetooth的封装,并兼容iOS和Mac OS X. 特色: 基于原生CoreBluetooth框架封装的轻量级的开源库,可以帮 ...

  5. Andorid/IOS 蓝牙开发总结

    IOS 蓝牙 ios 蓝牙依赖CoreBluetooth 库 1 首先增加库 CoreBluetooth    general-> Linked Frameworks and lib 2 权限i ...

  6. iOS 蓝牙开发资料记录

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

  7. ios 蓝牙开发总结

    随着蓝牙低功耗技术BLE(Bluetooth Low Energy)的发展,蓝牙技术正在一步步成熟,如今的大部分移动设备都配备有蓝牙4.0,相比之前的蓝牙技术耗电量大大降低.从iOS的发展史也不难看出 ...

  8. 涂鸦T2-U开发板快速入门

    文章目录 T2-U模组概述 特性 1.环境搭建 2.SDK下载 3.编译 3.1. 命令编译 3.2. 命令编译清除 3.3. Wind-IDE 编译 3.4.编译完成 4.下载 4.1. GUI工具 ...

  9. Z-Wave 800 Pro开发套件快速入门

    近期有用户在Silicon Labs(亦称"芯科科技")在线社区中分享了其使用Z-Wave 800 Pro开发套件(ZWAVE-PK800A)的心得,并简单介绍了如何快速启动的步骤 ...

最新文章

  1. sql注入,预编译和事务
  2. IE图标消失 HTML文件图标变为未知图标的解决方法
  3. 开关造成的毛刺_玻璃面板开关钻孔加工
  4. 三问三答,解传统企业敏捷转型担忧
  5. 数学专业下的计算机科学,被录取到信息与计算科学专业,这个专业什么性质,发展前景如何?...
  6. Spring Boot学习总结(14)——Spring Boot常见面试题汇总
  7. 没能 PK 掉 WiFi 的 Li-Fi,可能是 5G 请来的救兵
  8. 程序员的英语水平要达到什么程度才行?
  9. 微信小程序常用UI组件库
  10. php在线售卡系统,云尚在线发卡系统PHP源码|专门为个人或小型企业提供在线售卡,订单处理系统...
  11. 分享 :9个实用的Excel小技巧
  12. arcgis style样式表文件转换成geoserver sld文件
  13. 德国AI“算个球”:西班牙是冠军,只要别让德国进八强(严谨推理)
  14. 【CSS 书写模式 (Writing modes )】
  15. 内网visual studio code remote-ssh远程离线服务器
  16. c语言easyx改变字体大小,改变控制台字体大小
  17. 微信公众号自定义菜单如何添加特殊符号?
  18. Apollo-阿波罗配置中心详细使用教程
  19. Linux 重启nginx服务
  20. Springboot就业推荐系统qwy6c计算机毕业设计-课程设计-期末作业-毕设程序代做

热门文章

  1. 【Android】Activity的四种launchMode
  2. 组件面板 html 页面,Html - Bootstrap Panel面板
  3. android+定时器+动画,Android 实现定时器的四种方式总结及实现实例_Android_脚本之家...
  4. html怎么给框格加背景图,怎么给word 2013表格添加漂亮的背景图片
  5. 专科 java转go 翱翔之路(四)协议通信 锁,互斥锁 读写锁 条件变量锁 连接mysql 查询
  6. C++11学习笔记-----获取异步操作执行结果
  7. php写文件 效率,php中读写文件与读写数据库的效率_PHP教程
  8. zookeeper快速入门,配置虚拟机ip、mac、虚拟机免密,jdk的安装与卸载
  9. mysql 查询指定字段数据_MySQL使用select语句查询指定表中指定列(字段)的数据
  10. MFC使用CCommandLineInfo处理命令行