I notice that if i write fast and continuously a characteristic value the gatt server disconnect.
I know that I have to wait until onCharacteristicWrite
callback, so that's not the problem I think.
This my queue implementation, I'm using a kotlin Channel to syncronize write and read.
private var continuation: CancellableContinuation<BluetoothGattCharacteristic>? = null
private val channel = Channel<WriteOp>(1)
private suspend fun processBluetoothWrite() {
do {
val writeOp = channel.receiveOrNull()
writeOp?.apply {
try {
suspendCancellableCoroutine<BluetoothGattCharacteristic> { cont ->
continuation = cont
characteristic.value = writeOp?.value
Log.d(TAG, "Write to ${characteristic?.uuid} value ${writeOp?.value?.toHexString()}...")
if (gatt?.writeCharacteristic(characteristic) == false) {
cont.resumeWithException(Exception("Write to ${characteristic?.uuid} fails."))
}
}
} catch (ex: Exception) {
Log.e(TAG, ex.message, ex)
}
}
} while (writeOp != null)
}
override fun onCharacteristicWrite(
gatt: BluetoothGatt?,
characteristic: BluetoothGattCharacteristic?,
status: Int
) {
Log.d(TAG, "Write to ${characteristic?.uuid} value ${characteristic?.value?.toHexString()} | ${status}")
characteristic?.apply {
if (status == BluetoothGatt.GATT_SUCCESS) {
continuation?.resume(this)
} else {
continuation?.resumeWithException(Exception("Write to ${characteristic?.uuid} value ${characteristic?.value?.toHexString()} | ${status}"))
}
}
}
I need to add a delay of about 100ms in the queue processing to avoid disconnection.
UPDATE
After setting writeType
as default, it seems that onCharacteristicWrite
is more realistic (I used to get GATT_SUCCESS even when the device stopped communicating, so I guess it was a "virtual" state), now when the device stopped communicating it didn't get the onCharacteristicWrite
callback, though after a while it is fired with status = 133.
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
What does it mean?