基于低耗蓝牙的GATT Profile以及BLE中的回调

来源:互联网 发布:淘宝二级页面设计 编辑:程序博客网 时间:2024/05/17 23:17

一;先介绍GATT Profile的相关理论知识,接下来再讨论具体代码实现。
1;先了解一些关键词的含义;
——porfile;一种规范,一种标准的通信协议。每个profile中会包含多个service服务,每个service代表该从机的一种能力。
——service;一种服务,每种服务就代表一种能力,例如,蓝牙从机中有很多服务,电量信息服务、系统信息服务等,每个service中又包含多个characteristic特征值。每个具体的characteristic特征值才是ble通信的主题。比如当前的电量是80%,所以会通过电量的characteristic特征值存在从机的profile里,这样主机就可以通过这个characteristic来读取80%这个数据。
——characteristic;特征值,ble主从机的通信均是通过characteristic来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。
——UUID,统一识别码,我们刚才提到的service和characteristic,都需要一个唯一的uuid来标识
这里写图片描述
2;GATT是什么;
现在低功耗蓝牙(BLE)连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。
3;GAP
——详细介绍 GATT 之前,需要了解 GAP(Generic Access Profile),它在用来控制设备连接和广播。GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。例如 Beacon 设备就只是向外广播,不支持连接,小米手环就等设备就可以与中心设备连接。
——GAP 给设备定义了若干角色,其中主要的两个是:外围设备(Peripheral)和中心设备(Central)。
外围设备:这一般就是非常小或者简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备。例如小米手环。
中心设备:中心设备相对比较强大,用来连接其他外围设备。例如手机等。
——在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。

注意;实际上,我们在 Android 开发中,可以直接使用设备的 MAC 地址,发起连接,可以不经过扫描的步骤。这并不意味不需要经过 GAP,实际上在芯片级别已经给你做好了,蓝牙芯片发起连接,总是先扫描设备,扫描到了才会发起连接。意思就是在android开发中不需要管GAP,

4;GATT连接;
GATT 的全名是 Generic Attribute Profile(姑且翻译成:普通属性协议),它定义两个 BLE 设备通过叫做 Service 和 Characteristic 的东西进行通信。

注意;GATT 连接需要特别注意的是:GATT 连接是独占的。也就是一个 BLE 外设同时只能被一个中心设备连接。一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当设备断开,它又开始广播。中心设备和外设需要双向通信的话,唯一的方式就是建立 GATT 连接。

5;总结,这些理论告诉我们的就是
1;利用GAP进行连接,但是在android中我们不直接使用,直接通过获取MAC地址进行连接
2;主从机通过uuid找到服务和特征值进行读取修改等操作。

二,代码实现
1;先分析这几个类;都是api介绍;
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

注意;在BLE协议中,有两个角色,周边(Periphery)和中央(Central);周边是数据提供者,中央是数据使用/处理者;一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。a) BluetoothGattServer作为周边来提供数据;BluetoothGattServerCallback返回周边的状态。b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。

2;重新理解关于蓝牙ble通信的几个关键类;

  BluetoothGatt:BluetoothGatt 是我们用的最多,也是我们最重要的一个类,为了尽可能通俗的理解,这里我们可以把它看成Android手机与BLE终端设备建立通信的一个***管道***,只有有了这个管道,我们才有了通信的前提。  BluetoothGattService:蓝牙设备的服务,在这里我们把BluetoothGattService比喻成班级。而Bluetoothdevice我们把它比喻成学校,一个学校里面可以有很多班级,也就是说我们每台BLE终端设备拥有多个服务,班级(各个服务)之间通过UUID(唯一标识符)区别。  BluetoothGattCharacteristic: 蓝牙设备所拥有的特征,它是手机与BLE终端设备交换数据的关键,我们做的所有事情,目的就是为了得到它。在这里我们把它比喻成学生,一个班级里面有很多个学生,也就是说我们每个服务下拥有多个特征,学生(各个特征)之间通过UUID(唯一标识符)区别。  总结:当我们想要用手机与BLE设备进行通信时,实际上也就相当于我们要去找一个学生交流,首先我们需要搭建一个管道,也就是我们需要先获取得到一个BluetoothGatt,其次我们需要知道这个学生在哪一个班级,学号是什么,这也就是我们所说的serviceUUID,和charUUID。这里我们还需要注意一下,找到这个学生后并不是直接和他交流,他就好像一个中介一样,在手机和BLE终端设备之间帮助这两者传递着信息,我们手机所发数据要先经过他,在由他传递到BLE设备上,而BLE设备上的返回信息,也是先传递到他那边,然后手机再从他那边进行读取。  **重点;Android手机与BLE终端设备通信结果都是以回调的形式返回:**

3;了解ble中的回调事件。
这里写图片描述
——3.1;连接蓝牙BLE终端设备的方法以及回调方法;
这里写图片描述
——3.2;启动服务方法以及找到服务后回调的方法
这里写图片描述
——3.3;从特定的服务中获取特定的特征值;

之前我们说过,我们的最终目的就是获取Characteristic来进行通信,正常情况下,我们可以从硬件工程师那边得到serviceUUID和characteristicUUID.假设我们在知道serviceUUID和characteristicUUID的前提下,我们就可以通过下面代码获取相应特征值:  BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));BluetoothGattCharacteristic characteristic= service.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));

——3.4;开始通信,
在获取characteristic之后对其进行读写操作的方法以及其回调方法
这里写图片描述

——3.5;BLE终端设备返回数据回调事件
这里写图片描述

4;细讲ble中的回调事件。
部分源码
MainActivity 类

public class MainActivity extends Activity {    //BluetoothLeClass 类的对象    private BluetoothLeClass mBLE;    // 发现BLE终端的Service时回调    mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);    //实例化一个OnServiceDiscoverListener 接口对象    private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener() {        @Override        public void onServiceDiscover(BluetoothGatt gatt) {        }    }

BluetoothLeClass类;

public class BluetoothLeClass {    //创建一个监听的引用    private OnServiceDiscoverListener mOnServiceDiscoverListener;    //一个回调接口    public interface OnServiceDiscoverListener {        public void onServiceDiscover(BluetoothGatt gatt);    }    //进行注册,对mOnServiceDiscoverListener进行赋值,也就是记住传过来的监听对象    public void setOnServiceDiscoverListener(OnServiceDiscoverListener l) {        mOnServiceDiscoverListener = l;    }    //当服务被发现时调用接口中的方法。    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {        @Override        public void onServicesDiscovered(BluetoothGatt gatt, int status) {            mOnServiceDiscoverListener.onServiceDiscover(gatt);        }       }}

这里写图片描述
通过这个图来理解上面的代码。
MainActivity 类为客服端C;
BluetoothLeClass类;为服务端S;

原创粉丝点击