I am using RxAndroidBle library for handling BLE connection and reading/writing to GATT server from my android gatt client app. I have followed the sample application provided on github.
The problem I am facing is my GATT server is running on Intel Edison and it is supporting MTU size of 80 only .It sends data in chunks, I am supposed to read the charcterstics value multiple time until i encounter a special character, something like '/END' . I have tried Custom read operation example which is supposed to 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 a characteristic 5 times with a 250ms delay between each. This is easily achieve without
* a custom operation. The gain here is that only one operation goes into the RxBleRadio queue
* eliminating the overhead of going on & out of the 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 i am calling it like 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 i am not getting any data from the server using this code. However if i try simple read operation like 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 get the first chunk of data, but i need to read rest of data.
I am not very well versed with RxJava. So there might be an easy way to do this, But any suggestion or help will good.
This is my 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 i call CustomRead.