Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
546 views
in Technique[技术] by (71.8m points)

android - Using RxAndroidBle, how do I subscribe to responses from writing to a characteristic?

The BLE device that I'm connecting to emits bytes on one of its GATT characteristics in response to writes to the characteristic. Clients are supposed to enable notifications on that characteristic, and to interpret?change bytes on the characteristic. (The behavior I'm controlling is turning on a scanning service for nearby wireless networks, then listening to the service output.)

I'm using RxAndroidBle and following the examples. I have an active connection Observable. The characteristic I want to observe has a UUID called AP_SCAN_DATA. It's supposed to emit 0xFE in response to receiving a written 0xFF.

How do I call setupNotification and set up an Observer on it to catch emitted byte[]s, then write a value to the characteristic, so that I can catch the response?

My best effort so far:

connectionObservable.observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<RxBleConnection>() {
                @Override
                public void onCompleted() { // ignore...
                }

                @Override
                public void onError(Throwable e) { // ignore...
                }

                @Override
                public void onNext(final RxBleConnection connection) {
                    Observable.just(connection)
                              .flatMap(new Func1<RxBleConnection, Observable<Observable<byte[]>>>() {
                                  @Override
                                  public Observable<Observable<byte[]>> call(RxBleConnection connection) {
                                      return connection.setupNotification(AP_SCAN_DATA);
                                  }
                            })
                            .doOnNext(new Action1<Observable<byte[]>>() {
                                @Override
                                public void call(Observable<byte[]> observable) {
                                    Log.i(TAG, "notification has been set up");
                                    // This code logs on DEBUG that a write was made, but no response ever arrives 
                                    connection.writeCharacteristic(AP_SCAN_DATA, CharacteristicValue.RESET.asBytes())
                                            .observeOn(AndroidSchedulers.mainThread())
                                            .subscribe();

                                }
                            })
                            .flatMap(new Func1<Observable<byte[]>, Observable<byte[]>>() {
                                @Override
                                public Observable<byte[]> call(Observable<byte[]> observable) {
                                    return observable;
                                }
                            })
                            .doOnNext(new Action1<byte[]>() {
                                @Override
                                public void call(byte[] bytes) {
                                    Log.i(TAG, "want to read response bytes here, but I don't... " + HexString.bytesToHex(bytes));
                                }
                            })
                            .subscribe();
                }
            });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is already a topic in which you may find some insight -> RxAndroidBle keeping a persistant connection + Write/Notification handling

This is how you could achieve the same result while using only a single .subscribe().

    connectionObservable
            .flatMap( // when the connection is available...
                    rxBleConnection -> rxBleConnection.setupNotification(AP_SCAN_DATA), // ... setup the notification...
                    (rxBleConnection, apScanDataNotificationObservable) -> Observable.combineLatest( // ... when the notification is setup...
                            rxBleConnection.writeCharacteristic(AP_SCAN_DATA, writeValue), // ... write the characteristic...
                            apScanDataNotificationObservable.first(), // ... 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[]>...
            .first() // ... and finish after first response is received to cleanup notifications
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    responseBytes -> { /* consume the response here */ },
                    throwable -> { /* handle exception */ }
            );

FYI - you should handle errors in every .subscribe() unless you're 100% sure that the Observable does not emit errors.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...