文档章节

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

hejunbinlan
 hejunbinlan
发布于 2016/05/13 11:44
字数 1435
阅读 68
收藏 2
点赞 2
评论 0

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进行开发。实际上比想象的要简单。

© 著作权归作者所有

共有 人打赏支持
hejunbinlan
粉丝 40
博文 532
码字总数 21018
作品 0
浦东
高级程序员
介绍TTC CC2541 SDK 蓝牙4.0开发套件

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

昇润科技 ⋅ 05/21 ⋅ 0

nrf51822 另外一个板子

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

wowocpp ⋅ 05/10 ⋅ 0

【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951 ⋅ 06/11 ⋅ 0

Windows 10 新功能 Nearby Share 支持 Android 、iOS

Windows 10 April Update 中引入了诸多新功能,其中一项功能是 Nearby Share/Near Share,它可让用户轻松地将文件从一台 Windows 10 PC 传输到另一台,在 Build 2018 大会上,微软确认该功能...

雨田桑 ⋅ 05/15 ⋅ 0

集成蓝牙4.0的控制开发板--Bluno

DFRobot为你呈上Bluno,一款集成了蓝牙4。0通信模块的Arduino UNO开发板。通过我们开发的Android和IOS手机应用,你可以快速开发出一款与手机通信的硬件设备。正如现在非常火爆的可穿戴式手机...

红薯 ⋅ 2013/11/28 ⋅ 2

iOS-Security 苹果安全白皮书都讲了些啥?

2017.03.27 原文地址 使用Google 按段落翻译(上传文档的不太准),通读一遍后去掉设备或网络的超专业术语,也算是筛选掉对开发者意义不大的信息吧! 苹果设计的 iOS 平台向来是以安全为核心...

si1ence ⋅ 2017/12/14 ⋅ 0

苹果宣布将在 2019 年推出 iOS 和 macOS 跨平台功能

苹果 macOS 和 iOS 设备在功能方面越来越接近,现在苹果正在缩小这一差距。在昨天的 WWDC 开发者大会上,苹果表示不会将 iOS 和 macOS 进行合并,而是让 iOS 应用移植到 macOS 上变得更加简单...

王练 ⋅ 06/05 ⋅ 1

2018 一份"有点难"的iOS面试题(5年iOS开发)

序言: 之前一时兴致在本站上出过一份iOS的中级面试题,引起一些关注,不少同学表示对”隐藏关卡“感兴趣。升级版iOS面试题来了,目测难倒90%iOS程序员,目测一大波程序员撸着袖子在靠近。 ...

原来是泽镜啊 ⋅ 05/26 ⋅ 0

又拍云Prism CDN 超低价 低延时 超强兼容的P2P-CDN

又拍云Prism CDN 超低价 低延时 超强兼容的P2P-CDN 2018-05-15 10:26编辑: 枣泥布丁分类:业界动态来源:https://www.upyun.com/products CDN又拍云 招聘信息: C++工程师 Cocos2d-x游戏客户...

枣泥布丁 ⋅ 05/15 ⋅ 0

iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码

iOS精选源码 一款优秀的 聆听夜空FM 源码(http://www.code4app.com/thread-14546-1-1.html) zhPopupController 简单快捷弹出自定义视图(http://www.code4app.com/thread-14861-1-1.html) WHS......

sunnyaigd ⋅ 06/04 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

笔试题之Java基础部分【简】【一】

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他 1.length、length()和size() length针对...

anlve ⋅ 12分钟前 ⋅ 1

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 37分钟前 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 41分钟前 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 快别开心了,你还没有女友呢。

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享吴彤的单曲《好春光》 《好春光》- 吴彤 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :小萝莉街上乱跑,误把我认错成...

小小编辑 ⋅ 今天 ⋅ 8

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部