2016-12-22 13 views
0

爲RxBleConnection.setupNotification工作只有第一的我遇到困難找出使用RxAndroidBle意外的行爲兩個特點

問題的短形式是,我需要從特定裝置的兩個特性接收有序通知。在我下面的示例中,我掃描了SERVICE_UUID,併爲CHARACTERISTIC_FOO_UUID和CHARACTERISTIC_BAR_UUID設置了通知(按順序)。我需要根據兩個特性的響應來做一些事情---在我的例子中,我只是將byte []存儲在成員變量中。

我遇到的問題是,第一個特點報告回而不是第二。如果我翻轉訂單,它仍然是鏈中第一個特徵。下面,我提供了調試輸出,它顯示通知調用都發生在兩個位置,包括低級描述符寫入,但由於某種原因,第二個不會報告回來。 (假設我訂閱了觀測。)

我已經能夠得到這個沒有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調試輸出---我節錄實際的UUID與輸出「CHARACTERISTIC_FOO_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); 
+0

您的代碼應該工作(雖然它可能會開始胡作非爲如果超過一個值會從FOO通知特徵)並且從日誌中判斷第一通知是否被傳遞,儘管第二通知在任何地方都是不可見的。粘貼後有沒有BLE日誌?是否有另一個BLE連接同時連接到不同的設備? (我不知道Android操作系統限制特徵通知是否被連接共享) –

+0

@s_noopy謝謝。將只有一個來自FOO uuid的通知,所以我應該安全,但謝謝指出潛在的問題。至於日誌,我貼的是報道的一切。如果我單獨離開連接,一段時間後連接自動斷開連接時會生成額外的日誌。 –

+0

看起來您的設備在BAR特性上根本沒有發送任何通知。在建立通知之前,可能會更改BAR特徵值。 –

回答

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 
+0

終於有機會驗證這一點。事實上,你是正確的,第二個特徵是在通知建立之前發出的。你提供的代碼工作。非常感謝@s_noopy的幫助。 –