RxAndroidBle状态机设置通知在onDoNext上产生无限循环

时间:2018-12-25 21:23:21

标签: java android bluetooth rxandroidble

当前,我正在尝试重构my source code以使用RxAndroidBle库。

我实现了一个状态机,该状态机在每次蓝牙成功操作(通知,写入,读取等)下调用下一个状态。只要蓝牙设备正在运行,就应该始终建立rxBleConnection。

我的设置通知实现如下:

Foos

如果我只在通知中设置了该特性,那么它起作用了,但是如果发生错误或尝试再次设置它,我将陷入doOnNext的无限循环中,并且setNotificationOn方法永远不会终止。我认为doOnNext在成功的通知设置中仅被调用一次! (永远不会引发BleConflictingNotificationAlreadySetException或其他异常!?)

如何重复设置相同特征的通知?

是否有更好的方法用RxAndroidBle / RxJava2创建状态机? (我需要依次调用各种蓝牙操作)

您会发现我的完整实现here

编辑:

  

但是,如果有人尝试再次订阅.setupNotification()   对于相同的特征,两个订户将共享相同的   通知。

感谢您的解释,因此不会再次调用protected void setNotificationOn(UUID characteristic) { if (isConnected()) { final Disposable disposable = connectionObservable .flatMap(rxBleConnection -> rxBleConnection.setupNotification(characteristic)) .doOnNext(notificationObservable -> { Timber.d("Successful set notification on for %s", BluetoothGattUuid.prettyPrint(characteristic)); nextMachineStateStep(); } ) .flatMap(notificationObservable -> notificationObservable) .observeOn(AndroidSchedulers.mainThread()) .retry(BT_RETRY_TIMES_ON_ERROR) .subscribe( bytes -> { onBluetoothNotify(characteristic, bytes); Timber.d("onCharacteristicChanged %s: %s", BluetoothGattUuid.prettyPrint(characteristic), byteInHex(bytes)); }, throwable -> onError(throwable) ); compositeDisposable.add(disposable); } } ,因为如果我再次订阅doOnNext(),则通知已成功设置。

是否可以检查通知是否已设置(以便我可以跳过此步骤以转到我的下一个计算机状态)?

  

您的API为什么看起来像这样或您到底想要实现什么

我想实现通过RxAndroidBle的蓝牙通信是抽象的,以便setupNotification()的子类可以使用以下方法:

class BluetoothCommunication

设置蓝牙通信顺序。蓝牙通信/序列/算法始终是不同的,并且无法设置参数。但这总是顺序的。要初始化蓝牙规模,首先需要先设置A,然后再设置B。其次,我必须先发送命令C,然后再发送命令B,这样我将收到一个或多个通知呼叫,依此类推。我支持来自不同供应商的许多蓝牙秤,命令/设置通知和算法的数量总是不同的。

您可以看到带有各种算法here的子类

  

以我的经验,RxJava2不需要具有其他状态   机器,因为它已经是一个处理状态的库

如何抽象子类的库句柄状态?

1 个答案:

答案 0 :(得分:0)

  

我认为doOnNext仅在成功设置通知后被调用一次!?

在您的情况下,建立连接后,每次成功设置通知都会调用此.doOnNext()。如果连接由于任何原因而中断,.retry()操作员将重新订阅connectionObservable,这可能会启动新的连接,从而触发新的通知设置。

结论:每个.doOnNext()的{​​{1}}可能被调用BT_RETRY_TIMES_ON_ERROR

  

如何重复设置相同特征的通知?

只要订阅了.subscribe(),通知就处于活动状态,而无需重新设置。但是,如果一个用户尝试再次订阅.setupNotification()以获得相同的特征,则两个订阅者将共享相同的通知。在您的示例中,通知将一直有效,直到.setupNotification()被处置或连接断开(在这种情况下,如上所述,每个订阅最多可以建立compositeDisposable次新连接)。 / p>

  

是否有更好的方法用RxAndroidBle / RxJava2创建状态机? (我需要依次调用各种蓝牙操作)

RxJava2允许以许多不同的方式(也包括顺序的)构建状态转换并安排订阅特定的BT_RETRY_TIMES_ON_ERROR,例如

Observable

还有其他一些运算符也可以使进程按顺序进行。

一个更合适的问题是,为什么您的API看起来像这样,或者您究竟想要实现什么,例如

  • 是否符合指定的外部API?
  • 该流程是否由外部实体控制?
  • 能否在外部API级别上进行简化(即像Disposable disposable = Observable.concat(Arrays.asList( Observable.just("start").doOnSubscribe(disposable1 -> Log.d("Subscribe", "start")), Observable.just("0").delay(3, TimeUnit.SECONDS).doOnSubscribe(disposable1 -> Log.d("Subscribe", "0")), Observable.just("1").delay(2, TimeUnit.SECONDS).doOnSubscribe(disposable1 -> Log.d("Subscribe", "1")), Observable.just("2").delay(1, TimeUnit.SECONDS).doOnSubscribe(disposable1 -> Log.d("Subscribe", "2")), Observable.just("end").doOnSubscribe(disposable1 -> Log.d("Subscribe", "end")) )) .subscribe(s -> Log.d("Result", s)); // 2019-01-04 12:45:13.364 31887-31887/ D/Subscribe: start // 2019-01-04 12:45:13.364 31887-31887/ D/Result: start // 2019-01-04 12:45:13.364 31887-31887/ D/Subscribe: 0 // 2019-01-04 12:45:16.366 31887-32529/ D/Result: 0 // 2019-01-04 12:45:16.367 31887-32529/ D/Subscribe: 1 // 2019-01-04 12:45:18.367 31887-32535/ D/Result: 1 // 2019-01-04 12:45:18.368 31887-32535/ D/Subscribe: 2 // 2019-01-04 12:45:19.369 31887-32537/ D/Result: 2 // 2019-01-04 12:45:19.371 31887-32537/ D/Subscribe: end // 2019-01-04 12:45:19.372 31887-32537/ D/Result: end 这样的单一方法)?
  • 蓝牙通信过程是可设置的还是算法始终相同?

根据我的经验,RxJava2不需要具有其他状态机,因为它已经是处理状态的库。一旦了解了需求,就可以按照完全满足需求的方式对RxJava2操作员链进行建模。

  

是否可以检查通知是否已设置(以便我可以跳过此步骤以转到我的下一个计算机状态)?

否,无法检查它-呼叫者知道它是否已经设置。