蓝牙技术联盟在2010年6月30号公布了蓝牙4.0标准,4.0标准在蓝牙3.0+HS标准的基础上增加了对低功耗蓝牙(Bluetooth Low Energy, BLE)的支持。相比原有的普通蓝牙和高速蓝牙,BLE最大的特点就是低功耗,低延时,快速的搜索和连接速度,但数据传输速度相比传统蓝牙低。关于BLE设备的连接部分已经在上一篇中介绍,参见http://blog.csdn.net/luyi325xyz/article/details/41623995。
1. 数据发送
本文将介绍BLE设备之间的数据传输,首先是数据的发送。数据的发送通过Characteristic完成,发送数据的Characteristic必须拥有写权限,即BluetoothGattCharacteristic类中的mProperties属性必须为以下两者中之一:
/**
* 写权限:不需要响应
*/
public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04;
/**
* 写权限:需要响应
*/
public static final int PROPERTY_WRITE = 0x08;
在BLE的连接过程中,连接成功后会返回一个BluetoothGatt类型变量(见上一篇文章的2.7步骤),该类封装了BLE主要的操作。发送数据所需的Characteristic在BLE设备连接成功后的获取Service的过程中获得(见上一篇文章的2.10步骤),因此BLE的数据发送可以如下所示:
@Override
public boolean writeCharacteristic(ICharacteristicBle chrBle) {
return mBleGatt.writeCharacteristic((BluetoothGattCharacteristic)chrBle);
}
为了获取Characteristic的通知回调,在发送数据之前还需使能该Characteristic的通知:
/**
* 设置characteristicde的通知
*
* @param chrBle 设备的characteristic
* @param enable 是否通知
* @return 设置是否成功
*/
public boolean setCharacteristicNotification(ICharacteristicBle chrBle, boolean enable) {
return mBaseBle.setCharacteristicNotification(chrBle, enable);
}
BLE的写入结果回调函数:
/**
* 当写characteristics得到结果时回调
* 如果该函数可信写入过程中被调用, 此时characteristics的返回值由设备决定. APP应当将该值与
* 要求的值相比较, 如果两者不相等, 则APP将会终止可信写入过程.
*
* @param bleGatt GATT客户端连接, 被{@link BluetoothGatt#writeCharacteristic}调用
* @param bleChrc 写入相关设备的characteristics值
* @param status 写入操作的结果, 如果写入成功时返回{@link BluetoothGatt#GATT_SUCCESS}
*/
public void onCharacteristicWrite(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc, int status) {
/** 判断设备之间是否连接 */
if (status == BluetoothGatt.GATT_SUCCESS) {
try {
byte[] mByte = bleChrc.getValue();
StringBuilder mStrBuilder = new StringBuilder(mByte.length);
/** 逐byte转换 */
for (byte mByteChar : mByte) {
mStrBuilder.append(String.format("%02x", mByteChar));
} /** end of for (byte mByteChar : mByte) */
LogUtil.info(TAG, "device chrc write data: " + mStrBuilder.toString());
} catch (Exception e) {
LogUtil.error(TAG, "device chrc write data transform error");
e.printStackTrace();
}
} /** end of if (status == BluetoothGatt.GATT_SUCCESS) */
}
在该回调函数中处理发送结果。
2. 数据接收
数据接收的方式有2种:读取和通知。读取的方式速度较慢,但结果更稳定,通知的方式相反。在实际的使用过程中多用通知的方式。下面先介绍读取的方式,读取方式需要读取的Characteristic具有读取权限:
/**
* 读权限
*/
public static final int PROPERTY_READ = 0x02;
读取的函数:
@Override
public boolean readCharacteristic(ICharacteristicBle chrBle) {
return mBleGatt.readCharacteristic((BluetoothGattCharacteristic)chrBle.getImpl());
}
读取的结果在读取的回调函数获得:
/**
* 当读取characteristics得到结果时回调
*
* @param GATT客户端连接, 被{@link BluetoothGatt#readCharacteristic}调用
* @param bleChrc 从相关设备读取的characteristics值
* @param status 读取操作的结果, 如果读取操作成功时返回{@link BluetoothGatt#GATT_SUCCESS}
*/
public void onCharacteristicRead(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc, int status) {
/** 判断设备之间是否连接 */
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] mByte = bleChrc.getValue();
StringBuilder mStrBuilder = new StringBuilder(mByte.length);
/** 逐byte转换 */
for (byte mByteChar : mByte) {
mStrBuilder.append(String.format("%02x", mByteChar));
} /** end of for (byte mByteChar : mByte) */
LogUtil.info(TAG, "device chrc change data: " + mStrBuilder.toString());
} /** end of if (status == BluetoothGatt.GATT_SUCCESS) */
}
接下来是通知的方式,其中通知方式的设置函数即是上文的通知函数,在设置成功之后,通过通知回调函数获取结果:
/**
* 触发远程characteristics通知结果时回调
*
* @param bleGatt 与characteristics相关联的GATT客户端连接
* @param bleChrc 通知更新结果的characteristics
*/
public void onCharacteristicChanged(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc) {
byte[] mByte = bleChrc.getValue();
StringBuilder mStrBuilder = new StringBuilder(mByte.length);
/** 逐byte转换 */
for (byte mByteChar : mByte) {
mStrBuilder.append(String.format("%02x", mByteChar));
} /** end of for (byte mByteChar : mByte) */
LogUtil.info(TAG, "device chrc change data: " + mStrBuilder.toString());
}
这样就完成了BLE的通信过程。
附上两个BLE的Sample
1.Google官方BLE用例
https://github.com/googlesamples/android-BluetoothLeGatt
2.一个希腊研究无线传感器网络(WSN)的博士写的BLE开源库
https://github.com/alt236/Bluetooth-LE-Library---Android
说来有趣,我研究生的毕业论文也和WSN相关,现在在做与BLE相关的Android编程,现在看来WSN里最火的还是蓝牙吧。