android - How to Read BLE GATT characterstics in chunks form GATT server using RxAndroidBLE -
i using rxandroidble library handling ble connection , reading/writing gatt server android gatt client app. have followed sample application provided on github.
the problem facing gatt server running on intel edison , supporting mtu size of 80 .it sends data in chunks, supposed read charcterstics value multiple time until encounter special character, '/end' . have tried custom read operation example supposed read 5 times every 250 ms.
private static class customreadoperation implements rxbleradiooperationcustom<byte[]> { private rxbleconnection connection; private uuid characteristicuuid; customreadoperation(rxbleconnection connection, uuid characteristicuuid) { this.connection = connection; this.characteristicuuid = characteristicuuid; } /** * reads characteristic 5 times 250ms delay between each. achieve without * custom operation. gain here 1 operation goes rxbleradio queue * eliminating overhead of going on & out of operation queue. */ @nonnull @override public observable<byte[]> asobservable(bluetoothgatt bluetoothgatt, rxblegattcallback rxblegattcallback, scheduler scheduler) throws throwable { return connection.getcharacteristic(characteristicuuid) .flatmap(characteristic -> readandobserve(characteristic, bluetoothgatt, rxblegattcallback)) .subscribeon(scheduler) .takefirst(readresponseformatchingcharacteristic()) .map(byteassociation -> byteassociation.second) .repeatwhen(notificationhandler -> notificationhandler.take(5).delay(250, timeunit.milliseconds)); } @nonnull private observable<byteassociation<uuid>> readandobserve(bluetoothgattcharacteristic characteristic, bluetoothgatt bluetoothgatt, rxblegattcallback rxblegattcallback) { observable<byteassociation<uuid>> oncharacteristicread = rxblegattcallback.getoncharacteristicread(); return observable.create(emitter -> { subscription subscription = oncharacteristicread.subscribe(emitter); emitter.setcancellation(subscription::unsubscribe); try { final boolean success = bluetoothgatt.readcharacteristic(characteristic); if (!success) { throw new blegattcannotstartexception(bluetoothgatt, blegattoperationtype.characteristic_read); } } catch (throwable throwable) { emitter.onerror(throwable); } }, emitter.backpressuremode.buffer); } private func1<byteassociation<uuid>, boolean> readresponseformatchingcharacteristic() { return uuidbyteassociation -> uuidbyteassociation.first.equals(characteristicuuid); } }
and calling this
public void customread() { if (isconnected()) { connectionobservable .flatmap(rxbleconnection -> rxbleconnection.queue(new customreadoperation(rxbleconnection, uuid_read_characteristic))) .observeon(androidschedulers.mainthread()) .subscribe(bytes -> { configuremvpview.showlist(bytes); }, this::onruncustomfailure); } }
and not getting data server using code. if try simple read operation this
public void readinfo() { if (isconnected()) { connectionobservable .flatmap(rxbleconnection -> rxbleconnection.readcharacteristic(uuid_read_characteristic)) .observeon(androidschedulers.mainthread()) .subscribe(bytes -> { // parse data configuremvpview.showwifilist(bytes); }, this::onreadfailure); } }
i first chunk of data, need read rest of data.
not versed rxjava. there might easy way this, suggestion or good.
this prepareconnectionobservable
private observable<rxbleconnection> prepareconnectionobservable() { return bledevice .establishconnection(false) .takeuntil(disconnecttriggersubject) .subscribeon(schedulers.io()) .observeon(androidschedulers.mainthread()) .doonunsubscribe(this::clearsubscription) .compose(this.bindtolifecycle()) .compose(new connectionsharingadapter()); }
i call
connectionobservable.subscribe(this::onconnectionreceived, this::onconnectionfailure);
and onconnectionreceived call customread.
you not show how connectionobservable
created , not know if else done on connection before above code executed.
my guess if logs of application see radio processing queue starts executing customreadoperation
first operation after connection. in custom operation calling rxbleconnection.getcharacteristic(uuid)
tries execute .discoverservices()
(schedule rxbleradiooperationdiscoverservices
on radio queue). problem radio queue executing customreadoperation
, not discover services until finish.
there reason why rxbleconnection
not passed rxbleradiooperationcustom.asobservable()
— of functionality not work @ time.
what can perform rxbleconnection.discoverservices()
before scheduling customreadoperation
, pass bluetoothgattcharacteristic
retrieved rxbledeviceservices
in constructor. instead of having this:
public void customread() { if (isconnected()) { connectionobservable .flatmap(rxbleconnection -> rxbleconnection.queue(new customreadoperation(rxbleconnection, uuid_read_characteristic))) .observeon(androidschedulers.mainthread()) .subscribe(bytes -> { configuremvpview.showlist(bytes); }, this::onruncustomfailure); } }
you have like:
public void customread() { if (isconnected()) { connectionobservable .flatmap(rxbleconnection::discoverservices, (rxbleconnection, services) -> services.getcharacteristic(uuid_read_characteristic) .flatmap(characteristic -> rxbleconnection.queue(new customreadoperation(characteristic))) ) .flatmap(observable -> observable) .observeon(androidschedulers.mainthread()) .subscribe(bytes -> { configuremvpview.showlist(bytes); }, this::onruncustomfailure); } }
edit (clarification):
and constructor of customreadoperation
should this:
customreadoperation(bluetoothgattcharacteristic characteristic) { this.characteristic = characteristic; }
so not have use this.rxbleconnection.getcharacteristic(uuid)
inside of customreadoperation
, use directly bluetoothgatt.readcharacteristic(this.characteristic)
.
edit 2: change these 2 lines:
return connection.getcharacteristic(characteristicuuid) .flatmap(characteristic -> readandobserve(characteristic, bluetoothgatt, rxblegattcallback))
to (the rest same):
return readandobserve(this.characteristic, bluetoothgatt, rxblegattcallback)
Comments
Post a Comment