文档章节

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

hejunbinlan
 hejunbinlan
发布于 2016/05/13 11:44
字数 1435
阅读 70
收藏 2

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互联

从上面这幅图可以看到,我们的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。 
LightBlue

在实际使用中,我们都是要通过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];
  • 1

这里的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的方法:

  •  

我们这里先停止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进行开发。实际上比想象的要简单。

本文转载自:http://blog.csdn.net/songrotek/article/details/46443965

共有 人打赏支持
hejunbinlan
粉丝 41
博文 595
码字总数 21569
作品 0
浦东
高级程序员
私信 提问
MQTT消息推送, BLE蓝牙

MQTT协议 http://www.jianshu.com/p/19765f425259 http://blog.csdn.net/join_wangzi/article/details/7779709 https://github.com/wenghengcong/MQTTExplore Server和iOS的Client Demo htt......

iMrSong
2016/07/22
1
0
nrf51822 另外一个板子

overheat 2013年12月9日20:30到12月11日21:30,过期或售完自动下架。 描述: CPU:nRF51822 传感器:MPU6050(加速度计、陀螺仪) 用户界面:5个独立可编程LED,2个用户按键 GPIO:32 下载方...

wowocpp
05/10
0
0
介绍TTC CC2541 SDK 蓝牙4.0开发套件

简介 TTC CC2541 SDK 是由我司针对TI的CC2541芯片开发提供的快速开发工具。旨在让开发人员不再需要将大量精力放在蓝牙调试方面,只需将精力放在对CC2541芯片功能的应用开发上。 TTC CC2541 S...

昇润科技
05/21
0
0
Android ble peripheral 连接后自动断开

使用android手机作为蓝牙4.0的外围设备,用iOS上的lightblue进行测试; 能正常扫描到android的蓝牙,但一连接马上就断开了,根据log确实是连接成功后再断开的,但我没有进行断开连接的操作啊...

大明东北虎
2016/08/15
851
1
iOS发出蓝牙指令无法收到正确响应,但是相同蓝牙指令在安卓下可收到正常响应

【业务需求】 我们有一个自己设计生产的的蓝牙模块, 通过BLE(低功耗蓝牙)和手机通信。 目前在安卓上测试,手机发出指令后可以收到蓝牙模块的正确响应数据, 但是在iOS上发出指令后无法收到...

herozhang
2017/01/16
1
3

没有更多内容

加载失败,请刷新页面

加载更多

node.js学习笔记之koa框架和简单爬虫练习

Koa -- 基于 Node.js 平台的下一代 web 开发框架 koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调...

前端小攻略
5分钟前
0
0
JavaScript中的继承及实现代码

JS虽然不像是JAVA那种强类型的语言,但也有着与JAVA类型的继承属性,那么JS中的继承是如何实现的呢? 一、构造函数继承 在构造函数中,同样属于两个新创建的函数,也是不相等的 function Fn...

peakedness丶
27分钟前
1
0
记一次面试最常见的10个Redis"刁难"问题

导读:在程序员面试过程中Redis相关的知识是常被问到的话题。作为一名在互联网技术行业打击过成百上千名的资深技术面试官,本文作者总结了面试过程中经常问到的问题。十分值得一读。 Redis在...

小刀爱编程
40分钟前
14
0
TiDB Lab 诞生记 | TiDB Hackathon 优秀项目分享

本文由红凤凰粉凤凰粉红凤凰队的成员主笔,他们的项目 TiDB Lab 在本届 TiDB Hackathon 2018 中获得了二等奖。TiDB Lab 为 TiDB 培训体系增加了一个可以动态观测 TiDB / TiKV / PD 细节的动画...

TiDB
53分钟前
4
0
当区块链遇到零知识证明

本文由云+社区发表 当区块链遇到零知识证明 什么是零知识证明 零知识证明的官方定义是能够在不向验证者任何有用的信息的情况下,使验证者相信某个论断是正确的。这个定义有点抽象,下面笔者举...

腾讯云加社区
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部