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

从上面这幅图可以看到,我们的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];
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

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

4.2 Step 2 寻找CBPeripheral外设

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

[self.centralManager scanForPeripheralsWithServices:@[] options:nil];
  • 1
  • 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]; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我们在这里创建了一个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]; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们这里先停止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]; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

我们根据找到的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];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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

4.7 Step 7 处理数据

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

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{NSData *data = characteristic.value;// Parse data ...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.8 Step 8 向设备写数据

这个很简单,只要使用:

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

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>", 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

6 小结

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

转载于:https://www.cnblogs.com/liaolijun/p/6689858.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git服务器维护 备份,gitlab服务运维,备份与恢复 - 橙子柠檬's Blog

gitlab服务运维工作Gitlab-ctl 使用gitlab-ctl start #启动服务gitlab-ctl stop #停止服务gitlab-ctl restart #重启服务检查服务的日志信息gitlab-ctl tail redis #检查redis的日志gitlab-ctl tail postgresql #…

使用TestNG的弹簧测试支持

TestNG是一个测试框架&#xff0c;旨在涵盖所有类别的测试&#xff1a;单元&#xff0c;功能&#xff0c;端到端&#xff0c;集成等。 它包括许多功能&#xff0c;例如灵活的测试配置&#xff0c;对数据驱动测试的支持&#xff08;使用DataProvider&#xff09;&#xff0c;强大…

Entity Framework - 理清关系 - 基于外键关联的单向一对一关系

注&#xff1a;本文针对的是 Entity Framework Code First 场景。 之前写过三篇文章试图理清Entity Framework中的一对一关系&#xff08;单相思&#xff08;单向一对一&#xff09;, 两情相悦&#xff08;双向一对一&#xff09;, 两情相悦-续&#xff09;&#xff0c;但当时理…

微信社交小程序服务器,Day12-微信小程序实战-交友小程序-搭建服务器与上传文件到后端...

要搞一个小型的cms内容发布系统因为小程序上线之后&#xff0c;直接对数据库进行操作的话&#xff0c;慧出问题的&#xff0c;所以一般都会做一个管理系统&#xff0c;让工作人员通过这个管理系统来对这个数据库进行增删改查微信小程序其实给我们提供了这样的能力了(也就是可以…

文件共享服务器imac,iMac怎么在网络上共享设备windows文件夹和服务 | MOS86

本章通过向您展示如何在网络和Mac和Windows计算机之间共享文件&#xff0c;文件夹和设备&#xff0c;帮助您充分利用您的iMac网络连接。→使用Macs共享文件和文件夹使用AirDrop和文件共享→与Windows 7计算机共享文件→设置共享权限→使用共享表快速在线共享文件→共享和访问网…

【转】 简单理解Socket

题外话 前几天和朋友聊天&#xff0c;朋友问我怎么最近不写博客了&#xff0c;一个是因为最近在忙着公司使用的一些控件的开发&#xff0c;浏览器兼容性搞死人&#xff1b;但主要是因为这段时间一直在看html5的东西&#xff0c;看到web socket时觉得很有意思&#xff0c;动手写…

业务活动监视器(BAM)2.0带来的革命

生产兼具精益和企业价值的中间件是一项艰巨的工作。 它要么不存在&#xff0c;要么需要创新的思维&#xff08;很多&#xff09;&#xff0c;并且需要在实现中反复进行。 业务风险很大&#xff0c;但是如果您做对了&#xff0c;它就会使您领先于其他任何公司。 这就是为什么我们…

oracle销售服务器吗,oracle 服务器 版本

oracle 服务器 版本 内容精选换一换Atlas 800 训练服务器(型号 9010)安装上架、服务器基础参数配置、安装操作系统等操作请参见《Atlas 800 训练服务器 用户指南 (型号9010)》。Atlas 800 训练服务器(型号 9010)适配操作系统如表1所示。请参考表2下载驱动和固件包。Atlas 800 训…

html 甘特图_Rplotly|交互式甘特图(Gantt chart)项目管理/学习计划

甘特图(Gantt chart)&#xff0c;又常被称为横道图或者条状图&#xff0c;是现代企业项目管理领域运用最为广泛的一种图示。就是通过条形来显示项目的进度、时间安排等相关情况的。项目管理外&#xff0c;也可以用来管理学习计划。绘制甘特图的工具有很多&#xff0c;本文介绍使…

Oracle Coherence:分布式数据管理

本文介绍如何使用Oracle Coherence提供分布式&#xff08;分区&#xff09;数据管理。 在下面的示例应用程序中&#xff0c;创建了一个名为OTV的新集群&#xff0c;并且在该集群的两个成员之间分配了一个名为user-map的缓存对象。 二手技术&#xff1a; JDK 1.6.0_21 Maven的…

美团点评DBProxy读写分离使用说明

目的 因为业务架构上需要实现读写分离&#xff0c;刚好前段时间美团点评开源了在360Atlas基础上开发的读写分离中间件DBProxy&#xff0c;关于其介绍在官方文档已经有很详细的说明了&#xff0c;其特性主要有&#xff1a;读写分离、负载均衡、支持分表、IP过滤、sql语句黑名单、…

apriori算法c++_关联分析——基于Apriori算法实现

电子商务推荐系统主要是通过统计和挖掘技术&#xff0c;根据用户在网站上的行为,主动为用户提供推荐服务&#xff0c;从而提高网站体验。而根据不同的业务场景&#xff0c;推荐系统需要满足不同的推荐粒度&#xff0c;包括搜索推荐,商品类目推荐,商品标签推荐&#xff0c;店铺推…

在Oracle Coherence中分发Spring Bean

本文展示了如何通过使用Oracle Coherence中的EntryProcessor和可移植对象格式&#xff08;POF&#xff09;功能来分发Spring Bean。 Coherence通过EntryProcessor API支持无锁编程模型。 此功能通过减少网络访问并在条目上执行隐式的低级锁定来提高系统性能。 此隐式低级锁定功…

Apache Commons SCXML:有限状态机实现

本文提到有限状态机&#xff08;FSM&#xff09;&#xff0c;SCXML&#xff08;状态图可扩展标记语言&#xff09;和Apache Common的SCXML库。 本文还提供了基本的ATM有限状态机示例代码。 有限状态机&#xff1a; 您可能还记得计算机科学课程中的有限状态机。 FSM用于设计计算…

pymol怎么做底物口袋表面_怎么从文献中发掘一篇新文章?

本文来自微信公众号&#xff1a;X-MOLNews可能你的导师也曾说过这样的话——盯着Nature、Science级别的文章做&#xff0c;可能最终会中十分的文章&#xff1b;如果盯着十分的文章做&#xff0c;可能最终发出来也就五六分&#xff1b;但如果就为了发个文章混毕业&#xff0c;很…

如何分析线程转储– IBM VM

本文是我们的线程转储分析系列的第4部分&#xff0c;它将为您概述什么是IBM VM的JVM线程转储以及您将找到的不同线程和数据点。 您将看到和学习​​到&#xff0c;IBM VM Thread Dump格式是不同的&#xff0c;但是提供了更多现成的故障排除数据。 在这一点上&#xff0c;您应该…

VMware vSphere克隆虚拟机

参考资料&#xff1a;http://blog.csdn.net/shen_jz2012/article/details/484167711. 首先将你所要克隆的虚拟机关掉2. 选择你的ESXI服务器选中"配置"&#xff0c;然后选中存储器右键你的存储介质&#xff0c;比如我的是datastore1&#xff0c;选择“浏览数据存储”。…

windows命令行无法启动redis_windows系统安装redis

1、下载最新redis https://github.com/MicrosoftArchive/redis/releases我选择下载msi版本的2.双击下载包安装3.设置redis环境变量&#xff0c;把redis路径配置到系统变量path值中4启动redis&#xff0c;cmd进入安装好redis文件夹 输入&#xff1a;如果redis启动出错Creating S…

OpenShift Express Web管理控制台:入门

本周&#xff0c; 最新版本的OpenShift为已经很棒的PaaS Cloud提供商带来了两个非常好的功能。 首先&#xff0c;JBoss AS已从7.0升级到7.1&#xff0c;并且所有新的Express Web Management Console已作为预览发布。 在本文中&#xff0c;我们将研究如何使用此新控制台&#xf…

女士细线毛衣起多少针_从起针到缝合,教你织毛衣的各种要点(详细教程)

新手学织毛衣看过来&#xff0c;7大编织要点帮你解决织好一件毛衣的基础问题&#xff0c;满满的干货&#xff0c;每点都值得学习!一、起针二、棒针符号三、如何织小样四、依据小样推算针数收挂肩的推算五、斜肩针数的推算开前、后领的位置与针数六、袖山的推算七、如何上袖子一…