Android BLE: уведомление от нескольких характеристик c под одной услугой - PullRequest
0 голосов
/ 24 января 2020

ПРОБЛЕМА

Я пытаюсь получить уведомление от более чем одного признака c через BLE, я нашел какое-то решение для inte rnet, которое мне нужно подождать пока не завершится обратный вызов onDescriptorWrite() (что, я думаю, я здесь сделал?), но я не могу сделать onDescriptorWrite() во второй раз для уведомления FILE_TX (код там). Все это выполняется при onServicesDiscovery() - когда я установил соединение BLE.

Есть ли что-то, что я здесь делаю неправильно?

Вы можете иметь только одну выдающуюся операцию Гатта в время. В этом случае вы делаете два вызова writeDescriptor, прежде чем дождаться завершения первого. Вы должны ждать https://developer.android.com/reference/android/bluetooth/BluetoothGattCallback.html#onDescriptorWrite (android .bluetooth.BluetoothGatt , android .bluetooth.BluetoothGattDescriptor, int), пока не сможете отправить следующий.

Это это лучший ответ, который я могу найти, но как вы можете сказать, что onDescriptorWrite был завершен?

Я попытался поместить Thread.sleep(500) между, чтобы обойти, но я тоже не работаю.

Под onServicesDiscovery - gattCallback

for (gattCharacteristic in gattCharacteristics) {
                        uuid = gattCharacteristic.uuid
                        // // Log.d("GATT", "$uuid")

                        if (gattCharacteristic.uuid.equals(UUID_CHARACTERISTIC_READ_FILE_TX)) {
                            gatt.setCharacteristicNotification(gattCharacteristic, true)
                            val descriptorfile: BluetoothGattDescriptor = gattCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID) ?: error("Required Client Characteristic Configuration not found")
                            descriptorfile.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
                            isSuccess = gatt.writeDescriptor(descriptorfile)
                            Log.d("tagfile", "FILE_TX Successful ? " + isSuccess)
                            gattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE)
                            Log.d("tagfile", "Found Transparent service File Tx characteristics")
                        }

                        else if (gattCharacteristic.uuid.equals(UUID_CHARACTERISTIC_TX)) {
                            gatt.setCharacteristicNotification(gattCharacteristic, true)
                            val descriptor: BluetoothGattDescriptor = gattCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID) ?: error("Required Client Characteristic Configuration not found")
                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
                            isSuccess = gatt.writeDescriptor(descriptor)
                            Log.d("tagfile", "TX Successful ? " + isSuccess)
                            gattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE)
                            Log.d("tagfile", "Found Transparent service Tx characteristics")
                        }

                        if (gattCharacteristic.uuid.equals(UUID_CHARACTERISTIC_RX)) {
                            gattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE)
                            Log.d("tagfile", "Found Transparent service Rx characteristics")
                        }

                        else if (gattCharacteristic.uuid.equals(UUID_CHARACTERISTIC_READ_FILE_RX)) {
                            gattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE)
                            Log.d("tagfile", "Found Transparent service File Rx characteristics")
                        }
}

Под onDescriptorWrite - gattCallback

override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {

            Log.d("tagfile", "Status of gatt : " + status + "       GATT FAILURE : " + BluetoothGatt.GATT_FAILURE)
        }

РЕЗУЛЬТАТЫ:

2020-01-24 09:41:51.359 8565-8587/com.example.ricco_ble D/tagfile: TX Successful ? true
2020-01-24 09:41:53.359 8565-8587/com.example.ricco_ble D/tagfile: Found Transparent service Tx characteristics
2020-01-24 09:41:53.360 8565-8587/com.example.ricco_ble D/tagfile: Found Transparent service Rx characteristics
2020-01-24 09:41:53.371 8565-8587/com.example.ricco_ble D/tagfile: FILE_TX Successful ? false
2020-01-24 09:41:53.371 8565-8587/com.example.ricco_ble D/tagfile: Found Transparent service File Tx characteristics
2020-01-24 09:41:53.372 8565-8587/com.example.ricco_ble D/tagfile: Found Transparent service File Rx characteristics
2020-01-24 09:41:53.424 8565-8587/com.example.ricco_ble D/tagfile: Status of gatt : 0       GATT FAILURE : 257

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Я считаю полезным следовать двум пунктам при работе со стеком Android BLE.

  1. В любых обратных вызовах Gatt выполняется только копирование результатов, а schedule - следующая задача для выполнения ( не для выполнения). Так что функция обратного вызова может быть выпущена как можно скорее.
  2. Выполнять операцию последовательно. Не выполняйте следующую операцию, пока не получите обратный вызов от предыдущей операции.

Из вышеприведенного кода вы вкладываете дескрипторы записи в обратный вызов serviceDiscovery. Кроме того, вы пишете следующий дескриптор до получения предыдущего обратного вызова.

Чтобы иметь более стабильную / предсказуемую производительность, вы можете преобразовать свой код в нечто вроде

BluetoothGattCallback(){
    onServiceDiscovery(gatt){
        MainHandler.post((gatt)->setFirstNotification(gatt)) //do the scheduling, not direct execution here.
    }

    onDescriptorWrite(gatt){
         if(the first descriptor write success) {
        MainHandler.post((gatt)->setSecondNotification(gatt)) //do the scheduling
         } else if (the second descriptor write success) {
        MainHandler.post((gatt)->otherLogic(gatt)) //do the scheduling
        }
    } 
}

fun setFirstNotification(gatt){
    //your code to set descriptor value
}


fun setSecondNotification(gatt){
    //your code to set descriptor value
}

fun otherLogic(gatt){
    //your other code
}

Это примерно идея как бы вы подошли к этому, если вы хотите создать свое коммуникационное приложение напрямую со стеком Android.

1 голос
/ 06 февраля 2020

Вместо того, чтобы пытаться собрать систему самостоятельно, я рекомендую использовать Android BLE Library от Nordi c SemiConductor. Большую половину 4 месяца я провел, пытаясь сделать это сам. Эта библиотека позволяет вам выполнять вызовы, используя asyn c с определенными обратными вызовами, и вам не нужно беспокоиться о подобных проблемах.

...