SpeziDevices

Build and Test codecov DOI

支持与蓝牙设备交互。

概述

SpeziDevices 提供了三个不同的目标:SpeziDevicesSpeziDevicesUISpeziOmron

Screenshot showing paired devices in a grid layout. A sheet is presented in the foreground showing a nearby devices able to pair. Screenshot showing paired devices in a grid layout. A sheet is presented in the foreground showing a nearby devices able to pair. Displaying the device details of a paired device with information like Model number and battery percentage. Displaying the device details of a paired device with information like Model number and battery percentage. Showing a newly recorded blood pressure measurement. Showing a newly recorded blood pressure measurement.
使用 DevicesView 以网格布局显示已配对的设备。 使用 DeviceDetailsView 显示设备详情。 使用 MeasurementsRecordedSheet 显示记录的测量值。

SpeziDevices

SpeziDevices 抽象了与蓝牙设备的常见交互,这些交互使用 SpeziBluetooth 实现。它支持与设备配对并处理健康测量数据。

配对设备

配对设备是一种很好的方式,可以确保您的应用程序仅连接到固定的设备集,并且不接受来自未经授权的设备的数据。此外,可能需要确保某些操作保持安全。

使用 PairedDevices 模块来发现和配对 PairableDevice,并自动管理已连接设备的连接建立。

为了支持 PairedDevices,您需要为您的设备采用 PairableDevice 协议。如果您的设备支持 BatteryService,您可以选择采用 BatteryPoweredDevice 协议。加载设备后,通过调用 PairedDevices/configure(device:accessing:_:_:) 方法,将其注册到 PairedDevices 模块。

重要提示

不要忘记在您的 SpeziAppDelegate 中配置 PairedDevices 模块。

import SpeziDevices

class MyDevice: PairableDevice {
    @DeviceState(\.id) var id
    @DeviceState(\.name) var name
    @DeviceState(\.state) var state
    @DeviceState(\.advertisementData) var advertisementData
    @DeviceState(\.nearby) var nearby

    @Service var deviceInformation = DeviceInformationService()

    @DeviceAction(\.connect) var connect
    @DeviceAction(\.disconnect) var disconnect

    var isInPairingMode: Bool {
        // determine if a nearby device is in pairing mode
    }

    @Dependency private var pairedDevices: PairedDevices?

    required init() {}

    func configure() {
        pairedDevices?.configure(device: self, accessing: $state, $advertisementData, $nearby)
    }

    func handleSuccessfulPairing() { // called on events where a device can be considered paired (e.g., incoming notifications)
        pairedDevices?.signalDevicePaired(self)
    }
}

提示

要显示和管理已配对的设备并支持添加新的已配对设备,您可以使用功能齐全的 DevicesView

健康测量

使用 HealthMeasurements 模块从附近的蓝牙设备(如连接的体重秤或血压袖带)收集健康测量数据。

为了支持 HealthMeasurements,您需要为您的设备采用 HealthDevice 协议。加载设备后,通过调用 configureReceivingMeasurements(for:on:) 的合适变体,将其测量服务注册到 HealthMeasurements 模块。

import SpeziDevices

class MyDevice: HealthDevice {
    @Service var deviceInformation = DeviceInformationService()
    @Service var weightScale = WeightScaleService()

    @Dependency private var measurements: HealthMeasurements?

    required init() {}

    func configure() {
        measurements?.configureReceivingMeasurements(for: self, on: weightScale)
    }
}

要向用户显示新的测量值并将它们保存到您的外部数据存储中,您可以使用 MeasurementsRecordedSheet。以下是一个简短的代码示例。

import SpeziDevices
import SpeziDevicesUI

struct MyHomeView: View {
    @Environment(HealthMeasurements.self) private var measurements

    var body: some View {
        @Bindable var measurements = measurements
        ContentView()
            .sheet(isPresented: $measurements.shouldPresentMeasurements) {
                MeasurementsRecordedSheet { measurement in
                    // handle saving the measurement
                }
            }
    }
}

重要提示

不要忘记在您的 SpeziAppDelegate 中配置 HealthMeasurements 模块。

SpeziDevicesUI

SpeziDevicesUI 可帮助您可视化蓝牙设备状态并将交互传达给用户。

显示已配对的设备

当使用 PairedDevices 管理已配对的设备时,SpeziDevicesUI 提供了可重用的 View 组件来显示已配对的设备。

DevicesView 提供了配对和管理已配对设备所需的一切。 它使用 DevicesGrid 在网格布局中显示已经配对的设备。 此外,它还在工具栏中放置一个添加按钮,以使用 AccessorySetupSheet 视图发现新设备。

struct MyHomeView: View {
    var body: some View {
        TabView {
            NavigationStack {
                DevicesView(appName: "Example") {
                    Text("Provide helpful pairing instructions to the user.")
                }
            }
                .tabItem {
                    Label("Devices", systemImage: "sensor.fill")
                }
        }
    }
}

显示测量值

当使用 HealthMeasurements 管理测量值时,您可以使用 MeasurementsRecordedSheet 来显示待处理的测量值。 以下是一个关于如何配置此视图的简短代码示例。

struct MyHomeView: View {
    @Environment(HealthMeasurements.self) private var measurements

    var body: some View {
        @Bindable var measurements = measurements
        ContentView()
            .sheet(isPresented: $measurements.shouldPresentMeasurements) {
                MeasurementsRecordedSheet { samples in
                    // save the array of HKSamples
                }
            }
    }
}

重要提示

不要忘记在您的 SpeziAppDelegate 中配置 HealthMeasurements 模块。

SpeziOmron

SpeziOmron 通过支持 Omron 设备扩展了 SpeziDevices。 这包括 Omron 特定的模型、特征、服务和完全可重用的设备支持。

Omron 设备

OmronBloodPressureCuffOmronWeightScale 设备分别为 Omron 血压袖带和 Omron 体重秤提供了可重用的设备实现。 这两个设备都自动与 SpeziDevices 的 HealthMeasurementsPairedDevices 模块集成。 您只需要配置它们以与 Bluetooth 模块一起使用。

import SpeziBluetooth
import SpeziBluetoothServices
import SpeziDevices
import SpeziOmron

class ExampleAppDelegate: SpeziAppDelegate {
    override var configuration: Configuration {
        Configuration {
            Bluetooth {
                Discover(OmronBloodPressureCuff.self, by: .advertisedService(BloodPressureService.self))
                Discover(OmronWeightScale.self, by: .advertisedService(WeightScaleService.self))
            }

            // If required, configure the PairedDevices and HealthMeasurements modules
            PairedDevices()
            HealthMeasurements()
        }
    }
}

设置

您需要将 SpeziDevices Swift 包添加到 Xcode 中的您的应用Swift 包中。

许可证

此项目根据 MIT 许可证获得许可。 有关更多信息,请参见 许可证

贡献者

此项目是斯坦福大学斯坦福 Byers 生物设计中心的一部分开发。 有关所有 TemplatePackage 贡献者的完整列表,请参见 CONTRIBUTORS.md

Stanford Byers Center for Biodesign Logo Stanford Byers Center for Biodesign Logo