Android ble: невозможно отправить большие данные

Я пытаюсь реализовать приложение для передачи некоторых строк между устройствами (на данный момент одно устройство действует как центральное, а другое - как периферийное), но безуспешно.

Так настроено мое периферийное устройство (сервер). Характерная сборка

fun buildCharacteristic(
    characteristicUUID: UUID,
): BluetoothGattCharacteristic {

    var properties = BluetoothGattCharacteristic.PROPERTY_READ or
                     BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or 
                     BluetoothGattCharacteristic.PROPERTY_NOTIFY

    var permission = BluetoothGattCharacteristic.PERMISSION_READ or
                     BluetoothGattCharacteristic.PERMISSION_WRITE

    var characteristic = BluetoothGattCharacteristic(
                             characteristicUUID, 
                             properties, 
                             permission
                         )

    return characteristic

}

сервисная сборка

fun buildService(
    serviceUUID: UUID,
    serviceType: Int,
    characteristics: List<BluetoothGattCharacteristic>
) {
    bluetoothGattService = BluetoothGattService(
                               serviceUUID, 
                               BluetoothGattService.SERVICE_TYPE_PRIMARY
                           )
    for (characteristic in characteristics) {
        bluetoothGattService.addCharacteristic(characteristic)
    }
}

и вот как я запускаю сервер (я опускаю реализацию обратных вызовов)

 fun startServer(
    bleAdapter: BluetoothAdapter,
    btManager: BluetoothManager,
    context: Context
) {
    bleAdvertiser = bleAdapter.bluetoothLeAdvertiser

    bleGattServer = btManager.openGattServer(context, gattServerCallback)
    bleGattServer.addService(bluetoothGattService)

    var settings = AdvertiseSettings.Builder().apply {
            setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            setConnectable(true)
            setTimeout(0)
            setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
        }

    var data = AdvertiseData.Builder().apply {
            setIncludeDeviceName(true)
    }

    bleAdvertiser.startAdvertising(settings.build(), data.build(), advertiseCallback)
}

На центральной (клиентской) стороне при срабатывании onScanResult я пытаюсь подключиться к устройству:

fun connectToDevice(device: BluetoothDevice) {
    device.connectGatt(
        context,
        false,
        createGattCallback()
    )
}

где createGattCallback () - функция, возвращающая объект BluetoothGattCallback. Внутри этого обратного вызова, когда вызывается onConnectionStateChange, я вызываю обнаружение службы, а при обнаружении службы я пытаюсь записать данные на периферийное устройство.

override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
    super.onServicesDiscovered(gatt, status)
    if (gatt?.services != null) {
        var serviceFound = false
        for (service in gatt.services) {
            if (service.uuid == Consts.SERVICE_UUID) {
                serviceFound = true
                var bluetoothGattCharacteristic =    service.getCharacteristic(Consts.CHARACTERISTIC_UUID)

                writeCharacteristic(
                    gatt, 
                    bluetoothGattCharacteristic
                )

             }
         }
         if (!serviceFound) {
             gatt.disconnect()
         }
     }
}


fun writeCharacteristic(
    gatt: BluetoothGatt, 
    characteristic: BluetoothGattCharacteristic
) {

    var toSendString = "A random string for testing purpose only"
    var toSendByteArray = toSendString.toByteArray(Charsets.UTF_8)

    val chunkSize = 18
    val numberOfPackets = ceil(
        (toSendByteArray.size).toDouble() / chunkSize.toDouble()
    )

    for (i in 0 until numberOfPackets.toInt()) {
        var startIndex = i * chunkSize
        var endIndex = if (startIndex + chunkSize <= toSendByteArray.size) {
            startIndex + chunkSize
        } else {
            toSendByteArray.size
        }

        var packet = toSendByteArray.copyOfRange(startIndex, endIndex)
        characteristic.value = packet
        gatt.writeCharacteristic(characteristic)
        Thread.sleep(250)
    }
}

Кажется, мой код не работает, на периферии я получаю не всю строку, а только первые 18 байтов. Где я не прав?


person giozh    schedule 27.08.2019    source источник


Ответы (1)


Вам нужно дождаться onCharacteristicWrite, прежде чем вы сможете отправить следующее значение. См. Android BLE BluetoothGatt.writeDescriptor () иногда возвращает false. И твой сон ничего не решит.

person Emil    schedule 28.08.2019
comment
Да, после ночи тестов (и кофе) я заметил, что: D поэтому, когда срабатывает центральный onCharacteristicWrite, я отправляю следующий пакет - person giozh; 28.08.2019