Swift中的反应式心率监测器
利用RxSwift和RxBluetoothKit的功能以无缝方式与HR监视器交互。
集成核心蓝牙以连接到心率监测器需要进行大量工作。 如果您熟悉反应式编程,则RxBluetoothKit使事情变得容易得多。 但是您仍然需要了解Core Bluetooth的工作原理,并编写大量代码以与HR监视器对话。
RxHeartRateMonitors是RxBluetoothKit和Core Bluetooth之上的一层。 我构建了它以无缝,反应式的方式与心率监测器进行交互。
您可以下载该项目并进行尝试。
它有什么作用?
- 仅列出心率监测器。
- 连接和断开监视器。
- 从监视器读取心率。
- 记住以前连接的显示器。
- 自动连接到以前连接的显示器。
- 读取蓝牙状态。
- 读取监视器状态。
在本文中,我将解释有关该项目的一些细节。 为什么创建它以及一些实现细节。
我正在作为一个团队的一部分来构建健身应用程序。 该应用程序的要求之一是列出可以使用的心率监测器。 同样,用户应该能够连接并从此类设备读取值。
我以为CoreBluetooth将使这项工作变得容易。 事实并非如此。
核心蓝牙太通用
它抽象了BTLE协议栈,提供了与各种设备进行交互的方式。
发现外围设备非常容易。 但是随后您还需要发现其服务,特征和代码。 最后,您需要读取原始数据并将其转换为正确的格式。
代码可能变得非常复杂。 为了给您一个想法,以下是从监视器读取心率值所需的步骤:
- 启动中央管理器。
- 发现外围设备( 需要一名代表 )
- 过滤提供心率监测服务的外围设备
- 连接到外围设备( 需要委托 )
- 发现该外围设备的服务( 需要委托 )
- 发现服务的特征( 需要委托 )
- 找到代表心率的特征
- 订阅特征值( 需要委托 )
- 将原始数据转换为正确的格式。
实现必需的委托需要太多代码。 如果您看一下本教程或本文,则可以了解其复杂性。 苹果公司也有一个例子(在Objective-C中)。
复杂性很高,因为Core Bluetooth是通用的。 它的构建使您可以连接到任何类型的BTLE设备,而不仅仅是HR监视器。
RxBluetoothKit很有帮助!
RxBluetoothKit是Core Bluetooth的一个很好的包装。 它实现了所有委托功能,并为框架提供了反应式接口。 而不是编写所有这些委托,而是编写声明式反应式代码。
对我来说,这是一个很大的进步。 它使事情变得简单得多。 例如,扫描设备并从第一个设备获取特征:
代码更少,但仍有很多事情需要解决。 您仍然需要阅读服务,特征并格式化数据。
我想连接显示器并观察心律。
问题很简单。 但是,即使使用RxBluetoothKit,解决方案也不是那么简单。 当我使用此工具时,我意识到RxBluetoothKit与我所需要的之间存在差距。
代码应该更简单。 这就是为什么我创建RxHeartRateMonitors的原因。
同样,该想法是仅以无缝方式与心率监视器进行最佳交互,从而减少编写代码。
仅列出HR Monitor。
我想看到人力资源监视器,而不是恒温器或速度计之类的其他设备。 我let heartRateMonitors : Observable
。 所以我可以做一些事情,例如将它们显示在桌子上:
连接/断开
连接和断开显示器的连接应该很容易。 调用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设备进行交互)有很大帮助。 您可以阅读我撰写的有关该主题的另一篇文章。
你喜欢这篇文章吗? 请随时留下评论。 我希望得到一些反馈!