阻止RxAndroidBle写操作

时间:2019-02-18 21:10:35

标签: rx-java2 rxandroidble

如何使用RxAndroidBle在Android中执行阻止写入操作。仅当写入操作成功时,才应执行下一条命令。

protected void doWriteBytes(UUID characteristic, byte[] bytes) {
    final Disposable disposable = connectionObservable
            .flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
            .observeOn(AndroidSchedulers.mainThread())
            .retry(BT_RETRY_TIMES_ON_ERROR)
            .subscribe(
                    value -> {
                        Timber.d("Write characteristic %s: %s",
                                BluetoothGattUuid.prettyPrint(characteristic),
                                byteInHex(value));
                    },
                    throwable -> onError(throwable)
            );

    compositeDisposable.add(disposable);
}


protected void test() {
  // blocking write bytes
  doWriteBytes(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x35, 0x12});

  // following command should be only performed if doWriteBytes is successful executed
  foo();

  // blocking write bytes
  doWriteBytes(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x5, 0x6, 0x1});

  bar();
}

我知道订阅和onComplete,但是也可以不用这些方法吗?

背景是我想在几个不同的子类中覆盖测试方法,因此我可以执行各种doWriteBytes命令(例如ACK命令)以向蓝牙设备发送一些字节,但是我需要确保下一个命令是仅在ACK命令成功发送后才执行。

也许这更多是一个RxJava2问题,但我对此并不十分熟悉。

编辑:

感谢您的回答@Dariusz Seweryn。抱歉,我的问题可能不太清楚。我会尽量具体化。

我想像在test()中编写普通函数一样编写源代码,以抽象化RxJava2实现。唯一的不同是,应该通过RxAndroidBle完成doWriteBytes和其他蓝牙操作(通知,读取)。 我必须写给蓝牙设备的内容取决于通知字节或test()方法中的其他算法。另外,我想覆盖test()方法以为完全不同的蓝牙设备实现不同的蓝牙通信流程。顺序处理蓝牙操作始终很重要。

现在我想到了三个想法:

1)我的第一个想法是实现所有RxAndroidBle操作阻止,因此我可以将simple用于循环。

2)我的第二个想法是在运行时观察中动态地添加(concat?)到test()方法中的另一个,该方法是顺序处理的,但我总是需要以前观察中的返回值?

3)我的第三个想法是将写/通知/写操作作为一种方法组合在一起,可以在test()方法中调用它。该操作应将字节写入特征A,然后等待有关特征B的通知,对接收到的字节进行一些处理,然后再次写入特征C。 但是在添加的test()方法中,编写了什么内容或在运行期间如何动态地进行通知过程。

对于RxJava2中的问题,也许有一个优雅的解决方案,或者根本不可能?

编辑2:

我尝试实现所有这三个想法,但不幸的是我没有成功。

1)

connectionObservable
                .flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .retry(BT_RETRY_TIMES_ON_ERROR)
                .blockingSubscribe(
                        value -> {
                            Timber.d("Write characteristic %s: %s",
                                    BluetoothGattUuid.prettyPrint(characteristic),
                                    byteInHex(value));
                            processBtQueue();
                        },
                        throwable -> onError(throwable)
                );

即使成功,它总是会阻塞吗?我必须在某个地方释放它吗?另外,该方法返回void并且不再是一次性的,但是我无法处理它。

2)我正在为这个想法而苦苦挣扎。如果我不知道起始的可观察物,我应该关注哪个可观察物? connectionObserable不起作用,因为它包含RxBleConnection。第二个问题是,蓝牙操作后的值就是Java对象类!我是否每次都要投射?您是否有示例如何将蓝牙写入操作与通知蓝牙结果进行连接?

3)这个想法的问题是,我不知道如何在运行时动态地将处理部分动态添加到RxJava订阅部分之外的通知中?

我对第3号想法有一个可行的解决方案

protected Observable<byte[]> doWriteNotify(UUID characteristic, byte[] bytes, Observable<byte[]> notificationObservable) {
    Observable observable = connectionObservable
            .flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .retry(BT_RETRY_TIMES_ON_ERROR)
        .flatMap( writeBytes -> notificationObservable)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .retry(BT_RETRY_TIMES_ON_ERROR);

    compositeDisposable.add(observable.subscribe());

    return observable;
}

顺便说一句。这些问题我应该在stackoverflow上创建单独的线程吗?

如果有帮助,您可以找到我的实验源代码here

1 个答案:

答案 0 :(得分:0)

  

我知道订阅和onComplete,但是也可以不用这些方法吗?

给出:

Completable foo() { ... }

Completable bar() { ... )

一个人可以做:

Disposable testDisposable = connectionObservable
                                .flatMapCompletable(connection ->
                                    connection.writeCharacteristic(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x35, 0x12}).ignoreElement()
                                        .andThen(foo())
                                        .andThen(connection.writeCharacteristic(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x5, 0x6, 0x1}).ignoreElement())
                                        .andThen(bar())
                                )
                                .subscribe(
                                     () -> { /* completed */ },
                                     throwable -> { /* error happened */ }
                                )

使用.subscribe()结束以上内容可以控制流完成多少个连接。在上面的示例中,如果连接在第一次写入过程中过早终止,则所有后续操作(foo(),写入,bar())将根本不会发生。

编辑:

您所有的想法都可能有效-您可以尝试一下。

  

对于RxJava2中的问题,也许有一个优雅的解决方案,或者根本不可能?

如果确实需要.blocking*() / Observable / Single类,则有Completable个函数。不过请小心-由于您的应用程序引入了更多状态,因此您可能会开始遇到一些难以调试的问题,具体取决于您的实现。