iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发

1 前言

当前有越来越多的可穿戴设备使用了蓝牙4.0 BLE(Bluetooth Low Energy)。对于iOS开发而言,Apple之前专门推出CoreBluetooth的Framework来支持BLE的开发。对于硬件开发有了解的朋友应该知道,在之前使用低版本的蓝牙的设备,要连接到iOS设备上,需要注册MFI,拥有MFI协议才能进行相应的开发。如果大家关注我之前对LEGO EV3的研究,就可以发现,EV3是使用了蓝牙2.1,因此需要MFI协议来进行开发。

本文将一步一步讲解如何使用CoreBluetooth框架来与各种可穿戴设备进行通信,使用 小米手环 来进行基本的测试。

2 开发环境

1 Macbook Pro Mac OS X 10.10

2 Xcode 6.3.2

3 iPhone 5s v8.1

4 小米手环

3 基本流程

要开发蓝牙,需要对整个通讯过程有个基本了解。这里我摘录一些Apple官方的文档Core Bluetooth Programming Guide的图片来加以说明。这个文档其实对于开发的流程写的是非常的清楚,大家最好可以看一下。

3.1 可穿戴设备与iOS互联方式

从上面这幅图可以看到,我们的iOS设备是Central,用来接收数据和发送命令,而外设比如小米手环是Peripheral,向外传输数据和接收命令。我们要做的就是通过Central来连接Peripheral,然后实现数据的接收和控制指令的发送。在做到这一步之后,再根据具体的硬件,对接收到的数据进行parse解析。

3.2 可穿戴设备蓝牙的数据结构

这里用的是心率设备来做说明,每个外设Peripheral都有对应的服务Service,比如这里是心率Service。一个外设可以有不止一个s、Service。每个service里面可以有多个属性Characteristic,比如这里有两个Characteristic,一个是用来测量心率,一个是用来定位位置。

那么很关键的一点是每个Service,每个Characteristic都是用UUID来确定的。UUID就是每个Service或Characteristic的identifier。

大家可以在iPhone上下载LightBlue这个应用。可以在这里查看一些设备的UUID。

在实际使用中,我们都是要通过UUID来获取数据。这点非常重要。

在CoreBluetooth中,其具体的数据结构图如下:

4 Step-By-Step 上手BLE开发

4.1 Step 1 创建CBCentralManager

从名字上大家可以很清楚的知道,这个类是用来管理BLE的。我们也就是通过这个类来实现连接。

先创建一个:

@property (nonatomic,strong) CBCentralManager *centralManager;

dispatch_queue_t centralQueue = dispatch_queue_create("com.manmanlai", DISPATCH_QUEUE_SERIAL);
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];

然后关键在于CBCentralManagerDelegate的使用。这个之后再讲。

4.2 Step 2 寻找CBPeripheral外设

有了CBCentralManager,接下来就是寻找CBPeripheral外设,方法很简单:

[self.centralManager scanForPeripheralsWithServices:@[] options:nil];

这里的Service就是对应的UUID,如果为空,这scan所有service。

4.3 Step 3 连接CBPeripheral

在上一步中,如果找到了设备,则CBCentralManager的delegate会调用下面的方法:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSLog(@"name:%@",peripheral);
    if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) {
        return;
    }

    if (!self.peripheral || (self.peripheral.state == CBPeripheralStateDisconnected)) {
        self.peripheral = peripheral;
        self.peripheral.delegate = self;
        NSLog(@"connect peripheral");
        [self.centralManager connectPeripheral:peripheral options:nil];
    }

}

我们在这里创建了一个CBPeripheral的对象,然后直接连接

CBPeripheral的对象也需要设置delegate.

4.4 Step 4 寻找Service

如果Peripheral连接成功的话,就会调用delegate的方法:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    if (!peripheral) {
        return;
    }

    [self.centralManager stopScan];

    NSLog(@"peripheral did connect");
    [self.peripheral discoverServices:nil];

}

我们这里先停止Scan,然后让Peripheral外设寻找其Service。

4.5 Step 5 寻找Characteristic

