蓝牙技术联盟在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里最火的还是蓝牙吧。