Bluetooth LE(低功耗蓝牙) - 第五部分
回顾:
在本系列前面的文章中我们完成了发现BLE传感器并与之建立连接。现在只剩下从其中获取数据了,但是这并没有看起来那么简单。在这篇文章中我们将讨论GATT的特点以及如何促进主机与传感器之间的数据交换。
GATT服务器的结构:
在前面的文章看我们了解了传感器包含GATT服务器,我们也已经与GATT建立连接。GATT服务器包含一个或多个GATT服务,不同的GATT服务代表了可以进行交换的不同类型的数据。例如,在SensorTag中有不同的GATT服务分别代表着SensorTag中不同的传感器组件(湿度传感器,气压传感器,等)。
每个GATT服务包含一个或多个GATT特性。一个GATT特性是一个可以通过BLE进行传递的原子数据。一个GATT特性可以包含任意的数据,用一个类型标识符表示任意数据的类型。它也可以包含零个或多个GATT描述符。
GATT描述符包含了关于该GATT特性的原子数据,例如GATT特性值的单位,或者当GATT特征值变化时是否需要通知我们。
总之,GATT服务器可以包含一个或多个GATT服务;每个GATT服务可以包含一个或多个GATT特性;每个GATT特性可包含零个或更多个GATT描述符。
GATT服务、特征以及描述符的一个共同点是他们都是使用一个通用唯一标识符(UUID)标识。正如UUID名称所表现的那样,UUID是一个简单且唯的标识符,用来找到GATT服务、特征以及描述符。
SensorTag的UUIDs可在 GATT服务器参考文档 中找到的。这可能有点令人困惑,但它其实是很简单的。所有的SensorTag UUID 都是基于这种形式:F0000000-0451-4000-B000- 00000000。四个黑体字的数字是不同的GATT服务、特征、描述唯一不一样的地方。如果我们看看下面的湿度传感器,我们可以看到其UUID是为AA20(类型为GATT_PRIMARY_SERVICE_UUID)。此服务的完整的UUID是F000AA20-0451-4000-B000-00000000.
服务有两个特征:
第一个代表着实际的传感器数据,UUID为AA21,转换后完整的UUID为 F000AA21-0451-4000-B000- 00000000。这些数据为4个字节,表示的温度和湿度值:TempLSB:TempMSB:HumidityLSB:HumidityMSB 之后我们将看看该如何解码。该特征有一个描述符(GATT_CLIENT_CHAR_CFG_UUID 条目),在文档中不会有该特征的UUID定义。这是因为这是一个标准的UUID,因为它提供一个公共的功能而被共同使用,就是当该值改变时我们需要被通知到。我们将在后面深入讨论这一点。
第二个特征是一个需要我们设置其为打开状态的标志,UUID为AA22,完整的UUID为 F000AA22-0451-4000-B000- 00000000。还是那句话,我们将在适当的时候看到其使用方法。
我们有必要去解释一些关于UUID以及UUID怎么工作的事情,在某些情况下,他们可能不像在SensorTag上那样作为设备的显著的特征。在许多传感器上可能很多服务都拥有一个共同的UUID和结构,不同的厂商都坚持将执行相同的功能的传感器使用一个标准的GATT服务标准(例如有一个专门的心率仪GATT服务标准等)。Also, it is possible to include GATT service UUIDS in the device discovery phase to only match devices which offer specific services. 。不幸的是,SensorTag不支持这个,所以在这篇教程不涉及这一块。如果你有兴趣的话,可以通过调用 BluetoothAdapter#onStartLeScan() 方法的不同形式来实现。
那么,现在我们知道了服务是如何组织的,我们可以开始读取数据了,是吗?不幸的是,它不是那么简单的。记住,与GATT服务器的连接由两部分组成:传感器上的GATT服务器,和一个本地代理。虽然我们可能知道GATT服务,本地代理不知道,所以我们要让本地代理从传感器中获取其服务列表。这个通过使用 discoverservices() 方法实现:

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt,
int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.v(TAG, "Connection State Changed: " +
(newState == BluetoothProfile.STATE_CONNECTED ?
"Connected" : "Disconnected"));
if (newState == BluetoothProfile.STATE_CONNECTED) {
setState(State.CONNECTED);
gatt.discoverServices();
} else {
setState(State.IDLE);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt,
int status) {
if(status == BluetoothGatt.GATT_SUCCESS) {
Log.v(TAG, "onServicesDiscovered: " + status);
}
}
}