找到Service后会调用下面的方法:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    NSArray *services = nil;

    if (peripheral != self.peripheral) {
        NSLog(@"Wrong Peripheral.\n");
        return ;
    }

    if (error != nil) {
        NSLog(@"Error %@\n", error);
        return ;
    }

    services = [peripheral services];
    if (!services || ![services count]) {
        NSLog(@"No Services");
        return ;
    }

    for (CBService *service in services) {
        NSLog(@"service:%@",service.UUID);
        [peripheral discoverCharacteristics:nil forService:service];

    }

}

我们根据找到的service寻找其对应的Characteristic。

4.6 Step 6 找到Characteristic后读取数据

找到Characteristic后会调用下面的delegate方法:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    NSLog(@"characteristics:%@",[service characteristics]);
    NSArray *characteristics = [service characteristics];

    if (peripheral != self.peripheral) {
        NSLog(@"Wrong Peripheral.\n");
        return ;
    }

    if (error != nil) {
        NSLog(@"Error %@\n", error);
        return ;
    }

    self.characteristic = [characteristics firstObject];
    //[self.peripheral readValueForCharacteristic:self.characteristic];
    [self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];

这里我们可以使用readValueForCharacteristic:来读取数据。如果数据是不断更新的,则可以使用setNotifyValue:forCharacteristic:来实现只要有新数据,就获取。

4.7 Step 7 处理数据

读到数据后会调用delegate方法:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
   NSData *data = characteristic.value;
   // Parse data ...

}

4.8 Step 8 向设备写数据

这个很简单,只要使用:

[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];

data是NSData类型。

5 实验

使用小米手环实验,得到如下结果:

