用于大数据量的Rxandroid读取操作

用于大数据量的Rxandroid读取操作,android,rx-java2,rxandroidble,Android,Rx Java2,Rxandroidble,我正在使用RxAndroidBle库从我的BLE设备向android应用程序读取值。应用程序在可编程外围设备上执行多次读取,如下代码所示 public void longRead() { // if (isConnected()) { longReadSubscription = connectionObservable .flatMap(RxBleConnection::discoverServices, (rxBleConnec

我正在使用RxAndroidBle库从我的BLE设备向android应用程序读取值。应用程序在可编程外围设备上执行多次读取,如下代码所示

public void longRead()
{
   // if (isConnected())
    {
        longReadSubscription =  connectionObservable
                .flatMap(RxBleConnection::discoverServices, (rxBleConnection, services) ->
                        services.getCharacteristic(UUID_READ_CHARACTERISTIC)
                                .flatMap(characteristic -> rxBleConnection.queue(new CustomReadOperation(characteristic)))
                )
                .flatMap(observable -> observable)
                .first() // Bug fix for not disconnecting after read.
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.bindToLifecycle())
                .subscribe(bytes -> {
                    configureWifiMvpView.showList(bytes);
                }, this::onLongReadFailure);
    }
}

private static class CustomReadOperation implements RxBleRadioOperationCustom<byte[]> {

    private BluetoothGattCharacteristic characteristic;
    CustomReadOperation(BluetoothGattCharacteristic characteristic) {
        this.characteristic = characteristic;
    }

    /**
     * Reads a characteristic until a special charcter has been found.. 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 readAndObserve(this.characteristic, bluetoothGatt, rxBleGattCallback)
                .subscribeOn(scheduler)
                .takeFirst(readResponseForMatchingCharacteristic())
                .map(byteAssociation -> byteAssociation.second)

                .repeatWhen(completed -> completed.delay(200, TimeUnit.MILLISECONDS))
                .takeUntil(result -> getSpecialCharacter(result) == true);

    }

    public boolean getSpecialCharacter(byte[] s) {
        boolean result = false;
       try {
           String str = new String(s, "UTF-8");
           if (str == null || str.trim().isEmpty()) {
               // System.out.println("Incorrect format of string");
               return true;
           }
           System.out.println(s);
           Pattern p = Pattern.compile("]");
           Matcher m = p.matcher(str);
           result = m.find();
     }
       }catch(Exception e)
       {
           System.out.println("exception #####");
       }
        return result;

    }

    @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(UUID_READ_CHARACTERISTIC);
    }
}
public void longRead()
{
//如果(断开连接())
{
longReadSubscription=connectionObservable
.flatMap(RxBleConnection::discoverServices,(RxBleConnection,services)->
services.getCharacteristic(UUID\u READ\u CHARACTERISTIC)
.flatMap(特征->rxBleConnection.queue(新的CustomReadOperation(特征)))
)
.flatMap(可观察->可观察)
.first()//修复了读取后不断开连接的错误。
.observeOn(AndroidSchedulers.mainThread())
.compose(this.bindToLifecycle())
.订阅(字节->{
配置wifimvpview.showList(字节);
},此::onLongReadFailure);
}
}
私有静态类CustomReadOperation实现了RXbreadioOperationCustom{
私人蓝牙特征;
CustomReadOperation(蓝牙GattCharacteristic特征){
这个特性=特性;
}
/**
*读取一个特征,直到找到一个特殊的字符。这很容易实现,无需
*一个自定义操作。这里的好处是只有一个操作进入RXBRADIO队列
*消除进入和退出操作队列的开销。
*/
@非空
@凌驾
公众可观察到的(蓝牙GATT蓝牙GATT,
RXblettCallback RXblettCallback,
调度程序)抛出可丢弃的{
返回读取和观察(this.characteristic、Bluetooth GATT、RXBLAGETCALLBACK)
.subscribeOn(调度程序)
.takeFirst(readResponseForMatchingCharacteristic())
.map(byteAssociation->byteAssociation.second)
.repeatWhen(已完成->已完成.延迟(200,时间单位.毫秒))
.takeUntil(结果->getSpecialCharacter(结果)==true);
}
公共布尔getSpecialCharacter(字节[]s){
布尔结果=假;
试一试{
字符串str=新字符串,“UTF-8”);
if(str==null | | str.trim().isEmpty()){
//System.out.println(“字符串格式不正确”);
返回true;
}
系统输出打印项次;
Pattern p=Pattern.compile(“]”);
匹配器m=p.Matcher(str);
结果=m.find();
}
}捕获(例外e)
{
System.out.println(“异常”);
}
返回结果;
}
@非空
私人可观察读取和观察(蓝牙GATT特征特征,
蓝牙关贸总协定蓝牙关贸总协定,
RxBlegtCallback(RxBlegtCallback){
Observable onCharacteristicRead=RxBlegatetCallback.getOnCharacteristicRead();
返回可见。创建(发射器->{
订阅订阅=onCharacteristicRead.subscribe(发射器);
emitter.setCancellation(订阅::取消订阅);
试一试{
最终布尔成功=bluetoothGatt.readCharacteristic(特征);
如果(!成功){
抛出新的BlegatCannotStartException(蓝牙Gatt、BlegatToOperationType.CHARACTERISTIC_READ);
}
}捕捉(可抛可抛){
发射器。onError(可丢弃);
}
},发射器、背压模块、缓冲器);
}
private Func1 readResponseForMatchingCharacteristic(){
返回uuidByteAssociation->uuidByteAssociation.first.equals(UUID\u READ\u特征);
}
}
}


现在,所有这些都可以正常工作,但偶尔,如果从BLE设备读取的数据超过600字节,则在读取完整数据之前,我会得到Subscribe(字节->)调用,之后我会得到TAKETILL调用,在该调用中,它会检查字符串末尾的特殊字符并终止,从而丢失第二个块中的所有数据。看起来RxAndrodiBLE库维护了一个内部缓冲区,并一直在该缓冲区中写入所有数据,一旦缓冲区已满,就会调用subscribe observable。当数据读取的大小大于缓冲区大小时,这会导致问题。我们如何处理它,使我们不会得到数据块。我们还可以增加缓冲区的大小,以便在调用subscribe之前将接收到的所有数据都存储在那里

您是否尝试记录输出?也许您
getSpecialCharacter()
函数多次返回
true
?是的,我已经记录了输出,我从序列中删除了.first()调用,现在它正在工作。然而,有时我会遇到一个异常,不知道如何处理。java.lang.IllegalStateException:在Scheduler.Worker线程上引发的致命异常。在rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)中,您应该查看整个stacktrace来跟踪正在发生的事情。看起来你在某个地方有一个非法的州是的,现在看看堆栈跟踪:),顺便说一句,我希望你的假期很棒。我将更新注释部分“如果”我找到任何东西。@Avijeet您找到解决方案了吗?您是否尝试记录输出?也许您
getSpecialCharacter()
函数多次返回
true
?是的,我已经记录了输出,我从序列中删除了.first()调用,现在它正在工作。然而,有时我会遇到一个异常,不知道如何处理。java.lang.IllegalStateException