再次说明,这是一个异步方法,所以我们可以毫无顾虑地在UI线程调用,同时我们需要定义一个合适的回调方法,当服务列表被完整后被调用。比较重要的一点事是要在回调方法中检查状态值,因为有时在搜索服务的过程中会调用相应的回调,但事实上搜索服务已经完成了。所以检查是否为GATT_SUCCESS 状态将确保一旦服务发现完成我们的回调方法只执行一次。
下期预告:
一旦支持的服务被装载到当地的代理,我们就可以访问服务所包含的特征,我们将在本系列文章的总结中讨论这一点。
本文的源代码在这里 可以找到。
Bluetooth LE(低功耗蓝牙) - 第五部分的更多相关文章
- Bluetooth LE(低功耗蓝牙) - 第一部分
前言 在写这篇文章的时候,谷歌刚刚发布了Android Wear ,摩托罗拉也发布了 Moto 360 智能手表.Android Wear的API还是相当基本的,是很好的文档材料,而且还会不断的更新, ...
- Bluetooth LE(低功耗蓝牙) - 第三部分
回顾 在本系列的前两篇文章中,我们已经了解了一些关于Bluetooth LE的背景并建立一个简单的Activity / Service框架. 在这篇文章中,我们将探讨Bluetooth LE的细节 ...
- Bluetooth LE(低功耗蓝牙) - 第二部分
回顾 在前面的文章中我们介绍了Bluetooth LE的背景也说明了我们在本系列文章中将要开发什么,但是还没有实际的代码.我们将在这篇文章中纠正这一点,我们将通过定义 Service/Activity ...
- Bluetooth LE(低功耗蓝牙) - 第四部分
回顾 在本系列前几篇文章中我们完成了BLE设备的发现 , 为我们的app通过BLE显示从TI SensorTag设备中获取到环境温度和湿度的工作打下了基础.在这篇文章中我们将着眼于连接到我们所发现的S ...
- Bluetooth LE(低功耗蓝牙) - 第六部分(完)
在本系列前面的文章中我们已经了解了,在我们从一个TI SensorTag中获取温度和湿度数据之前,我们需要经历的各种步骤.在本系列中的最后一篇文章,我们将完成注册并接收SensorTag的通知,并接收 ...
- Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探
Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便 ...
- Bluetooth Low Energy——蓝牙低功耗
Android4.3(API级别18)引入内置平台支持BLE的central角色,同时提供API和app应用程序用来发现设备,查询服务,和读/写characteristics.与传统蓝牙(Classi ...
- Android使用BLE(低功耗蓝牙,Bluetooth Low Energy)
背景 在学习BLE的过程中,积累了一些心得的DEMO,放到Github,形成本文.感兴趣的同学可以下载到源代码. github: https://github.com/vir56k/bluetooth ...
- 低功耗之战!ANT VS Bluetooth LE
利用近距离无线通信技术将手机及可穿戴式传感器终端等与智能电话连接起来,实现新的功能.最近,以此为目标的行动正在展开.其中备受关注的近距离无线方式是“ANT”和“Bluetooth LE”.为了在各种便 ...
随机推荐
- 在DropDownList里显示多级分类
protected void ddlBind() { DataTable dt = new DataTable(); ddlCategoryId.DataSource = getList(" ...
- spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务
spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务 >>>>>>>>>>>> ...
- ASP.NET MVC 第七回 UrlHelper
这节讲 一下ASP.NET MVC中的Helper. 何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组. 其实ASP.NET MVC的View是Aspx的页面,本身可以声明定义方 ...
- Oracle 特殊字符模糊查询的方法
最近在写DAO层的时候,遇到一个问题,就是使用like进行模糊查询时,输入下划线,无法精确查到数据,而是返回所有的数据. 这让我很好奇,百度之后才发现,原来是因为有些特殊字符需要进行转义才可以进行查询 ...
- 为什么要设置Java环境变量(详解)
关于java环境变量配置讲解: 1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下 ...
- C#中有关字符串去重的解决方案
今天在群里看到一个同学的面试题 题目中有一个这样的要求 //本地有个文档文件a.txt里面包含的内容分为一段字符串"abacbacde"请编写一个程序,获取文件得到对应的内容,并对 ...
- 如何写robots.txt?
robin 发表在 八月 2, 2006 在国内,网站管理者似乎对robots.txt并没有引起多大重视,应一些朋友之请求,今天想通过这篇文章来简单谈一下robots.txt的写作. robots.t ...
- 使用java的Calendar对象获得当前日期的上几个度开始、结束时间
思路: 先获得当前季度的开始和结束日期,在当前日期的基础上往前推3个月即上个季度的开始和结束日期 /** * @param flag true:开始日期:false:结束日期 * @return */ ...
- SQL SERVER排序函数
排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: 1.row_number 2.rank 3.dense_rank 4.ntile 下面分别介绍一 ...
- Jmeter软件测试3--发送二进制报文
一直用Jmeter测试post接口,但报文信息都是明文方式,今天测试兄弟求助二进制报文如何使用Jmeter测试,查看了项目源码,报文中不仅采用二进制,而且还用java.util.zip进行了压缩,从晚 ...