generated from StanfordSpezi/SpeziTemplateApplication
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Connect to weight scale, Save and display recorded measurements ## ♻️ Current situation & Problem Currently, the application is unable to connect to the weight scale, record weight measurements, and save them to cloud storage. ## ⚙️ Release Notes - Application now automatically connects to nearest device advertising the Weight Scale Service as defined in the Bluetooth LE protocol. - If the device is new, the application will prompt the user to pair the device. - New measurements are managed by the MeasurementManager class. - When a new weight measurement is recorded, a sheet will appear prompting the user to confirm it, and either save or discard the new measurement. This will appear over any tab of the home view, wherever the user happens to be at the time. - If the user selects save, the measurement is converted to an Apple HealthKit HKQuantitySample, then uploaded to cloud storage (Firestore) as a FHIR Observation via HealthkitOnFHIR. - Also edited the Github action workflow for building and testing to fix a bug preventing previous PR's from passing. This related to the test runs not being signed into a Google Firebase account. ## 📚 Documentation More thorough in-line documentation will be included along with testing in the next PR. ## ✅ Testing UI Tests will be implemented in the next PR. ### 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). --------- Co-authored-by: Paul Schmiedmayer <[email protected]>
- Loading branch information
1 parent
15b47f6
commit 9e3715d
Showing
20 changed files
with
982 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
ENGAGEHF/Bluetooth/Devices/WeightScale/Characteristics/WeightMeasurement.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// | ||
// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import BluetoothServices | ||
import ByteCoding | ||
import Foundation | ||
import NIOCore | ||
|
||
|
||
enum WeightUnits: String, Equatable { | ||
case metric = "kg" | ||
case imperial = "lb" | ||
} | ||
|
||
|
||
struct WeightMeasurement: Equatable { | ||
// Flags | ||
let units: WeightUnits | ||
let timeStampPresent: Bool | ||
let userIDPresent: Bool | ||
let heightBMIPresent: Bool | ||
|
||
// Units: | ||
// Kilograms with a resolution of 0.005 | ||
// Pounds with a resolution of 0.01 | ||
let weight: UInt16 | ||
|
||
// Only present when corresponding flag is true | ||
let timeStamp: DateTime? | ||
let bmi: UInt16? | ||
let height: UInt16? | ||
let userID: UInt8? | ||
} | ||
|
||
|
||
extension WeightMeasurement: ByteDecodable { | ||
init?(from byteBuffer: inout NIOCore.ByteBuffer, preferredEndianness endianness: NIOCore.Endianness) { | ||
guard byteBuffer.readableBytes >= 11 else { | ||
return nil | ||
} | ||
|
||
// Decode fields as described in the manual | ||
guard let flagBits = UInt8(from: &byteBuffer, preferredEndianness: endianness), | ||
let weight = UInt16(from: &byteBuffer, preferredEndianness: endianness) else { | ||
return nil | ||
} | ||
|
||
// Extract flags | ||
let timeStampFlag: Bool = ((flagBits >> 1) & 0b1) != 0 | ||
let userIDFlag: Bool = ((flagBits >> 2) & 0b1) != 0 | ||
let heightBMIFlag: Bool = ((flagBits >> 3) & 0b1) != 0 | ||
|
||
// Get the time stamp | ||
if timeStampFlag { | ||
guard let timeStamp = DateTime(from: &byteBuffer, preferredEndianness: endianness) else { | ||
return nil | ||
} | ||
|
||
self.timeStamp = timeStamp | ||
} else { | ||
self.timeStamp = nil | ||
} | ||
|
||
if userIDFlag { | ||
guard let userID = UInt8(from: &byteBuffer, preferredEndianness: endianness) else { | ||
return nil | ||
} | ||
|
||
self.userID = userID | ||
} else { | ||
self.userID = nil | ||
} | ||
|
||
if heightBMIFlag { | ||
guard let bmi = UInt16(from: &byteBuffer), | ||
let height = UInt16(from: &byteBuffer) else { | ||
return nil | ||
} | ||
|
||
self.bmi = bmi | ||
self.height = height | ||
} else { | ||
self.bmi = nil | ||
self.height = nil | ||
} | ||
|
||
self.units = { | ||
if (flagBits & 1) == 1 { | ||
return .imperial | ||
} else { | ||
return .metric | ||
} | ||
}() | ||
|
||
|
||
self.timeStampPresent = timeStampFlag | ||
self.heightBMIPresent = heightBMIFlag | ||
self.userIDPresent = userIDFlag | ||
self.weight = weight | ||
} | ||
} |
Oops, something went wrong.