Skip to content

Commit

Permalink
Introduce Omron Device Pairing (#16)
Browse files Browse the repository at this point in the history
# Introduce Omron Device Pairing

## ♻️ Current situation & Problem
This PR changes how we handle device interaction with Omron devices.
Instead of continuously browsing for weigh scale and blood pressure
devices in the environment, the user pairs with a specific Omron devices
via the new Devices Tab. The devices tab shows all currently paired
devices, their connection status (currently connected vs. last seen) and
additional information like battery. Further, it provides
customizability to name your devices.

## ⚙️ Release Notes 
* Integrate Omron device pairing.
* Rework measurement retrieval to support visualizing multiple
measurements
* Use SpeziDevices to host measurement conversion and device pairing
functionality.


## 📚 Documentation
--


## ✅ Testing
Functionality is tested as part of the SpeziDevices package.
Functionality was manually verified using real Omron devices.


### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
Supereg authored Jul 2, 2024
1 parent fc3175f commit 78ef6fa
Show file tree
Hide file tree
Showing 38 changed files with 288 additions and 1,420 deletions.
1 change: 0 additions & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ jobs:
with:
artifactname: ENGAGEHF.xcresult
runsonlabels: '["macOS", "self-hosted"]'
setupSimulators: true
setupfirebaseemulator: true
fastlanelane: test
firebaseemulatorimport: ./firebase
Expand Down
215 changes: 49 additions & 166 deletions ENGAGEHF.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "4680bbbdca4179318420f5e90c76b7b5892a3fbaf02dc6668d80ce474e195a4d",
"originHash" : "bf5084f3a1640b549abaeb7502f3d1650efe31a71ce63ae49ff0fb7732a037e2",
"pins" : [
{
"identity" : "abseil-cpp-binary",
Expand Down Expand Up @@ -105,8 +105,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/gtm-session-fetcher.git",
"state" : {
"revision" : "0382ca27f22fb3494cf657d8dc356dc282cd1193",
"version" : "3.4.1"
"revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b",
"version" : "3.5.0"
}
},
{
Expand Down Expand Up @@ -169,7 +169,7 @@
"location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR",
"state" : {
"revision" : "dcd5f95522ed02a873b03c9638dbf397b99c74e0",
"version" : "1.4.0"
"version" : "2.0.0"
}
},
{
Expand Down Expand Up @@ -204,8 +204,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziBluetooth.git",
"state" : {
"revision" : "f3b8cc8461f12268b15db17aa45cc66b889cd1d0",
"version" : "1.6.0"
"revision" : "6b88cae1ea9a18ec875dcc8fae80cbeb291133f0",
"version" : "2.0.1"
}
},
{
Expand All @@ -217,6 +217,15 @@
"version" : "1.0.0"
}
},
{
"identity" : "spezidevices",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziDevices.git",
"state" : {
"revision" : "6b5e24f9983ae0ffccd57d078edb3981400af721",
"version" : "1.0.0"
}
},
{
"identity" : "spezifirebase",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -258,8 +267,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziNetworking",
"state" : {
"revision" : "71236efc911d5580fbf4d53748f38ad22ef00a2d",
"version" : "1.0.0"
"revision" : "b01333fbe46bc02445cc06a1d721bc490d77d95e",
"version" : "2.1.2"
}
},
{
Expand All @@ -276,8 +285,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziQuestionnaire.git",
"state" : {
"revision" : "76732ebcb0b521fa94d41c38a5fe35e6e1a87173",
"version" : "1.2.1"
"revision" : "853585fbdd5d2d0af440c805d629a025ef5545d9",
"version" : "1.2.2"
}
},
{
Expand Down Expand Up @@ -330,8 +339,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "e5a216ba89deba84356bad9d4c2eab99071c745b",
"version" : "2.67.0"
"revision" : "fc79798d5a150d61361a27ce0c51169b889e23de",
"version" : "2.68.0"
}
},
{
Expand Down Expand Up @@ -402,8 +411,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/XCTestExtensions.git",
"state" : {
"revision" : "1fe9b8e76aeb7a132af37bfa0892160c9b662dcc",
"version" : "0.4.10"
"revision" : "cc2705fde81978eacd5496e14c9caf58909e2322",
"version" : "0.4.12"
}
},
{
Expand Down
17 changes: 12 additions & 5 deletions ENGAGEHF.xcodeproj/xcshareddata/xcschemes/ENGAGEHF.xcscheme
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1530"
LastUpgradeVersion = "1540"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down Expand Up @@ -83,23 +83,23 @@
</CommandLineArgument>
<CommandLineArgument
argument = "--assumeOnboardingComplete"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--setupTestEnvironment"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--testMockDevices"
isEnabled = "NO">
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--skipOnboarding"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--skipOnboarding"
isEnabled = "NO">
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "--skipOnboarding"
Expand All @@ -114,6 +114,13 @@
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "IDEPreferLogStreaming"
value = "YES"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
38 changes: 21 additions & 17 deletions ENGAGEHF/Dashboard/Dashboard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
// SPDX-License-Identifier: MIT
//

@_spi(TestingSupport) import SpeziDevices
import SwiftUI


struct Dashboard: View {
@Binding var presentingAccount: Bool

#if DEBUG || TEST
@Environment(MeasurementManager.self) private var measurementManager
@Environment(HealthMeasurements.self) private var measurements
#endif


Expand All @@ -29,26 +30,29 @@ struct Dashboard: View {
}
.padding()
}
.background(Color(.systemGroupedBackground))
.navigationTitle("Home")
.toolbar {
if AccountButton.shouldDisplay {
AccountButton(isPresented: $presentingAccount)
.background(Color(.systemGroupedBackground))
.navigationTitle("Home")
.toolbar {
if AccountButton.shouldDisplay {
AccountButton(isPresented: $presentingAccount)
}
}
}
#if DEBUG || TEST
.toolbar {
if FeatureFlags.testMockDevices {
ToolbarItemGroup(placement: .secondaryAction) {
Button("Trigger Weight Measurement", systemImage: "scalemass.fill") {
measurementManager.loadMockWeightMeasurement()
}
Button("Trigger Blood Pressure Measurement", systemImage: "drop.fill") {
measurementManager.loadMockBloodPressureMeasurement()
.toolbar {
if FeatureFlags.testMockDevices {
ToolbarItemGroup(placement: .secondaryAction) {
Button("Trigger Weight Measurement", systemImage: "scalemass.fill") {
measurements.loadMockWeightMeasurement()
}
Button("Trigger Blood Pressure Measurement", systemImage: "drop.fill") {
measurements.loadMockBloodPressureMeasurement()
}
Button("Show Measurements", systemImage: "heart.text.square") {
measurements.shouldPresentMeasurements = true
}
}
}
}
}
#endif
}
}
Expand All @@ -60,7 +64,7 @@ struct Dashboard: View {
Dashboard(presentingAccount: .constant(false))
.previewWith(standard: ENGAGEHFStandard()) {
NotificationManager()
MeasurementManager()
HealthMeasurements(mock: [.weight(.mockWeighSample)])
VitalsManager()
}
}
Expand Down
12 changes: 6 additions & 6 deletions ENGAGEHF/Dashboard/Notifications/NotificationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class NotificationManager: Module, EnvironmentAccessible {
if FeatureFlags.setupTestEnvironment, let user {
// Make sure to not load the mock notifications multiple times
if let notifications = self?.notifications, notifications.isEmpty {
Task {
Task { [weak self] in
try await self?.setupNotificationTests(user: user)
}
}
Expand Down Expand Up @@ -99,8 +99,8 @@ class NotificationManager: Module, EnvironmentAccessible {
///
/// Creates a snapshot listener to save new notifications to the manager as they are added to the user's directory in Firebase
func registerSnapshotListener(user: User?) {
logger.info("Initializing notifiation snapshot listener...")
logger.info("Initializing notification snapshot listener...")

// Remove previous snapshot listener for the user before creating new one
snapshotListener?.remove()
guard let uid = user?.uid else {
Expand Down Expand Up @@ -139,12 +139,12 @@ class NotificationManager: Module, EnvironmentAccessible {
return
}

logger.debug("Marking notitification complete with the following id: \(id)")
logger.debug("Marking notification complete with the following id: \(id)")

let firestore = Firestore.firestore()

guard let user = Auth.auth().currentUser else {
logger.error("Unable to mark notitificaitons complete: \(FetchingError.userNotAuthenticated)")
logger.error("Unable to mark notifications complete: \(FetchingError.userNotAuthenticated)")
return
}

Expand Down
52 changes: 30 additions & 22 deletions ENGAGEHF/Dashboard/Vitals/Views/RecentVitalsSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
//

import HealthKit
@_spi(TestingSupport) import SpeziDevices
import SwiftUI


struct RecentVitalsSection: View {
@Environment(VitalsManager.self) private var vitalsManager

@Environment(HealthMeasurements.self) private var measurements


private var massUnits: HKUnit {
switch Locale.current.measurementSystem {
Expand Down Expand Up @@ -58,33 +60,38 @@ struct RecentVitalsSection: View {


var body: some View {
Section(
content: {
VStack {
HStack {
VitalsCard(
type: "Weight",
units: massUnits.unitString,
measurement: weightMeasurement
)
VitalsCard(
type: "Heart Rate",
units: "BPM",
measurement: heartRateMeasurement
)
}
Section {
VStack {
HStack {
VitalsCard(
type: "Weight",
units: massUnits.unitString,
measurement: weightMeasurement
)
VitalsCard(
type: "Blood Pressure",
units: "mmHg",
measurement: bloodPressureMeasurement
type: "Heart Rate",
units: "BPM",
measurement: heartRateMeasurement
)
}
},
header: {
VitalsCard(
type: "Blood Pressure",
units: "mmHg",
measurement: bloodPressureMeasurement
)
}
} header: {
HStack {
Text("Recent Vitals")
.studyApplicationHeaderStyle()
Spacer()
if !measurements.pendingMeasurements.isEmpty {
Button("Review", systemImage: "heart.text.square") {
measurements.shouldPresentMeasurements = true
}
}
}
)
}
}


Expand Down Expand Up @@ -118,5 +125,6 @@ struct RecentVitalsSection: View {
RecentVitalsSection()
.previewWith(standard: ENGAGEHFStandard()) {
VitalsManager()
HealthMeasurements(mock: [.weight(.mockWeighSample)])
}
}
Loading

0 comments on commit 78ef6fa

Please sign in to comment.