RxBleConnection.setupNotification仅适用于两个特征中的第一个

时间:2016-12-22 20:34:41

标签: android rxandroidble

我很难使用RxAndroidBle找出意外行为。

问题的简短形式是我需要从特定设备的两个特征接收有序通知。在下面的示例中,我扫描SERVICE_UUID,并为CHARACTERISTIC_FOO_UUID和CHARACTERISTIC_BAR_UUID设置通知(按顺序)。我需要根据两个特征的响应做一些事情 - 在我的例子中,我只是将byte []存储在成员变量中。

我遇到的问题是第一个特征报告但不是第二个报告。如果我翻转订单,它仍然是链中第一个特征。下面,我提供调试输出,它显示两者都发生通知调用,包括低级描述符写入,但由于某种原因,第二个不报告。 (假设我订阅了Observable。)

我已经能够在没有RxAndroidBle的情况下使用它。我也有一个使用RxAndroidBle的版本可以工作但是使用ConnectionSharingAdapter和几个订阅以不同的方式设置。下面的例子是尝试采用更清洁的方法,但正如我所说的那样,似乎并没有起作用。

rxBleClient.scanBleDevices(SERVICE_UUID)
    .first()
    .flatMap(rxBleScanResult -> {
        return Observable.just(rxBleScanResult.getBleDevice());
    })
    .flatMap(rxBleDevice -> {
        return rxBleDevice.establishConnection(context, IS_AUTO_CONNECT);
    })
    .flatMap(rxBleConnection -> 
        rxBleConnection.setupNotification(CHARACTERISTIC_FOO_UUID)
        .flatMap(observable -> observable)
        .flatMap(new Func1<byte[], Observable<RxBleConnection>>() {
            @Override
            public Observable<RxBleConnection> call(final byte[] notificationBytes) {
                mFooBytes = notificationBytes;
                return Observable.just(rxBleConnection);
            }
        })
    )
    .flatMap(rxBleConnection -> 
        rxBleConnection.setupNotification(CHARACTERISTIC_BAR_UUID)
        .flatMap(observable -> observable)
        .flatMap(new Func1<byte[], Observable<RxBleConnection>>() {
            @Override
            public Observable<RxBleConnection> call(final byte[] notificationBytes) {
                mBarBytes = notificationBytes;
                return Observable.just(rxBleConnection);
            }
        })
    )

这里是RxBle调试输出---我使用&#34; CHARACTERISTIC_FOO_UUID&#34;编辑了实际的uuid。在输出中。

