如何在 android 应用程序上从 BLE 设备接收数据
How to receive data from BLE device on android app
我是 android studio 和创建应用程序的新手,这是我正在做的项目的一部分。
我能够连接到蓝牙设备并能够将其置于状态为 GATT_SUCCESS 的 onServicesDiscovered 函数中。
我不知道从这里去哪里,因为我没有从设备接收数据。我是否需要广播更新或广播接收器,或者下面的代码是否正常但需要修复?
如果有人能提供帮助那就太好了!
@Override
//New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i("onServicesDiscovered", "Status: " + status);
if(status == GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for(BluetoothGattService service : services){
if(!service.getUuid().equals("49535343-FE7D-4AE5-8FA9-9FAFD205E455"))
continue;
List<BluetoothGattCharacteristic> gattCharacteristics = service.getCharacteristics();
// Loops through available Characteristics
for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){
if(!gattCharacteristic.getUuid().equals("49535343-1E4D-4BD9-BA61-23C647249616"))
continue;
final int charaProp = gattCharacteristic.getProperties();
if((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0){
setCharacteristicNotification(gattCharacteristic, true);
Log.w(TAG, "Working");
}else{
Log.w(TAG, "Characteristic does not support notify");
}
}
}
}else{
Log.w(TAG, "onServicesDiscovered receive: " + status);
}
//List<BluetoothGattService> services = gatt.getServices();
//Log.i("onServicesDiscovered", services.toString());
//gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));
}
@Override
//Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
if(status != GATT_SUCCESS){
Log.e(TAG, String.format(Locale.ENGLISH, "ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));
completedCommand();
return;
}
//gatt.disconnect();
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == GATT_SUCCESS) {
if (descriptor.getCharacteristic().getUuid().equals(UUID_TARGET_CHARACTERISTIC)) {
Log.i(TAG, "Successfully subscribed");
}
byte[] data = {1, 1};
BluetoothGattService Service = mGatt.getService(UUID_TARGET_SERVICE);
BluetoothGattCharacteristic charac = Service.getCharacteristic(UUID_TARGET_CHARACTERISTIC);
charac.setValue(data);
mGatt.readCharacteristic(charac);
} else {
Log.e(TAG, "Error subscribing");
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] value = characteristic.getValue();
Log.i("BLE", "receive value ----------------------------");
for (int i = 0; i < value.length; i++) {
Log.w("BLE", "character_value = " + value[i]);
}
//processData(characteristic.getValue());
}
};
public boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {
if(mGatt == null) {
Log.e(TAG, "ERROR: Gatt is 'null', ignoring read request");
return false;
}
// Check if characteristic is valid
if(characteristic == null) {
Log.e(TAG, "ERROR: Characteristic is 'null', ignoring read request");
return false;
}
// Check if this characteristic actually has READ property
if((characteristic.getProperties() & PROPERTY_READ) == 0 ) {
Log.e(TAG, "ERROR: Characteristic cannot be read");
return false;
}
// Enqueue the read command now that all checks have been passed
boolean result = commandQueue.add(new Runnable() {
@Override
public void run() {
if(!mGatt.readCharacteristic(characteristic)) {
Log.e(TAG, String.format("ERROR: readCharacteristic failed for characteristic: %s", characteristic.getUuid()));
completedCommand();
} else {
Log.d(TAG, String.format("reading characteristic <%s>", characteristic.getUuid()));
nrTries++;
}
}
});
if(result) {
nextCommand();
} else {
Log.e(TAG, "ERROR: Could not enqueue read characteristic command");
}
return result;
}
private void nextCommand() {
// If there is still a command being executed then bail out
if(commandQueueBusy) {
return;
}
// Check if we still have a valid gatt object
if (mGatt == null) {
Log.e(TAG, String.format("ERROR: GATT is 'null' for peripheral '%s', clearing command queue", device.getAddress()));
commandQueue.clear();
commandQueueBusy = false;
return;
}
// Execute the next command in the queue
if (commandQueue.size() > 0) {
final Runnable bluetoothCommand = commandQueue.peek();
commandQueueBusy = true;
nrTries = 0;
mHandler.post(new Runnable() {
@Override
public void run() {
try {
bluetoothCommand.run();
} catch (Exception ex) {
Log.e(TAG, String.format("ERROR: Command exception for device '%s'", device.getName()), ex);
}
}
});
}
}
private void retryCommand() {
commandQueueBusy = false;
Runnable currentCommand = commandQueue.peek();
if(currentCommand != null) {
if (nrTries >= MAX_TRIES) {
// Max retries reached, give up on this one and proceed
Log.v(TAG, "Max number of tries reached");
commandQueue.poll();
} else {
//isRetrying = true;
}
}
nextCommand();
}
private void completedCommand() {
commandQueueBusy = false;
//isRetrying = false;
commandQueue.poll();
nextCommand();
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (bluetoothAdapter == null || mGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(BTMODULEUUID);
descriptor.setValue(enabled?BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE :BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
您似乎想打开通知以从您的 BLE 设备接收数据,并且您使用了 setCharacteristicNotification(gattCharacteristic, true);
来达到这个目的。但这还不够。它只会告诉蓝牙堆栈此特性将发送通知,但您还想在设备上订阅通知。
为此你需要所谓的 CCC 描述符并向其写入 ENABLE_NOTIFICATION_VALUE:
private final String CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";
final BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(UUID.fromString(CCC_DESCRIPTOR_UUID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
同时执行这两项操作将为该设备启用通知。看看来自 PunchTrough 的这个很棒的 Guide,了解有关使用 BLE 的更多信息。
我是 android studio 和创建应用程序的新手,这是我正在做的项目的一部分。
我能够连接到蓝牙设备并能够将其置于状态为 GATT_SUCCESS 的 onServicesDiscovered 函数中。
我不知道从这里去哪里,因为我没有从设备接收数据。我是否需要广播更新或广播接收器,或者下面的代码是否正常但需要修复?
如果有人能提供帮助那就太好了!
@Override
//New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i("onServicesDiscovered", "Status: " + status);
if(status == GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for(BluetoothGattService service : services){
if(!service.getUuid().equals("49535343-FE7D-4AE5-8FA9-9FAFD205E455"))
continue;
List<BluetoothGattCharacteristic> gattCharacteristics = service.getCharacteristics();
// Loops through available Characteristics
for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){
if(!gattCharacteristic.getUuid().equals("49535343-1E4D-4BD9-BA61-23C647249616"))
continue;
final int charaProp = gattCharacteristic.getProperties();
if((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0){
setCharacteristicNotification(gattCharacteristic, true);
Log.w(TAG, "Working");
}else{
Log.w(TAG, "Characteristic does not support notify");
}
}
}
}else{
Log.w(TAG, "onServicesDiscovered receive: " + status);
}
//List<BluetoothGattService> services = gatt.getServices();
//Log.i("onServicesDiscovered", services.toString());
//gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));
}
@Override
//Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
if(status != GATT_SUCCESS){
Log.e(TAG, String.format(Locale.ENGLISH, "ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));
completedCommand();
return;
}
//gatt.disconnect();
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == GATT_SUCCESS) {
if (descriptor.getCharacteristic().getUuid().equals(UUID_TARGET_CHARACTERISTIC)) {
Log.i(TAG, "Successfully subscribed");
}
byte[] data = {1, 1};
BluetoothGattService Service = mGatt.getService(UUID_TARGET_SERVICE);
BluetoothGattCharacteristic charac = Service.getCharacteristic(UUID_TARGET_CHARACTERISTIC);
charac.setValue(data);
mGatt.readCharacteristic(charac);
} else {
Log.e(TAG, "Error subscribing");
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] value = characteristic.getValue();
Log.i("BLE", "receive value ----------------------------");
for (int i = 0; i < value.length; i++) {
Log.w("BLE", "character_value = " + value[i]);
}
//processData(characteristic.getValue());
}
};
public boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {
if(mGatt == null) {
Log.e(TAG, "ERROR: Gatt is 'null', ignoring read request");
return false;
}
// Check if characteristic is valid
if(characteristic == null) {
Log.e(TAG, "ERROR: Characteristic is 'null', ignoring read request");
return false;
}
// Check if this characteristic actually has READ property
if((characteristic.getProperties() & PROPERTY_READ) == 0 ) {
Log.e(TAG, "ERROR: Characteristic cannot be read");
return false;
}
// Enqueue the read command now that all checks have been passed
boolean result = commandQueue.add(new Runnable() {
@Override
public void run() {
if(!mGatt.readCharacteristic(characteristic)) {
Log.e(TAG, String.format("ERROR: readCharacteristic failed for characteristic: %s", characteristic.getUuid()));
completedCommand();
} else {
Log.d(TAG, String.format("reading characteristic <%s>", characteristic.getUuid()));
nrTries++;
}
}
});
if(result) {
nextCommand();
} else {
Log.e(TAG, "ERROR: Could not enqueue read characteristic command");
}
return result;
}
private void nextCommand() {
// If there is still a command being executed then bail out
if(commandQueueBusy) {
return;
}
// Check if we still have a valid gatt object
if (mGatt == null) {
Log.e(TAG, String.format("ERROR: GATT is 'null' for peripheral '%s', clearing command queue", device.getAddress()));
commandQueue.clear();
commandQueueBusy = false;
return;
}
// Execute the next command in the queue
if (commandQueue.size() > 0) {
final Runnable bluetoothCommand = commandQueue.peek();
commandQueueBusy = true;
nrTries = 0;
mHandler.post(new Runnable() {
@Override
public void run() {
try {
bluetoothCommand.run();
} catch (Exception ex) {
Log.e(TAG, String.format("ERROR: Command exception for device '%s'", device.getName()), ex);
}
}
});
}
}
private void retryCommand() {
commandQueueBusy = false;
Runnable currentCommand = commandQueue.peek();
if(currentCommand != null) {
if (nrTries >= MAX_TRIES) {
// Max retries reached, give up on this one and proceed
Log.v(TAG, "Max number of tries reached");
commandQueue.poll();
} else {
//isRetrying = true;
}
}
nextCommand();
}
private void completedCommand() {
commandQueueBusy = false;
//isRetrying = false;
commandQueue.poll();
nextCommand();
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (bluetoothAdapter == null || mGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(BTMODULEUUID);
descriptor.setValue(enabled?BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE :BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
您似乎想打开通知以从您的 BLE 设备接收数据,并且您使用了 setCharacteristicNotification(gattCharacteristic, true);
来达到这个目的。但这还不够。它只会告诉蓝牙堆栈此特性将发送通知,但您还想在设备上订阅通知。
为此你需要所谓的 CCC 描述符并向其写入 ENABLE_NOTIFICATION_VALUE:
private final String CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";
final BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(UUID.fromString(CCC_DESCRIPTOR_UUID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
同时执行这两项操作将为该设备启用通知。看看来自 PunchTrough 的这个很棒的 Guide,了解有关使用 BLE 的更多信息。