如果我像下面的代码一样启用通知,为什么我们在写入特征时会收到 ERROR_GATT_WRITE_REQUEST_BUSY 错误?

问题描述 投票:0回答:1
object CHatServer{
 private fun setupGattService(): BluetoothGattService {
       //......
        val rrepCharacteristic = BluetoothGattCharacteristic(
            RREP_UUID,
            BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_NOTIFY ,
            BluetoothGattCharacteristic.PERMISSION_READ
        )
        val cccd = BluetoothGattDescriptor(
            CCCD_UUID,
            BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE
        )
        rrepCharacteristic.addDescriptor(cccd)

        service.addCharacteristic(rrepCharacteristic)
        val uuid = BluetoothGattCharacteristic(
            app?.let { UUIDManager.getStoredUUID(it.applicationContext) },
            BluetoothGattCharacteristic.PROPERTY_READ,
            BluetoothGattCharacteristic.PERMISSION_READ
        )
        service.addCharacteristic(uuid)

        return service
    }

    private class GattClientCallback : BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
       //.......


        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        @SuppressLint("MissingPermission")
        override fun onServicesDiscovered(discoveredGatt: BluetoothGatt, status: Int) {
            super.onServicesDiscovered(discoveredGatt, status)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "onServicesDiscovered: Have gatt $discoveredGatt")
                gatt = discoveredGatt
                val service = discoveredGatt.getService(SERVICE_UUID)
                if (service!=null){
                    if(service.getCharacteristic(MESSAGE_UUID)!=null){
                        messageCharacteristic = service.getCharacteristic(MESSAGE_UUID)
                    }
                    if(service.getCharacteristic(RREQ_UUID)!=null){
                        rreqCharacteristic = service.getCharacteristic(RREQ_UUID)
                    }
                    if(service.getCharacteristic(RREP_UUID)!=null){
                        rrepCharacteristic = service.getCharacteristic(RREP_UUID)
                        enableNotificationsForRrepCharacteristic(gatt, rrepCharacteristic)
                    }
                    val uuid = getUUID(service)
                    notifyConnectionSuccess(gatt!!.device,uuid)
                    Log.d(TAG, "UUID Discovered: $uuid")
                    gatt!!.requestMtu(GATT_MAX_MTU_SIZE)
                }
            }
        }


        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray
        ) {
            super.onCharacteristicChanged(gatt, characteristic, value)
            Log.d(TAG, "Received RREP: ${gatt.device}")
            val packet = deserializePacket(value)
            if (packet != null) {
                if(packet.src == appUUID.toString()){
                    Log.d(TAG, "Path Found from A to C")
                }
            }
            _rrepRequests.postValue(packet)
        }

     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     @SuppressLint("MissingPermission")
     fun enableNotificationsForRrepCharacteristic(gatt: BluetoothGatt?, rrepCharacteristic: BluetoothGattCharacteristic?) {
        // Step 1: Enable notifications locally
        val notificationEnabled = gatt?.setCharacteristicNotification(rrepCharacteristic, true) ?: false
        if (!notificationEnabled) {
            Log.w(TAG, "Failed to enable local notifications for RREP_UUID")
            return
        }

        // Step 2: Write to the CCCD to enable notifications on the peripheral
        val cccd = rrepCharacteristic?.getDescriptor(CCCD_UUID)
        if (cccd == null) {
            Log.w(TAG, "RREP_UUID characteristic does not have a CCCD")
            return
        }
        val success = gatt?.writeDescriptor(cccd,BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
        if (success != BluetoothStatusCodes.SUCCESS) {
            Log.w(TAG, "Failed to write CCCD value for enabling notifications")
        } else {
            Log.d(TAG, "Successfully requested to enable notifications for RREP_UUID")
        }
    }
}


我认为问题在于 writeDescriptor() 函数,因为我们在 GATT 操作之间仍在 onDiscoveredServices() 回调中时进行写入,这导致了 201 错误(繁忙错误)。但如果我们不能这样做,那么我们如何启用通知呢?

当我在 onServiceDiscovered() 回调中仅使用 setCharacteristicNotification() 函数时,我可以写入任何特征,但无法接收通知。因为我听说你需要描述符才能做到这一点。`

android bluetooth-lowenergy android-bluetooth gatt bluetooth-gatt
1个回答
0
投票

一般来说,您需要对所有 BLE 操作进行排队,以便在开始下一个操作之前可以完全完成一个操作。所有 BLE 库都这样做。

在您的情况下,实际上可能是 requestMTU() 方法存在问题。因为对描述符的写入尚未完成。只需调试它,看看哪个 gatt 操作给你带来了错误......

© www.soinside.com 2019 - 2024. All rights reserved.