12-22 12:13:43.322 12074-12074/com.foo.example D/RxBle#Radio:   QUEUED RxBleRadioOperationScan(217963087)
12-22 12:13:43.322 12074-12281/com.foo.example D/RxBle#Radio:  STARTED RxBleRadioOperationScan(217963087)
12-22 12:13:43.412 12074-12281/com.foo.example D/RxBle#Radio: FINISHED RxBleRadioOperationScan(217963087)
12-22 12:13:43.682 12074-12074/com.foo.example D/RxBle#Radio:   QUEUED RxBleRadioOperationConnect(37012551)
12-22 12:13:43.682 12074-12281/com.foo.example D/RxBle#Radio:  STARTED RxBleRadioOperationConnect(37012551)
12-22 12:13:44.052 12074-12085/com.foo.example D/RxBle#BluetoothGatt: onConnectionStateChange newState=2 status=0
12-22 12:13:44.092 12074-12558/com.foo.example D/RxBle#Radio:   QUEUED RxBleRadioOperationServicesDiscover(72789039)
12-22 12:13:44.092 12074-12281/com.foo.example D/RxBle#Radio: FINISHED RxBleRadioOperationConnect(37012551)
12-22 12:13:44.092 12074-12281/com.foo.example D/RxBle#Radio:  STARTED RxBleRadioOperationServicesDiscover(72789039)
12-22 12:13:45.232 12074-12086/com.foo.example D/RxBle#BluetoothGatt: onServicesDiscovered status=0
12-22 12:13:45.262 12074-12558/com.foo.example D/RxBle#Radio:   QUEUED RxBleRadioOperationDescriptorWrite(8700606)
12-22 12:13:45.262 12074-12281/com.foo.example D/RxBle#Radio: FINISHED RxBleRadioOperationServicesDiscover(72789039)
12-22 12:13:45.262 12074-12281/com.foo.example D/RxBle#Radio:  STARTED RxBleRadioOperationDescriptorWrite(8700606)
12-22 12:13:45.342 12074-12085/com.foo.example D/RxBle#BluetoothGatt: onDescriptorWrite descriptor=00002902-0000-1000-8000-00805f9b34fb status=0
12-22 12:13:45.362 12074-12281/com.foo.example D/RxBle#Radio: FINISHED RxBleRadioOperationDescriptorWrite(8700606)
12-22 12:13:46.172 12074-12086/com.foo.example D/RxBle#BluetoothGatt: onCharacteristicChanged characteristic=CHARACTERISTIC_FOO_UUID
12-22 12:13:46.192 12074-12558/com.foo.example D/RxBle#Radio:   QUEUED RxBleRadioOperationDescriptorWrite(179103302)
12-22 12:13:46.192 12074-12281/com.foo.example D/RxBle#Radio:  STARTED RxBleRadioOperationDescriptorWrite(179103302)
12-22 12:13:46.272 12074-12201/com.foo.example D/RxBle#BluetoothGatt: onDescriptorWrite descriptor=00002902-0000-1000-8000-00805f9b34fb status=0
12-22 12:13:46.272 12074-12281/com.foo.example D/RxBle#Radio: FINISHED RxBleRadioOperationDescriptorWrite(179103302)
下面是使用RxAndroidBle的版本的简化示例,该版本可以正常工作,但具有多个订阅和ConnectionSharingAdapter。在这两个版本中,Observable都会在其他地方订阅,所以我试图避免多个订阅的所有簿记 - 这里的CompositeSubscription和其他地方的其他订阅。上面的方法,有问题,似乎更有用。在我的实际应用程序中,我所做的事情更复杂,因此上面的版本实际上变得更容易理解,在这个简化版本中,它可能看起来像更多的代码。

CompositeSubscription bleConnectionSubscriptions = new CompositeSubscription();

Observable<RxBleConnection> bleConnectionObservable =
    bleConnectionObservable = bleDevice.establishConnection(context, IS_AUTO_CONNECT)
        .compose(new ConnectionSharingAdapter());

Subscription subscription =
    bleConnectionObservable
        .flatMap(rxBleConnection ->
                 rxBleConnection.setupNotification(CHARACTERISTIC_FOO_INGREDIENTS))
        .flatMap(observable -> observable)
        .subscribe(notificationBytes -> mFooBytes = notificationBytes);

bleConnectionSubscriptions.add(subscription);

subscription =
    bleConnectionObservable
        .flatMap(rxBleConnection ->
                 rxBleConnection.setupNotification(CHARACTERISTIC_BAR_INGREDIENTS))
        .flatMap(observable -> observable)
        .subscribe(notificationBytes -> mBarBytes = notificationBytes);

bleConnectionSubscriptions.add(subscription);

1 个答案:

答案 0 :(得分:1)

正如您在日志中看到的那样,两个通知都已正确设置,但第二个通知未收到任何值。怀疑是在设置通知之前发出了BAR值。

您可以使用以下代码在连接的最开始设置两个通知:

rxBleClient.scanBleDevices(SERVICE_UUID)
        .first() // subscribe to the first device that is available...
        .flatMap(rxBleScanResult -> rxBleScanResult.getBleDevice().establishConnection(context, IS_AUTO_CONNECT)) // ...establish the connection...
        .flatMap(rxBleConnection -> Observable.combineLatest( // ...when connection is established we combine latest results from...
                rxBleConnection.setupNotification(CHARACTERISTIC_FOO_INGREDIENTS) // ...setup notification on FOO...
                        .flatMap(observable -> observable) // ...flatMap it to values...
                        .first(), // ...take the first value so the notification will be disposed...
                rxBleConnection.setupNotification(CHARACTERISTIC_BAR_INGREDIENTS) // ...setup notification on BAR...
                        .flatMap(observable -> observable) // ...flatMap it to values...
                        .first(), // ...take the first value so the notification will be disposed...
                ((fooBytes, barBytes) -> {
                    mFooBytes = fooBytes; 
                    mBarBytes = barBytes;
                    return true; // return whatever
                })
        ))
        .first(); // after the first returned value the connection will be disconnected