Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BeeKit/HeathKit/CategoryHealthKitMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class CategoryHealthKitMetric : HealthKitMetric {
public let category : HealthKitCategory
let hkSampleType : HKSampleType

public var precision: [HKUnit : Int] { [:] }

internal init(humanText: String, databaseString: String, category : HealthKitCategory, hkSampleType: HKSampleType) {
self.humanText = humanText
self.databaseString = databaseString
Expand Down
4 changes: 2 additions & 2 deletions BeeKit/HeathKit/HealthKitConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum HealthKitConfig {
// Activity
QuantityHealthKitMetric(humanText: "Active energy", databaseString: "activeEnergy", category: .Activity, hkQuantityTypeIdentifier: .activeEnergyBurned, precision: [HKUnit.largeCalorie(): 0]),
QuantityHealthKitMetric(humanText: "Cycling distance", databaseString: "cyclingDistance", category: .Activity, hkQuantityTypeIdentifier: .distanceCycling),
QuantityHealthKitMetric(humanText: "Exercise time", databaseString: "exerciseTime", category: .Activity, hkQuantityTypeIdentifier: .appleExerciseTime),
QuantityHealthKitMetric(humanText: "Exercise time", databaseString: "exerciseTime", category: .Activity, hkQuantityTypeIdentifier: .appleExerciseTime, precision: [HKUnit.minute(): 1]),
QuantityHealthKitMetric(humanText: "Nike Fuel", databaseString: "nikeFuel", category: .Activity, hkQuantityTypeIdentifier: .nikeFuel),
QuantityHealthKitMetric(humanText: "Resting energy", databaseString: "basalEnergy", category: .Activity, hkQuantityTypeIdentifier: .basalEnergyBurned, precision: [HKUnit.largeCalorie(): 0]),
StandHoursHealthKitMetric(humanText: "Stand hours", databaseString: "standHour", category: .Activity),
Expand Down Expand Up @@ -49,7 +49,7 @@ public enum HealthKitConfig {
QuantityHealthKitMetric(humanText: "Vitamin D", databaseString: "dietaryVitaminD", category: .Nutrition, hkQuantityTypeIdentifier: .dietaryVitaminD),
QuantityHealthKitMetric(humanText: "Vitamin E", databaseString: "dietaryVitaminE", category: .Nutrition, hkQuantityTypeIdentifier: .dietaryVitaminE),
QuantityHealthKitMetric(humanText: "Vitamin K", databaseString: "dietaryVitaminK", category: .Nutrition, hkQuantityTypeIdentifier: .dietaryVitaminK),
QuantityHealthKitMetric(humanText: "Water", databaseString: "water", category: .Nutrition, hkQuantityTypeIdentifier: .dietaryWater),
QuantityHealthKitMetric(humanText: "Water", databaseString: "water", category: .Nutrition, hkQuantityTypeIdentifier: .dietaryWater, precision: [HKUnit.fluidOunceUS(): 1]),

// Sleep
TimeInBedHealthKitMetric(humanText: "Time in bed", databaseString: "timeInBed", category: .Sleep),
Expand Down
11 changes: 11 additions & 0 deletions BeeKit/HeathKit/HealthKitMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public protocol HealthKitMetric {
var humanText : String { get }
var databaseString : String { get }
var category : HealthKitCategory { get }
var precision : [HKUnit: Int] { get }

/// The permission required for this connection to read data from HealthKit
func permissionType() -> HKObjectType
Expand All @@ -41,3 +42,13 @@ public protocol HealthKitMetric {
/// The units this metric returns its datapoint values in
func units(healthStore : HKHealthStore) async throws -> HKUnit
}

extension HealthKitMetric {
func applyPrecision(value: Double, unit: HKUnit) -> Double {
if let unitPrecision = precision[unit] {
let roundingFactor = pow(10.0, Double(unitPrecision))
return round(value * roundingFactor) / roundingFactor
}
return value
}
}
5 changes: 1 addition & 4 deletions BeeKit/HeathKit/QuantityHealthKitMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,7 @@ class QuantityHealthKitMetric : HealthKitMetric {
continue
}

if let unitPrecision = precision[unit] {
let roundingFactor = pow(10.0, Double(unitPrecision))
datapointValue = round(datapointValue * roundingFactor) / roundingFactor
}
datapointValue = applyPrecision(value: datapointValue, unit: unit)

let id = "apple-health-" + daystamp.description
results.append(NewDataPoint(requestid: id, daystamp: daystamp, value: NSNumber(value: datapointValue), comment: "Auto-entered via Apple Health"))
Expand Down
6 changes: 4 additions & 2 deletions BeeKit/HeathKit/WorkoutMinutesHealthKitMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import OSLog
public class WorkoutMinutesHealthKitMetric : CategoryHealthKitMetric {
private let logger = Logger(subsystem: "com.beeminder.beeminder", category: "WorkoutMinutesHealthKitMetric")
let minuteInSeconds = 60.0

public override var precision: [HKUnit: Int] { return [HKUnit.minute(): 1] }


init(humanText: String, databaseString: String, category: HealthKitCategory) {
Expand All @@ -16,7 +18,7 @@ public class WorkoutMinutesHealthKitMetric : CategoryHealthKitMetric {
let samplesOnDay = samples.filter{sample in sample.startDate >= startOfDate}
let workouts = samplesOnDay.compactMap({sample in sample as? HKWorkout})
let workoutMinutes = workouts.map{sample in sample.duration / minuteInSeconds}.reduce(0, +)
return Double(workoutMinutes)
return applyPrecision(value: Double(workoutMinutes), unit: HKUnit.minute())
}

public override func recentDataPoints(days: Int, deadline: Int, healthStore: HKHealthStore, autodataConfig: [String: Any]) async throws -> [BeeDataPoint] {
Expand All @@ -40,7 +42,7 @@ public class WorkoutMinutesHealthKitMetric : CategoryHealthKitMetric {
let workouts = samples.compactMap { $0 as? HKWorkout }

for workout in workouts {
let workoutMinutes = workout.duration / minuteInSeconds
let workoutMinutes = applyPrecision(value: workout.duration / minuteInSeconds, unit: HKUnit.minute())
let workoutDescription = formatWorkoutDescription(workout: workout)
let id = "apple-health-workout-\(workout.uuid.uuidString)"

Expand Down