【问题标题】:How do I effectively read temperature from two BLE devices at the same time?如何有效地同时从两个 BLE 设备读取温度?
【发布时间】:2023-03-12 11:41:01
【问题描述】:

首先,我使用 RxAndroidBLE 库来管理我的 BLE 连接。

我有两个SensorTag devices,我想同时读取两者的温度。例如,我想每 500 毫秒准确地读取两个设备的温度,并在两个 TextView 中显示给用户。

我的应用目前成功连接到两个 BLE 设备,如下所示:

@OnClick(R.id.connectButton1)
public void connectFirstSensorTag(Button b) {
    if (!isDeviceConnected(sensorTag1)) {
        connectionObservable1 = sensorTag1.establishConnection(getApplicationContext(), false).compose(new ConnectionSharingAdapter());
    }

    connectionObservable1.subscribe(new Subscriber<RxBleConnection>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {
            updateStatus(statusTextView1, "SensorTag not found");
        }

        @Override
        public void onNext(RxBleConnection rxBleConnection) {
            updateStatus(statusTextView1, "Connected");
            enableSensorTagTemperatureSensor(connectionObservable1);
        }
    });
}

@OnClick(R.id.connectButton2)
public void connectSecondSensorTag(Button b) {
    if (!isDeviceConnected(sensorTag2)) {
        connectionObservable2 = sensorTag2.establishConnection(getApplicationContext(), false).compose(new ConnectionSharingAdapter());
    }

    connectionObservable2.subscribe(new Subscriber<RxBleConnection>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {
            updateStatus(statusTextView2, "SensorTag not found");
        }

        @Override
        public void onNext(RxBleConnection rxBleConnection) {
            updateStatus(statusTextView2, "Connected");
            enableSensorTagTemperatureSensor(connectionObservable2);
        }
    });
}

现在我正在寻找每 500 毫秒同时读取两者温度的最佳方法。

现在,我正在做这样的事情:

connectionObservable1
                .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(uuidFromShortCode("AA01")))
                .subscribe(bytes -> {

                    // first temperature was successfully read here

                    connectionObservable2
                            .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(uuidFromShortCode("AA01")))
                            .subscribe(bytes -> {

                                // second temperature was successfully read here

                            }, error -> {
                                updateStatus(error.toString());
                            });
                }, error -> {
                    updateStatus(error.toString());
                });

这段代码位于每 500 毫秒调用一次的可运行文件中。

我觉得这是一种非常低效的方法。有人可以告诉我是否有更好的方法来做到这一点?

【问题讨论】:

  • 您应该并行读取,不是吗?另请注意,没有理由有两个匿名的“new Subscriber(”(将其提取为内部类并由构造函数传递statusTextView1/2

标签: android android-bluetooth rx-android android-ble rxandroidble


【解决方案1】:

首先,您无法在 BLE 上进行真正的并行读取或任何其他操作,因为您只有一个无线电并且操作需要是顺序的。你能做的最好的事情就是尽快一个接一个地解雇他们。使用 RxAndroidBle,您可以为您管理序列化。

做你想做的事我这样看:

    RxBleDevice sensorTag0 = // your first SensorTag
    RxBleDevice sensorTag1 = // your second SensorTag
    UUID characteristicUuid = uuidFromShortCode("AA01");

    Subscription flowSubscription = Observable.combineLatest(
            sensorTag0.establishConnection(this, false), // establishing connections
            sensorTag1.establishConnection(this, false),
            Pair::new // merging them together
    )
            .flatMap(connections -> Observable
                    .interval(500, TimeUnit.MILLISECONDS) // every 500 ms
                    .flatMap(aLong -> Observable.combineLatest(
                            connections.first.readCharacteristic(characteristicUuid), // performing reads
                            connections.second.readCharacteristic(characteristicUuid),
                            Pair::new // and merging the results
                    )))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    readings -> {
                        updateUISensorTag0(readings.first); // updating the UI
                        updateUISensorTag1(readings.second);
                    },
                    throwable -> updateStatus(throwable.toString()) // or showing the error
            );

希望对你有所帮助。

最好的问候。

【讨论】:

  • 谢谢!这正是我正在寻找的答案。还有一个问题。你怎么知道 RxAndroidBle 能够做到这一点?我已经阅读了该库可用的所有文档(而且内容不多),并且没有任何示例可以显示这样的内容。您是否深入研究了源代码以找出答案?或者在了解这个库时我还有什么遗漏的吗?我真的很感兴趣,因为我经常偶然发现一个即使在大量阅读文档后也无法解决的问题。
  • 我是 RxAndroidBle 库的作者之一。该库试图遵守 Observable 合同,其余的是将其与 rxJava 知识相结合。在上面的例子中,我只使用了两个库方法:establishConnection(Context, boolean)readCharacteristic(UUID)——其余的是纯 rxJava。实际上有示例 #5 github.com/Polidea/RxAndroidBle/blob/master/sample/src/main/…,其中使用了类似的流程 readRssi() 而不是 readCharacteristic(UUID)
  • 如果我可以问 - 您希望得到什么信息?在哪里?我会尝试更新可用的文档。
  • 其实我不知道这大多只是RxJava。我对 RxJava 也很陌生(在此之前几乎从未使用过它),所以这可能是我不能以更“高级”的方式使用这个库的原因。我想我对文档的期望是展示并可能解释一些更高级的使用示例,例如您的答案中的示例,因为很多像我这样的人在想要使用像您这样的库时第一次遇到 RxJava。但无论哪种方式,很棒的图书馆,我喜欢它!它让 BLE 对我来说非常容易使用 :)
【解决方案2】:

我建议你启动两个线程。线程 1 检查第一个设备,线程 2 检查第二个设备。这样可以确保同时读取两者。为了仅在两者都完成后继续执行代码,我将执行阻塞连接循环。

//Threads array has been created, with 0 checking the first 
//device and 1 checking the second
for(i = 0; i < threads.length(); i++)
    threads[i].join();

【讨论】:

  • 您好,谢谢您的回答。您能否详细说明您提到的 for 循环?我不认为我完全理解这将如何帮助我知道两个线程何时完成。
  • thread.join 允许您在完成之前等待线程结束。现在,如果您遍历所有线程并确保它们都已完成,那么这正是您想要的!
  • 有道理,谢谢!我接受了另一个答案,因为它对我的示例更可行,但您的信息也有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多