1

After doing my best to understand all the magic in RxJava and the excellent rxandrodible library I'm stuck! The last thing that I need to fix is to setup a write/Notification link in which I write a value - a single value - and after that subscribe to a specific characteristic.

I've used the following code - as considered best practice (?) - but it doesen't actually result in any data on the soundTV.

connectionSubscription = device.establishConnection(false)
                    .flatMap( // when the connection is available...
                            rxBleConnection -> rxBleConnection.setupNotification(RX_CHAR_UUID), // ... setup the notification...
                            (rxBleConnection, apScanDataNotificationObservable) -> Observable.combineLatest( // ... when the notification is setup...
                                    rxBleConnection.writeCharacteristic(TX_CHAR_UUID, new byte[]{SOUND}).toObservable(), // ... write the characteristic...
                                    apScanDataNotificationObservable.take(1),// ... and observe for the first notification on the AP_SCAN_DATA
                                    (writtenBytes, responseBytes) -> responseBytes // ... when both will appear return just the response bytes...
                            )
                    )
                    .flatMap(observable -> observable) // ... flatMap the result as it is Observable<byte[]>...// ... and finish after first response is received to cleanup notifications
                    .take(1)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                            responseBytes -> {
                                soundTV.setText(new String(responseBytes));
                            },
                            throwable -> {
                                soundTV.setText(throwable.toString());}
                    );

There is no data written by the subscription to the give TextView, and I can't find anything that goes wrong.

If I just setup the notifications, without combining it with the write, everything works as it should.

Any suggestions on how to make it work?


The code example used gives only one response. What I was looking for was a write and a subscription that was ongoing. I didn't realize that the take(1) call actually made a difference, thought it was a clean-up in the complex call structure.

Sorry! This works as intended for me:

    connectionSubscription = device.establishConnection(false)
                    .flatMap( // when the connection is available...
                            rxBleConnection -> rxBleConnection.setupNotification(RX_CHAR_UUID), // ... setup the notification...
                            (rxBleConnection, apScanDataNotificationObservable) -> Observable.combineLatest( // ... when the notification is setup...
                                    rxBleConnection.writeCharacteristic(TX_CHAR_UUID, new byte[]{SOUND}).toObservable(), // ... write the characteristic...
                                    apScanDataNotificationObservable,// ... and observe for the first notification on the AP_SCAN_DATA
                                    (writtenBytes, responseBytes) -> responseBytes // ... when both will appear return just the response bytes...
                            )
                    )
                    .flatMap(observable -> observable) // ... flatMap the result as it is Observable<byte[]>...// ... and finish after first response is received to cleanup notifications
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                            responseBytes -> {
                                soundTV.setText(new String(responseBytes));
                            },
                            throwable -> {
                                soundTV.setText(throwable.toString());}
                    ); 
  • There are few things you may consider: add logging to your code (e.g. `[Observable].doOnNext(bytes -> Log.d("TAG0", Arrays.toString(bytes))).doOnError(throwable -> Log.e("TAG0", "Whoops!", throwable).doOnComplete(...)` for every Observable that you think is not behaving properly. You may also include the logs from the library (`RxBleLog.setLogLevel(RxBleLog.VERBOSE)`). Also do not use `new String(responseBytes)` for debug log purposes as the response bytes may not have sense as characters — use `Arrays.toString()` instead. – Dariusz Seweryn Oct 22 '18 at 09:54
  • Thanks! I will add logs and see what I find. I get data from the connection once - don't know if its valid - but after that nothing. No errors are thrown and nothing suspicious, i.e. errors are found in the logs, hence I think it is a logical error in the code I'm using. The connection is not terminated either. – Anders Gustafsson Oct 22 '18 at 10:39
  • I solved the issue. Dariusz comment about logging got me a bit confused, didn't know where to put the code example to get any result from it, when I realized that the presence of take(1) was the logical error. Will post working code below. – Anders Gustafsson Oct 23 '18 at 06:54
  • Edited the original post with working code! – Anders Gustafsson Oct 23 '18 at 07:03

0 Answers0