diff --git a/Package.swift b/Package.swift index f6f9f61..49e2ed8 100644 --- a/Package.swift +++ b/Package.swift @@ -38,7 +38,7 @@ let package = Package( .package(url: "https://github.com/StanfordSpezi/SpeziViews.git", from: "1.5.0"), .package(url: "https://github.com/StanfordSpezi/SpeziBluetooth", from: "2.0.0"), .package(url: "https://github.com/StanfordSpezi/SpeziNetworking", from: "2.1.1"), - .package(url: "https://github.com/StanfordBDHG/XCTestExtensions.git", .upToNextMinor(from: "0.4.11")) + .package(url: "https://github.com/StanfordBDHG/XCTestExtensions.git", .upToNextMinor(from: "0.4.12")) ] + swiftLintPackage(), targets: [ .target( diff --git a/Sources/SpeziDevices/Devices/PairableDevice.swift b/Sources/SpeziDevices/Devices/PairableDevice.swift index 6786d67..0698764 100644 --- a/Sources/SpeziDevices/Devices/PairableDevice.swift +++ b/Sources/SpeziDevices/Devices/PairableDevice.swift @@ -34,6 +34,7 @@ public protocol PairableDevice: GenericDevice { /// ``` /// var connect: BluetoothConnectAction { get } + /// Disconnect action. /// /// Use the [`DeviceAction`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/deviceaction) property wrapper to diff --git a/Sources/SpeziDevices/HealthMeasurements.swift b/Sources/SpeziDevices/HealthMeasurements.swift index 2ae0d64..1be11c1 100644 --- a/Sources/SpeziDevices/HealthMeasurements.swift +++ b/Sources/SpeziDevices/HealthMeasurements.swift @@ -17,7 +17,7 @@ import SwiftUI /// Manage and process health measurements from nearby Bluetooth Peripherals. /// -/// Use the `HealthMeasurements` module to collect health measurements from nearby Bluetooth Peripherals like connected weight scales or +/// Use the `HealthMeasurements` module to collect health measurements from nearby Bluetooth devices like connected weight scales or /// blood pressure cuffs. /// - Note: Implement your device as a [`BluetoothDevice`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/bluetoothdevice) /// using [SpeziBluetooth](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth). @@ -66,7 +66,7 @@ import SwiftUI /// ``` /// /// - Important: Don't forget to configure the `HealthMeasurements` module in -/// your [`SpeziAppDelegate`](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/speziappdelegate) +/// your [`SpeziAppDelegate`](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/speziappdelegate). /// /// ## Topics /// diff --git a/Sources/SpeziDevices/Measurements/StoredMeasurement.swift b/Sources/SpeziDevices/Measurements/StoredMeasurement.swift index 92b8fb5..93a2322 100644 --- a/Sources/SpeziDevices/Measurements/StoredMeasurement.swift +++ b/Sources/SpeziDevices/Measurements/StoredMeasurement.swift @@ -26,7 +26,7 @@ private struct CodableHKDevice { /// Copy of the `BloodPressureMeasurement` type that just uses plain RawValue types to work around SwiftData coding issues and crashes. -private struct BloodPressureMeasurementCopy { +private struct BloodPressureMeasurementSwiftDataWorkaroundContainer { // swiftlint:disable:this type_name let systolicValue: UInt16 let diastolicValue: UInt16 let meanArterialPressure: UInt16 @@ -75,7 +75,7 @@ private struct SwiftDataBluetoothHealthMeasurementWorkaroundContainer { private let type: MeasurementType - private var bloodPressureMeasurement: BloodPressureMeasurementCopy? + private var bloodPressureMeasurement: BloodPressureMeasurementSwiftDataWorkaroundContainer? private var bloodPressureFeatures: BloodPressureFeature.RawValue? private var weightMeasurement: WeightMeasurement? @@ -172,7 +172,7 @@ extension CodableHKDevice { } -extension BloodPressureMeasurementCopy: Codable { +extension BloodPressureMeasurementSwiftDataWorkaroundContainer: Codable { enum CodingKeys: CodingKey { case systolicValue case diastolicValue @@ -224,7 +224,10 @@ extension SwiftDataBluetoothHealthMeasurementWorkaroundContainer: Codable { self.type = try container.decode(SwiftDataBluetoothHealthMeasurementWorkaroundContainer.MeasurementType.self, forKey: .type) switch type { case .bloodPressure: - self.bloodPressureMeasurement = try container.decodeIfPresent(BloodPressureMeasurementCopy.self, forKey: .bloodPressureMeasurement) + self.bloodPressureMeasurement = try container.decodeIfPresent( + BloodPressureMeasurementSwiftDataWorkaroundContainer.self, + forKey: .bloodPressureMeasurement + ) self.bloodPressureFeatures = try container.decodeIfPresent(BloodPressureFeature.RawValue.self, forKey: .bloodPressureFeatures) case .weight: self.weightMeasurement = try container.decodeIfPresent(WeightMeasurement.self, forKey: .weightMeasurement) diff --git a/Sources/SpeziDevices/Model/PairingContinuation.swift b/Sources/SpeziDevices/Model/PairingContinuation.swift index 242b952..de1dddf 100644 --- a/Sources/SpeziDevices/Model/PairingContinuation.swift +++ b/Sources/SpeziDevices/Model/PairingContinuation.swift @@ -43,4 +43,4 @@ final class PairingContinuation { } -extension PairingContinuation: @unchecked Sendable {} +extension PairingContinuation {} diff --git a/Sources/SpeziDevices/PairedDevices.swift b/Sources/SpeziDevices/PairedDevices.swift index e5df929..2fc8be1 100644 --- a/Sources/SpeziDevices/PairedDevices.swift +++ b/Sources/SpeziDevices/PairedDevices.swift @@ -18,15 +18,19 @@ import SwiftUI /// Persistently pair with Bluetooth devices and automatically manage connections. /// -/// Use the `PairedDevices` module to discover and pair ``PairedDevices`` and automatically manage connection establishment +/// Use the `PairedDevices` module to discover and pair ``PairableDevice``s and automatically manage connection establishment /// of connected devices. /// - Note: Implement your device as a [`BluetoothDevice`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/bluetoothdevice) /// using [SpeziBluetooth](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth). /// -/// To support `PairedDevices`, you need to adopt the ``PairedDevices`` protocol for your device. -/// Optionally you can adopt ``BatteryPoweredDevice`` if your device supports the `BatteryService`. +/// To support `PairedDevices`, you need to adopt the ``PairableDevice`` protocol for your device. +/// Optionally you can adopt ``BatteryPoweredDevice`` if your device supports the +/// [`BatteryService`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/batteryservice). /// Once your device is loaded, register it with the `PairedDevices` module by calling the ``configure(device:accessing:_:_:)`` method. /// +/// - Important: Don't forget to configure the `PairedDevices` module in +/// your [`SpeziAppDelegate`](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/speziappdelegate). +/// /// ```swift /// import SpeziDevices /// @@ -60,13 +64,12 @@ import SwiftUI /// } /// ``` /// -/// To display and manage paired devices and support adding new paired devices, you can use the full-featured ``DevicesTab`` view. +/// - Tip: To display and manage paired devices and support adding new paired devices, you can use the full-featured ``DevicesTab`` view. /// /// ## Topics /// /// ### Configuring Paired Devices /// - ``init()`` -/// - ``init(_:)`` /// /// ### Register Devices /// - ``configure(device:accessing:_:_:)`` diff --git a/Sources/SpeziDevices/SpeziDevices.docc/HealthKit.md b/Sources/SpeziDevices/SpeziDevices.docc/HealthKit.md index 0599757..4a736b4 100644 --- a/Sources/SpeziDevices/SpeziDevices.docc/HealthKit.md +++ b/Sources/SpeziDevices/SpeziDevices.docc/HealthKit.md @@ -14,14 +14,34 @@ SPDX-License-Identifier: MIT ## Overview -Text +SpeziDevices helps developers converting measurements received from Bluetooth devices to HealthKit sample types. +### Device Information + +As soon as you conform your [SpeziBluetooth `BluetoothDevice`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/bluetoothdevice) +to the ``HealthDevice`` protocol and implement the [`DeviceInformationService`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/deviceinformationservice), +you can access the [`HKDevice`](https://developer.apple.com/documentation/healthkit/hkdevice) +description using the ``HealthDevice/hkDevice-32s1d`` property + +### Converting Measurements + +SpeziDevices can convert your Bluetooth Health Measurement characteristics into HealthKit samples. +This is support for characteristics like [`BloodPressureMeasurement`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/bloodpressuremeasurement) +or [`WeightMeasurement`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/weightmeasurement). + +Use methods like ``SpeziBluetoothServices/BloodPressureMeasurement/bloodPressureSample(source:)`` or +``SpeziBluetoothServices/WeightMeasurement/weightSample(source:resolution:)`` to convert these measurements to their respective HealthKit Sample +representation. + +> Tip: By using the [`resource`](https://swiftpackageindex.com/stanfordbdhg/healthkitonfhir/documentation/healthkitonfhir/healthkit/hksample/resource) + provided through [`HealthKitOnFHIR`](https://swiftpackageindex.com/StanfordBDHG/HealthKitOnFHIR/documentation/healthkitonfhir) you can convert + your Bluetooth measurements to [HL7 FHIR Observation Resources](http://hl7.org/fhir/R4/observation.html). ## Topics ### Device -- ``HealthDevice/hkDevice`` +- ``HealthDevice/hkDevice-32s1d`` ### Blood Pressure Measurement diff --git a/Sources/SpeziDevices/SpeziDevices.docc/SpeziDevices.md b/Sources/SpeziDevices/SpeziDevices.docc/SpeziDevices.md index cde5efa..aea6080 100644 --- a/Sources/SpeziDevices/SpeziDevices.docc/SpeziDevices.md +++ b/Sources/SpeziDevices/SpeziDevices.docc/SpeziDevices.md @@ -1,6 +1,6 @@ # ``SpeziDevices`` -Summary +Support interactions with Bluetooth Devices. Summary +Visualize Bluetooth device interactions. Text +SpeziDevicesUI helps you to visualize Bluetooth device state and communicate interactions to the user. ## Topics @@ -32,7 +32,7 @@ Views that are helpful when building a nearby devices view. ### Paired Devices -- ``DevicesTab`` +- ``DevicesView`` - ``DevicesGrid`` - ``DeviceTile`` - ``DeviceDetailsView`` diff --git a/Sources/SpeziOmron/SpeziOmron.docc/SpeziOmron.md b/Sources/SpeziOmron/SpeziOmron.docc/SpeziOmron.md index 7e9bdc0..73f844d 100644 --- a/Sources/SpeziOmron/SpeziOmron.docc/SpeziOmron.md +++ b/Sources/SpeziOmron/SpeziOmron.docc/SpeziOmron.md @@ -1,6 +1,6 @@ # ``SpeziOmron`` -Summary +Support interactions with Omron Bluetooth Devices. Text +SpeziOmron extends SpeziDevices with support for Omron devices. This includes Omron-specific models, characteristics, services and fully reusable +device support. + +### Omron Devices + + + +- models (e.g., manufcaturer data) +- characteristic & services +- device implementations ## Topics diff --git a/Tests/SpeziDevicesTests/PairedDevicesTests.swift b/Tests/SpeziDevicesTests/PairedDevicesTests.swift index 00d75c9..57cc2e5 100644 --- a/Tests/SpeziDevicesTests/PairedDevicesTests.swift +++ b/Tests/SpeziDevicesTests/PairedDevicesTests.swift @@ -177,7 +177,6 @@ final class PairedDevicesTests: XCTestCase { await device.disconnect() try await XCTAssertThrowsErrorAsync(await task.value) { error in - print(error) XCTAssertEqual(try XCTUnwrap(error as? DevicePairingError), .deviceDisconnected) } diff --git a/Tests/UITests/TestApp/DevicesTestView.swift b/Tests/UITests/TestApp/DevicesTestView.swift index b43665c..6172694 100644 --- a/Tests/UITests/TestApp/DevicesTestView.swift +++ b/Tests/UITests/TestApp/DevicesTestView.swift @@ -34,7 +34,7 @@ struct DevicesTestView: View { var body: some View { NavigationStack { - DevicesTab(appName: "TestApp", pairingHint: "Enable pairing mode on the device.") + DevicesView(appName: "TestApp", pairingHint: "Enable pairing mode on the device.") .toolbar { ToolbarItemGroup(placement: .secondaryAction) { Button("Discover Device", systemImage: "plus.rectangle.fill.on.rectangle.fill") {