簡體   English   中英

如何使用RxAndroidBLE從GATT服務器讀取塊中的BLE GATT特征

[英]How to Read BLE GATT characterstics in chunks form GATT server using RxAndroidBLE

我正在使用RxAndroidBle庫來處理BLE連接以及從我的android gatt客戶端應用讀取/寫入GATT服務器。 我遵循了github提供的示例應用程序。

我面臨的問題是我的GATT服務器在Intel Edison上運行,並且僅支持80的MTU大小。它以塊的形式發送數據,我應該多次讀取特征值,直到遇到特殊字符,例如`` /結束' 。 我嘗試了“自定義讀取”操作示例,該示例應該每250毫秒讀取5次。

private static class CustomReadOperation implements RxBleRadioOperationCustom<byte[]> {

    private RxBleConnection connection;
    private UUID characteristicUuid;

    CustomReadOperation(RxBleConnection connection, UUID characteristicUuid) {
        this.connection = connection;
        this.characteristicUuid = characteristicUuid;
    }

    /**
     * Reads a characteristic 5 times with a 250ms delay between each. This is easily achieve without
     * a custom operation. The gain here is that only one operation goes into the RxBleRadio queue
     * eliminating the overhead of going on & out of the operation queue.
     */
    @NonNull
    @Override
    public Observable<byte[]> asObservable(BluetoothGatt bluetoothGatt,
                                           RxBleGattCallback rxBleGattCallback,
                                           Scheduler scheduler) throws Throwable {
        return connection.getCharacteristic(characteristicUuid)
                .flatMap(characteristic -> readAndObserve(characteristic, bluetoothGatt, rxBleGattCallback))
                .subscribeOn(scheduler)
                .takeFirst(readResponseForMatchingCharacteristic())
                .map(byteAssociation -> byteAssociation.second)
                .repeatWhen(notificationHandler -> notificationHandler.take(5).delay(250, TimeUnit.MILLISECONDS));
    }

    @NonNull
    private Observable<ByteAssociation<UUID>> readAndObserve(BluetoothGattCharacteristic characteristic,
                                                             BluetoothGatt bluetoothGatt,
                                                             RxBleGattCallback rxBleGattCallback) {
        Observable<ByteAssociation<UUID>> onCharacteristicRead = rxBleGattCallback.getOnCharacteristicRead();

        return Observable.create(emitter -> {
            Subscription subscription = onCharacteristicRead.subscribe(emitter);
            emitter.setCancellation(subscription::unsubscribe);

            try {
                final boolean success = bluetoothGatt.readCharacteristic(characteristic);
                if (!success) {
                    throw new BleGattCannotStartException(bluetoothGatt, BleGattOperationType.CHARACTERISTIC_READ);
                }
            } catch (Throwable throwable) {
                emitter.onError(throwable);
            }
        }, Emitter.BackpressureMode.BUFFER);
    }

    private Func1<ByteAssociation<UUID>, Boolean> readResponseForMatchingCharacteristic() {
        return uuidByteAssociation -> uuidByteAssociation.first.equals(characteristicUuid);
    }
}

我這樣稱呼它

public void customRead()
{
    if (isConnected()) {
        connectionObservable
                .flatMap(rxBleConnection -> rxBleConnection.queue(new CustomReadOperation(rxBleConnection, UUID_READ_CHARACTERISTIC)))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> {
                    configureMvpView.showList(bytes);
                }, this::onRunCustomFailure);
    }
}

而且我沒有使用此代碼從服務器獲取任何數據。 但是,如果我嘗試這樣的簡單讀取操作

public void readInfo() {

    if (isConnected()) {
        connectionObservable
                .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(UUID_READ_CHARACTERISTIC))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> {
                    // parse data
                    configureMvpView.showWifiList(bytes);

                }, this::onReadFailure);
    }

}

我得到了第一批數據,但是我需要讀取其余數據。
我對RxJava不太了解。 因此,可能有一種簡單的方法來執行此操作,但是任何建議或幫助都會很好。

這是我的prepareConnectionObservable

private Observable<RxBleConnection> prepareConnectionObservable() {
    return bleDevice
            .establishConnection(false)
            .takeUntil(disconnectTriggerSubject)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnUnsubscribe(this::clearSubscription)
            .compose(this.bindToLifecycle())
            .compose(new ConnectionSharingAdapter());


}

我打電話

 connectionObservable.subscribe(this::onConnectionReceived, this::onConnectionFailure);

和onConnectionReceived我叫CustomRead。

您沒有顯示如何創建connectionObservable ,並且我不知道在執行上述代碼之前對該連接是否進行了其他操作。

我的猜測是,如果您查看應用程序的日志,您會看到無線電處理隊列在連接后的第一個操作中開始執行CustomReadOperation 在自定義操作中,您正在調用RxBleConnection.getCharacteristic(UUID) ,該嘗試嘗試執行.discoverServices() (在無線電隊列上安排RxBleRadioOperationDiscoverServices )。 問題在於,無線電隊列已經在執行CustomReadOperation並且在完成之前不會發現服務。

還有就是為什么一個原因RxBleConnection沒有傳遞到RxBleRadioOperationCustom.asObservable() -大部分的功能將不會在那個時候工作。

您可以做的是在安排CustomReadOperation之前執行RxBleConnection.discoverServices()並在構造函數中傳遞從RxBleDeviceServices檢索到的BluetoothGattCharacteristic 所以不要這樣:

public void customRead()
{
    if (isConnected()) {
        connectionObservable
                .flatMap(rxBleConnection -> rxBleConnection.queue(new CustomReadOperation(rxBleConnection, UUID_READ_CHARACTERISTIC)))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> {
                    configureMvpView.showList(bytes);
                }, this::onRunCustomFailure);
    }
}

您將有類似以下內容:

public void customRead()
{
    if (isConnected()) {
        connectionObservable
                .flatMap(RxBleConnection::discoverServices, (rxBleConnection, services) -> 
                    services.getCharacteristic(UUID_READ_CHARACTERISTIC)
                        .flatMap(characteristic -> rxBleConnection.queue(new CustomReadOperation(characteristic)))
                )
                .flatMap(observable -> observable)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> {
                    configureMvpView.showList(bytes);
                }, this::onRunCustomFailure);
    }
}

編輯(說明):

而且CustomReadOperation的構造函數應如下所示:

CustomReadOperation(BluetoothGattCharacteristic characteristic) {
    this.characteristic = characteristic;
}

因此,您不必在CustomReadOperation內部使用this.rxBleConnection.getCharacteristic(UUID)並直接使用bluetoothGatt.readCharacteristic(this.characteristic)

編輯2:更改這兩行:

    return connection.getCharacteristic(characteristicUuid)
            .flatMap(characteristic -> readAndObserve(characteristic, bluetoothGatt, rxBleGattCallback))

對此(其余部分相同):

    return readAndObserve(this.characteristic, bluetoothGatt, rxBleGattCallback)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM