RxAndroidBle:如果客户端处于可观察状态,如何执行读写操作?

RxAndroidBle: If client is in observable state how to perform Read and Write operations?

建立连接时我使用 .asObservable() 属性 保持连接。

bleDevice = rxBleDevice;
rxBleDevice.establishConnection(false)
        .flatMap(RxBleConnection::discoverServices)
        **.asObservable()**
        .subscribe(rxBleDeviceServices -> swapScanResult(rxBleDeviceServices));

建立连接后,当我尝试读取值时显示

Already connected to device

 bleDevice.establishConnection(false)
        .flatMap(rxBleConnection -> Observable.combineLatest(
                    rxBleConnection.readCharacteristic(gattCharacteristicList.get(6).getUuid()),
                    rxBleConnection.readCharacteristic(gattCharacteristicList.get(7).getUuid()),
                    ReadValuesOnConnection::new
        ))
        .subscribe(
                readValuesOnConnection -> Log.i("UUid 6 Value: ", readValuesOnConnection.value_1+""),
                throwable -> Log.e("Error", throwable.getMessage())
        );

日志:

I/Bluetooth Enable: True
I/RxBle#QueueOperation: Scan operation is requested to start.
I/Scan Results:: 6Q:6C:05:8E:F5:5B
I/Scan Results:: 6P:6A:05:8E:F8:2X
I/RxBle#CancellableSubscription: Scan operation is requested to stop.
W/zygote64: Suspending all threads took: 5.645ms
I/Characteristics List size:: 33
E/Error: Already connected to device with MAC address 6Q:6C:05:8E:F5:5B

我浏览了示例项目,但没有找到任何解决方案。

client is in observable state 是什么意思? .asObservable() 不是 属性,而是一个函数——在这种特殊情况下——没有任何改变,因为 .flatMap() 的结果已经是一个 Observable

Already connected to device with MAC address 来自 BleAlreadyConnectedException 并且表示在已经打开一个连接时尝试建立一个新连接。

您可能想要的是将两个独立的流程合并为一个可以同时执行以下操作的流程:swapScanResult 和读取特征。你可以这样做:

subscription = rxBleDevice.establishConnection(false) // first we want to establish the connection
  .flatMap( // once the connection is established
    RxBleConnection::discoverServices, // we want to explicitly discover the services
    (rxBleConnection, rxBleDeviceServices) -> { // when both the connection and services are available
      swapScanResult(rxBleDeviceServices); // we swap scan result?
      return Observable.combineLatest( // and start reading characteristics
        rxBleConnection.readCharacteristic(gattCharacteristicList.get(6).getUuid(),
        rxBleConnection.readCharacteristic(gattCharacteristicList.get(7).getUuid(),
        ReadValuesOnConnection::new // when both characteristics are read we combine the result
      );
    }
  )
  .flatMap(observable -> observable) // we need to flatMap the result as we returned an Observable from the first flatMap
  .take(1) // after the read has completed we unsubscribe from the upstream to make the connection close
  .subscribe( // we consume the result
    readValuesOnConnection -> Log.i("UUid 6 Value: ", readValuesOnConnection.value_1+""),
    throwable -> Log.e("Error", throwable.getMessage())
  );

此外,此流程使用了一些副作用,使其具有潜在的不确定性。您调用一个方法 swapScanResult(RxBleDeviceServices) 并在其他地方使用 gattCharacteristicList.get(int).getUuid() 并将其反馈给流程。

通过更改上述方法并访问特征列表(存储为 属性),可以使代码更易于理解。它就像将它更改为一个可以具有如下签名的纯函数一样简单:

static Pair<UUID, UUID> getUuidsOfCharacteristicsToRead(RxBleDeviceServices services);