2015-06-10 16:52:31.607 KetherDemo[13786:1792995] scaning device
2015-06-10 16:52:33.474 KetherDemo[13786:1793032] name:<CBPeripheral: 0x1700e4380, identifier = 6FF833E3-93C1-28C6-CBC0-74A706AAAE31, name = LS_SCA16, state = disconnected>
2015-06-10 16:52:33.475 KetherDemo[13786:1793032] connect peripheral
2015-06-10 16:52:37.538 KetherDemo[13786:1793031] peripheral did connect
2015-06-10 16:52:37.984 KetherDemo[13786:1793031] service:FEE7
2015-06-10 16:52:37.985 KetherDemo[13786:1793031] service:Device Information
2015-06-10 16:52:38.099 KetherDemo[13786:1793032] characteristics:(
    "<CBCharacteristic: 0x17409c250, UUID = FEC8, properties = 0x20, value = (null), notifying = NO>",
    "<CBCharacteristic: 0x17409c200, UUID = FEC7, properties = 0x8, value = (null), notifying = NO>"
)
2015-06-10 16:52:38.100 KetherDemo[13786:1793032] Kether did connect
2015-06-10 16:52:38.101 KetherDemo[13786:1793032] Kether did connect
2015-06-10 16:52:38.280 KetherDemo[13786:1793031] characteristics:(
    "<CBCharacteristic: 0x17009f270, UUID = Manufacturer Name String, properties = 0x2, value = (null), notifying = NO>",
    "<CBCharacteristic: 0x17009f2c0, UUID = Model Number String, properties = 0x2, value = (null), notifying = NO>",
    "<CBCharacteristic: 0x17009f310, UUID = Serial Number String, properties = 0x2, value = (null), notifying = NO>",
    "<CBCharacteristic: 0x17009eb90, UUID = Hardware Revision String, properties = 0x2, value = (null), notifying = NO>",
    "<CBCharacteristic: 0x17009f0e0, UUID = Firmware Revision String, properties = 0x2, value = (null), notifyi``

 = NO>",

6 小结

通过上面的方法,我们就可以轻松的对BLE进行开发。实际上比想象的要简单。

【本文为原创文章,转载请注明出处:blog.csdn.net/songrotek】

时间: 2024-10-05 05:06:08

iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发的相关文章

iOS开发之可穿戴设备蓝牙4.0 BLE 开发

http://yuedu.baidu.com/album/view/e581f869011ca300a6c390b0.html/2015-6-21 http://yuedu.baidu.com/album/view/e581f869011ca300a6c390b0.html/2015-6-21 http://yuedu.baidu.com/album/view/0ab367c20c22590102029db0.html/2015-6-21 http://yuedu.baidu.com/album

蓝牙4.0 BLE 开发

在BLE开发中的一些随记,供大家参考: 凡事皆有状态 低功耗蓝牙背后有个基本的概念:任何事务都有状态.状态可以是任何东西:当前的温度,设备里电池的状态,设备名称或者对测量温度的地点的描述.它通过属性服务器上的属性协议对外公开. 状态不局限与“可读”状态,还包括“可写”状态. 一些状态是可变的,甚至是频繁改变(部分传感器).哟快速实现服务器到客户端的状态传输,就必须支持状态信息的通知功能.通知直接从服务器发送至客户端,无需客户端向服务器执行轮询,这种设计可以支持高效的应用,比如只有当电池出现状况是

Android项目实战(三十四):蓝牙4.0 BLE 多设备连接

原文:Android项目实战(三十四):蓝牙4.0 BLE 多设备连接 最近项目有个需求,手机设备连接多个蓝牙4.0 设备 并获取这些设备的数据. 查询了很多资料终于实现,现进行总结. -------------------------------------------------------------------------------------------------------------------------------------------------------------

蓝牙4.0 BLE

读了N多文档,其中推荐的有: Webee的<蓝牙4.0是战演练> Ghostyu的 <BLE权威教程> 1:透穿实现: 利用TI的BLE包里的工程直接烧 上位设备用 central,下位设备用peripheral工程 做以下处理: central 的NPI初始化时添加uart CB,并在串口回调函数中 直接添加write char函数写进特征值(实现上位从串口接收并通过蓝牙发送), 使能特征值通知,并在通知处理事件中将数据从串口发送(实现上位的从蓝牙接受并从串口发送) periph

[Android Wear]安卓穿戴设备Moto 360测评与开发分析

前言: 昨天刚买到了Moto 360,这是楼主目前为止见到的最好的安卓可穿戴设备,一个圆形的手表: BesBuy和官网都卖光了..这是楼主听说补货了去bestbuy买到的. 外形上这就是一块普通的电子表,但其实包含的功能确实不少.最令人心动的就是它圆形的表盘,这比市面上方形的安卓手表更具有吸引力. 唯一的遗憾就是..不是完整的圆形(处女座的..) 这个其实是可以理解的:做成完整的圆形也是可以的,但是那样必然会加大或者加厚表盘--因为需要空间去放IC和一些排线,而美观和实用程度会大大降低.不然的话

iOS开发——项目实战Swift篇&amp;swift 2.0项目开发总结二(开发常用)

swift 2.0项目开发总结二(开发常用) 一:相册中选择相片到App指定位置 随 着相机像素的提高,实际用户选择的图片都是很大的,有的高达5.6M,如果直接使用用户选着的图片,非常消耗内存,并且也用不到这么高像素的图片,可以当 用户选着好图片后,在UIImagePickerController对应的代理方法中,先将图片进行重新绘制为需要的大小,在设置给iconView 1 /// MARK: 摄像机和相册的操作和代理方法 2 extension MeViewController: UIIma

iOS开发——项目实战Swift篇&amp;swift 2.0项目开发总结一(开发常用)

swift 2.0项目开发总结一(开发常用) 一:新特性(版本判断)的实现 1 let versionStr = "CFBundleShortVersionString" 2 let cureentVersion = NSBundle.mainBundle().infoDictionary![versionStr] as! String 3 let oldVersion = (NSUserDefaults.standardUserDefaults().objectForKey(vers

蓝牙4.0 BLE学习笔记

一.知识普及 1.蓝牙4.0分为两个部分: 1)Bluetooth Ready,兼容传统蓝牙的高速部分: 2)Bluetooth Smart,BLE(Bluetooth Low Energy),功耗低,速率低.最大传输速率4~5k字节/s: 2.BLE协议栈: 1)只是一个协议规范,BLE协议栈是该协议的代码实现:蓝牙组织SIG负责制定协议,芯片公司负责实现协议: 2)BLE协议栈是芯片公司预先编好的源码或者库: 3.CC2540/2541,CC254x就是一颗带有蓝牙功能的51单片机,BLE协

Android 蓝牙4.0 BLE

Android ble (Bluetooth Low Energy) 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用. BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备. 官方demo:http://developer.android.com/guide/topics/connectivity/bluetooth-le.html 官方demo(