使用RxAndroidBle(rxJava)将命令列表发送到设备

时间:2016-07-07 16:20:17

标签: android rx-java rx-android rxandroidble

我正在尝试通过rxJava向设备发送命令列表。这是我的代码:

public void startWriteCommucation(final ArrayList<byte[]> b) {
    if (isConnected()){
            connectionObservable
                    .flatMap(new Func1<RxBleConnection, Observable<Observable<byte[]>>>() {
                        @Override
                        public Observable<Observable<byte[]>> call(final RxBleConnection rxBleConnection) {
                            final List<Observable<byte[]>> list = new ArrayList<>();
                            for (byte[] bytes: b){
                                Log.e("Observer", Arrays.toString(bytes));
                                list.add(rxBleConnection
                                        .writeCharacteristic(BleDevice.characteristicWrite, bytes));
                            }
                            return Observable.from(list);
                        }
                    })
                    .concatMap(new Func1<Observable<byte[]>, Observable<byte[]>>() {
                        @Override
                        public Observable<byte[]> call(Observable<byte[]> observable) {
                            return observable;
                        }
                    })
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<byte[]>() {
                        @Override
                        public void call(byte[] bytes) {
                            view.setTextStatus("Write success");
                            Log.e("Subscriber", Arrays.toString(bytes));
                        }
                    });
        }
}

它有效,然后我点击一次按钮。例如,我的clikc方法:

 public void onClick(){
        ArrayList<byte[]> listCmd = new ArrayList<>();
        listCmd.add(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
        listCmd.add(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        startWriteCommucation(listCmd);
}

我在LogCat中的日志:

E/Observer: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
E/Observer: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

E/Subscriber: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
E/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

但是当我使用快速双击按钮时会出现问题。然后第一次点击observable仍然有效,我再次点击再次调用startWriteCommunication方法。在此之后我的日志看起来如此:

 E/Observer: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 E/Observer: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 E/Observer: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 E/Observer: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

 E/Subscriber: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 E/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 E/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 E/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

主要问题是他们没有按顺序,我的设备工作不正确。你能帮忙寻找一个问题吗?

1 个答案:

答案 0 :(得分:2)

问题是RxAndroidBle库错误(使得响应与请求不匹配)并在两个有状态的通信流之间共享连接(需要按顺序进行两次写入而不进行任何通信)。

错误:应该写入BluetoothGattCharacteristic的值(byte [])设置得太早。如果有两个并行写入器用于相同的特性 - 其中一个可能会覆盖由于竞争条件而由另一个设置的字节[]。我已经修复了现在正在进行代码审查的库,并且应该在不久的将来应用于SNAPSHOT版本。

通过更改,输出将如下所示:

D/Observer: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D/Observer: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
D/Observer: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D/Observer: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

D/Subscriber: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D/Subscriber: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
D/Subscriber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

可能的解决方案

如果用户不想快速点按两次按钮,那么如果你对两次触发流量不感兴趣 - 你可以创建一个可共享的流程:

Observable<byte[]> theSharedFlow = rxBleConnection
  .writeCharacteristic(uuid, data1)
  .flatMap(writtenBytes -> rxBleConnection.writeCharacteristic(uuid, data2))
  .share()

多次订阅时,只会执行一次,直到完成为止。在上面的代码片段中,第二个writeCharacteristic()将在第一个flatMap()将发出写入的字节后订阅(并排队等待通信)。

如果应用程序是为了在共享连接时在任意时间按顺序发送任意命令集,则应用程序需要确保先前的设置已完成。

我希望我已经回答了你的问题。如果您提供有关用例的更多信息,我会尝试改进我的答案。

最好的问候

编辑:

替代解决方案:

要保留订单,所有Observable都需要订阅才能到达。 Observable的合约是Observable(如果它很冷)直到订阅才执行。当使用connectionObservable .flatMap(rxBleConnection -> { Observable<byte[]> mergedObservable = null; for (byte[] bytes : b) { Log.d("Observer", Arrays.toString(bytes)); final Observable<byte[]> writeObservable = rxBleConnection .writeCharacteristic(uuid, bytes); if (mergedObservable == null) { mergedObservable = writeObservable; } else { // merging two Observables to be subscribed at the same time when subscribed mergedObservable = mergedObservable.mergeWith(writeObservable); } } return mergedObservable; }) // removed .concatMap() .observeOn(AndroidSchedulers.mainThread()) .subscribe( bytes -> Log.d("Subscriber", Arrays.toString(bytes)), throwable -> Log.e("Subscriber", "error", throwable) ); 时,第二个Observable会在第一个Observable发出后订阅。

要使两个写入按顺序传输,必须以相同的顺序进行订阅,这样流程可能如下所示:

X.o

RxJava显然有更多方法可以实现相同的行为,但这不是这个问题的一部分。

相关问题