Swift中的反应式心率监测器

利用RxSwiftRxBluetoothKit的功能以无缝方式与HR监视器交互。

集成核心蓝牙以连接到心率监测器需要进行大量工作。 如果您熟悉反应式编程,则RxBluetoothKit使事情变得容易得多。 但是您仍然需要了解Core Bluetooth的工作原理,并编写大量代码以与HR监视器对话。

RxHeartRateMonitors是RxBluetoothKit和Core Bluetooth之上的一层。 我构建了它以无缝,反应式的方式与心率监测器进行交互。

您可以下载该项目并进行尝试。

它有什么作用?

  • 仅列出心率监测器。
  • 连接和断开监视器。
  • 从监视器读取心率。
  • 记住以前连接的显示器。
  • 自动连接到以前连接的显示器。
  • 读取蓝牙状态。
  • 读取监视器状态。

在本文中,我将解释有关该项目的一些细节。 为什么创建它以及一些实现细节。

我正在作为一个团队的一部分来构建健身应用程序。 该应用程序的要求之一是列出可以使用的心率监测器。 同样,用户应该能够连接并从此类设备读取值。

我以为CoreBluetooth将使这项工作变得容易。 事实并非如此。

核心蓝牙太通用

它抽象了BTLE协议栈,提供了与各种设备进行交互的方式。

发现外围设备非常容易。 但是随后您还需要发现其服务,特征和代码。 最后,您需要读取原始数据并将其转换为正确的格式。

代码可能变得非常复杂。 为了给您一个想法,以下是从监视器读取心率值所需的步骤:

  1. 启动中央管理器。
  2. 发现外围设备( 需要一名代表
  3. 过滤提供心率监测服务的外围设备
  4. 连接到外围设备( 需要委托
  5. 发现该外围设备的服务( 需要委托
  6. 发现服务的特征( 需要委托
  7. 找到代表心率的特征
  8. 订阅特征值( 需要委托
  9. 将原始数据转换为正确的格式。

实现必需的委托需要太多代码。 如果您看一下本教程或本文,则可以了解其复杂性。 苹果公司也有一个例子(在Objective-C中)。

复杂性很高,因为Core Bluetooth是通用的。 它的构建使您可以连接到任何类型的BTLE设备,而不仅仅是HR监视器。

RxBluetoothKit很有帮助!

RxBluetoothKit是Core Bluetooth的一个很好的包装。 它实现了所有委托功能,并为框架提供了反应式接口。 而不是编写所有这些委托,而是编写声明式反应式代码。

对我来说,这是一个很大的进步。 它使事情变得简单得多。 例如,扫描设备并从第一个设备获取特征:

代码更少,但仍有很多事情需要解决。 您仍然需要阅读服务,特征并格式化数据。

我想连接显示器并观察心律。

问题很简单。 但是,即使使用RxBluetoothKit,解决方案也不是那么简单。 当我使用此工具时,我意识到RxBluetoothKit与我所需要的之间存在差距。

代码应该更简单。 这就是为什么我创建RxHeartRateMonitors的原因。

同样,该想法是仅以无缝方式与心率监视器进行最佳交互,从而减少编写代码。

仅列出HR Monitor。

我想看到人力资源监视器,而不是恒温器或速度计之类的其他设备。 我let heartRateMonitors : Observable 。 所以我可以做一些事情,例如将它们显示在桌子上:

心率监测器。 UITableView中列出的名称和状态

连接/断开

连接和断开显示器的连接应该很容易。 调用connect返回一个observable,它将以新状态流式传输监视器。

连接和断开与心率监测器的连接。

看看我如何连接按钮的tap事件,以及如何使用materialize()处理可能的错误我真的很喜欢Adam Borek的这篇关于处理错误的文章,以防您想了解更多有关materialize()

阅读心率。

每分钟的节拍是用户实际需要查看的。 心率监视器将以无符号整数流的形式发布此值:

let heartRate : Observable = self.heartRateMonitor.heartRate

心率可以显示在这样的标签中:

心率绑定到标签。

自动连接到先前连接的显示器。

使用上面的代码,用户可以查看可用监视器的列表并连接到它们。 他们不必每次都绑在显示器上时手动连接。

例如,用户可能注册了一个心率监测器频段,并在第二天打开该应用程序,并开始使用相同的频段进行锻炼。

考虑到这一点,有必要自动连接到监视器并显示心率,而无需用户做任何事情。 我想写这样的东西:

库会记住已连接到应用程序的设备,以便以后能够自动连接到它们。

因此,RxHeartRateMonitors可以列出,连接,断开连接,显示状态,心率以及自动连接到已保存的设备。 生成的代码非常简单。

我已经解释了要求,并且也介绍了如何使用该库。 在github仓库中有一个例子,涵盖了通常的情况。

本文可能有一些实现细节值得一提。 如果您需要扩展代码以编程另一种中央控件,则它们很有用。

例如,如果您需要与速度计通话,则可以根据以下说明编写您自己的中央仪表。

重要提示 :使用RxHeartRateMonitors实际上不需要理解或编写以下任何代码

读取数据。

蓝牙设备以原始位发布数据。 如果要获取字符串,数字或其他内容,则需要正确转换这些位。 我想获取表示监视器每分钟节拍数的无符号整数。

这是代码从Apple的示例迁移到swift的方式:

代码用于从监视器读取心率。

服务和特征代码

蓝牙设备支持各种服务。 每个服务都有一个代码。 特征也是如此。 心率监测器发布心率监测服务心率测量特性

如果您直接使用CoreBluetooth或RxBluetoothKit,这是您需要研究和编码的另一件事。 您可以在GATT规范中查看服务和特性代码。

中心使用此信息来过滤其他类型设备的心率监视器。 同样,RxBluetoothKit使用它来允许开发人员在便捷调用方法中编写更简单的代码。

中心使用此信息来过滤其他类型设备的心率监视器。

通用中央

在项目中,您将找到与RxBluetoothKit和CoreBluetooth对话的BluetoothCentral 。 它包含一些样板代码,并完成任何类型的中央设备需要执行的艰苦工作。

有一个通用协议SpecifiedBluetoothCentral ,可以通过任何一种具体的中央协议来实现。 就我而言,是HeartRateMonitorsCentral. 这允许以后扩展到其他类型的设备。

可以扩展该层以创建另一种中央,例如与恒温器通信。 为此,您将需要:

  • 创建设备和中央协议。 例如,ThermostatMonitor和ThermostatMonitorsCentral。
  • 提供服务和特征代码。
  • 将数据转换为所需格式。

如果您遵循HeartRateMonitor和HeartRateMonitorCentral的代码样式,则实现应相当简单。

该项目还很年轻,可能包含一些错误。 我仍然需要编写很多单元测试代码,并将它们添加到Pod中。

如果您有任何疑问或发现任何错误或怪异的东西,请告诉我。

与心率监测器进行通信应该非常简单,这就是我编写此层的原因。 它是在RxBluetoothKit之上编写的。 他们在提供CoreBluetooth顶部的反应层方面做得非常出色。

反应性声明代码在异步情况下(例如与BTLE设备进行交互)有很大帮助。 您可以阅读我撰写的有关该主题的另一篇文章。

你喜欢这篇文章吗? 请随时留下评论。 我希望得到一些反馈!