Уведомление о настройке конечного автомата RxAndroidBle создает бесконечный цикл onDoNext - PullRequest
0 голосов
/ 26 декабря 2018

В настоящее время я пытаюсь провести рефакторинг моего исходного кода для использования библиотеки RxAndroidBle.

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

Моя реализация уведомления об установке выглядит следующим образом:

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, и метод setNotificationOn никогда не завершается.Я думал, doOnNext вызывается только один раз при успешной настройке уведомлений !?(Исключение BleConflictingNotificationAlreadySetException никогда не генерируется, как и другие исключения!?)

Как я могу повторно настроить уведомление для одной и той же характеристики?

Есть ли лучший способ создать конечный автомат с помощью RxAndroidBle / RxJava2?(Мне нужно вызывать различные операции Bluetooth)

Здесь вы найдете мою полную реализацию

Редактировать:

Однако, если быпопробуйте снова подписаться на .setupNotification () для той же характеристики, что оба подписчика будут использовать одно и то же уведомление.

Спасибо за объяснение, поэтому doOnNext() больше не вызывается, потому что, если я подпишусь на setupNotification() снова уведомление уже успешно выполнено.

Можно ли проверить, настроено ли уже уведомление (чтобы я мог пропустить этот шаг, чтобы перейти к следующему состоянию машины)?

почему ваш API выглядит так или чего именно вы хотите достичь

Я хочу добиться того, чтобы связь Bluetooth через RxAndroidBle была абстрагирована, чтобы подкласс class BluetoothCommunication мог просто использоватьСпособы:

protected void writeBytes(UUID characteristic, byte[] bytes)
protected void readBytes(UUID characteristic)
protected void setIndicationOn(UUID characteristic)
protected void setNotificationOn(UUID characteristic)
/*  Method is triggered if a Bluetooth data is read from a device. */
protected void onBluetoothRead(UUID characteristic, byte[] value) {}
/* Method is triggered if a Bluetooth data from a device is notified */
protected void onBluetoothNotify(UUID characteristic, byte[] value) {}

для настройки последовательности связи Bluetooth.Связь / последовательность / алгоритм Bluetooth всегда отличаются и не могут быть параметризованы.Но это всегда последовательно.Чтобы инициализировать шкалу Bluetooth, во-первых, мне нужно настроить уведомления A, а затем B. Во-вторых, мне нужно отправить команду C, после чего я получу один или несколько уведомлений, после чего мне придется отправить команду B и так далее.Я поддерживаю множество шкал Bluetooth от разных поставщиков, количество команд / уведомлений о настройке и алгоритм всегда различны.

Здесь вы можете увидеть подклассы с их различным алгоритмом здесь

По моему опыту, RxJava2 не нуждается в дополнительном автомате состояний, поскольку это уже библиотека, которая обрабатывает состояние

Как я могу абстрагировать состояние дескриптора библиотеки для подклассов?

1 Ответ

0 голосов
/ 04 января 2019

Я думал, что doOnNext вызывается только один раз при успешной настройке уведомлений!?

В вашем случае это .doOnNext() будет вызываться для каждой успешной настройки уведомлений после установления соединения.Если по какой-либо причине соединение будет разорвано, оператор .retry() перепишется на connectionObservable, что может запустить новое соединение, которое вызовет новую настройку уведомлений.

Вывод: ваш .doOnNext() может быть вызванBT_RETRY_TIMES_ON_ERROR раз для каждого .subscribe()

Как я могу повторно настроить уведомление на одну и ту же характеристику?

Уведомление активно, пока .setupNotification()подписан, и нет необходимости настраивать его снова.Однако, если попытаться снова подписаться на .setupNotification() для той же характеристики, оба подписчика будут использовать одно и то же уведомление.В вашем примере уведомление будет активно до тех пор, пока не будет удалено compositeDisposable или не будет разорвано соединение (в этом случае новое соединение будет устанавливаться до BT_RETRY_TIMES_ON_ERROR раз для каждой подписки, как указано выше).

Есть ли лучший способ создать конечный автомат с помощью RxAndroidBle / RxJava2?(Мне нужно вызывать различные операции Bluetooth по очереди)

RxJava2 позволяет создавать преобразования состояний и планировать подписку на определенные Observable различными способами (в том числе и последовательными), например

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

Существуют и другие операторы, которые делают процессы также последовательными.

Более подходящий вопрос - почему ваш API выглядит так или чего именно вы хотите достичь, например,

  • Это так?соответствовать указанному внешнему API?
  • Управляется ли процесс внешним объектом?
  • Можно ли его упростить на внешнем уровне API (т. е. одним методом, таким как .getMeasurementData(device, callbackForResult))?
  • Параметризован ли процесс связи Bluetooth или алгоритм всегда один и тот же?

По моему опыту, RxJava2 не нуждается в дополнительном автомате состояний, поскольку он уже является библиотекой, которая обрабатывает состояние.,Как только требования известны, можно смоделировать цепочку операторов RxJava2 так, чтобы она выполняла именно то, что нужно.

Можно ли проверить, настроено ли уже уведомление (чтобы яможете пропустить этот шаг, чтобы перейти к следующему состоянию машины)?

Нет, проверить это невозможно, однако вызывающий абонент знает, был ли он уже установлен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...