【问题标题】:What is the proper way to write multiple characteristics with RxAndroidBle?使用 RxAndroidBle 编写多个特征的正确方法是什么?
【发布时间】:2017-09-25 18:01:20
【问题描述】:

我是 Rx 的新手,仍在尝试弄清楚如何正确处理 observables。我想知道是否有更好的方法来编写多个特性而不是使用 RxAndroidBle 一次编写一个特性?目前我正在使用下面的代码一次做一个。

Observable<RxBleConnection> mConnectionObservable;

private void saveChanges(String serialNumber, Date date, MachineTypeEnum machineType, MachineConfig machineConfig) {
    mWriteSubscription = mConnectionObservable
            .flatMap(rxBleConnection -> Observable.merge(
                    getWrites(rxBleConnection, serialNumber, machineType, machineConfig, date)
            ))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(bytes -> {
                Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
                ((MainActivity)getActivity()).back();
            }, BleUtil::logError);
}

private Iterable<? extends Observable<? extends byte[]>> getWrites(RxBleConnection rxBleConnection,
                                                                   String serialNumber,
                                                                   MachineTypeEnum machineType,
                                                                   MachineConfig machineConfig,
                                                                   Date date) {
    List<Observable<byte[]>> observables = new ArrayList<>();


    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_WRITE_SERIAL_NUMBER,
            Utf8Util.nullPad(serialNumber, 16).getBytes()).doOnError(throwable -> Log.e("Write", "serial failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_MACHINE_TYPE,
            new byte[]{(byte) machineType.val()}).doOnError(throwable -> Log.e("Write", "machine type failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_CHARACTERISTIC,
            MachineConfigBitLogic.toBytes(machineConfig)).doOnError(throwable -> Log.e("Write", "machine config failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.CurrentTime.Characteristics.UUID_CURRENT_TIME,
            TimeBitLogic.bytesFor(date)).doOnError(throwable -> Log.e("Write", "date failed", throwable)));

    return observables;
}

所以我将旧代码更改为上面的代码,现在使用合并,但现在似乎只有一个特征更新了。

【问题讨论】:

    标签: android rx-android rxandroidble


    【解决方案1】:

    我会使用merge 运算符:

    mConnectionObservable
            .flatMap(rxBleConnection -> 
            Observable.merge(
            rxBleConnection.writeCharacteristic(
                Constants.Bluetooth.Services.DeviceInformation.Characteristics.UUID_SERIAL_NUMBER,
                Utf8Util.nullPad(serialNumber, 16).getBytes()
            ),
            rxBleConnection.writeCharacteristic(
                Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_MACHINE_TYPE,
                new byte[]{(byte) machineType.val()}
            ))
            .subscribe(bytes -> {/* do something*/}, BleUtil::logError);
    

    您也可以将可观察的列表传递给该操作员:

    您无需将多个 Observable(最多 9 个)传递给合并,而是 也可以传入 Observables 的 List(或其他 Iterable), Observables 数组,甚至是发出 Observables 的 Observable, 和 merge 会将它们的输出合并到单个的输出中 可观察的

    【讨论】:

    • 我确实遇到了使用合并的问题。使用这种方法似乎只能写入其中一个特征。我将使用我当前的代码添加一个编辑。
    【解决方案2】:

    RxAndroidBle 库在后台序列化任何 BLE 请求,因为 Android 上的 BLE 实现大部分是同步的(尽管 Android vanilla API 表明它不是)。

    合并写入是一种好方法,但您需要了解合并运算符的作用:

     * You can combine the items emitted by multiple Observables so that they appear as a single Observable, by
     * using the {@code merge} method.
    

    所以我将旧代码更改为上面的代码,现在使用合并,但现在似乎只有一个特征更新了。

    这种行为的原因可能是您使用流的方式:

            .subscribe(bytes -> {
                Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
                ((MainActivity)getActivity()).back();
            }, BleUtil::logError);
    

    每当发出bytes 时,您就是在调用Activity.back().merge() 操作符会为每个执行的写入命令发出 bytes。如果您取消订阅Subscription,即.onPause(),那么它将在第一次写入完成后立即取消订阅。 您可以让您的流程等到所有写入完成,如下所示:

    private void saveChanges(String serialNumber, Date date, MachineTypeEnum machineType, MachineConfig machineConfig) {
        mWriteSubscription = mConnectionObservable
            .flatMap(rxBleConnection -> 
                Observable.merge(
                    getWrites(rxBleConnection, serialNumber, machineType, machineConfig, date)
                )
                .toCompletable() // we are only interested in the merged writes completion
                .andThen(Observable.just(new byte[0])) // once the merged writes complete we send a single value that will be reacted upon (ignored) in .subscribe()
            )
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(ignored -> {
                Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
                ((MainActivity)getActivity()).back();
            }, BleUtil::logError);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      • 2013-11-29
      • 2010-11-22
      • 2017-04-20
      相关资源
      最近更新 更多