forked from C3-PRO/c3-pro-ios-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHealthKitReporter.swift
99 lines (81 loc) · 3.18 KB
/
HealthKitReporter.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//
// HealthKitReporter.swift
// C3PRO
//
// Created by Pascal Pfiffner on 15/07/16.
// Copyright © 2016 University Hospital Zurich. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
import HealthKit
import SMART
/**
Convenience class querying HealthKit and CoreMotion for activity data.
See [HealthKit/README.md](https://github.com/C3-PRO/c3-pro-ios-framework/tree/master/Sources/HealthKit#activity-reporter) for detailed instructions.
*/
open class HealthKitReporter: ActivityReporter {
/// The health store used by the instance.
lazy var healthStore = HKHealthStore()
public init() {
}
// MARK: - Convenience Methods
/**
Creates one `ActivityReportPeriod` instance containing summarized HKQuantitySample over the given period.
*/
open func reportForActivityPeriod(startingAt start: Date, until: Date, callback: @escaping ((_ period: ActivityReportPeriod?, _ error: Error?) -> Void)) {
retrieveHealthKitActivitySummary(startingAt: start, until: until) { samples, error in
// create the period
let period = Period()
period.start = start.fhir_asDateTime()
period.end = until.fhir_asDateTime()
// Put all data into one ActivityData instance
let report = ActivityReportPeriod(period: period)
report.healthKitSamples = samples
callback(report, error)
}
}
// MARK: - HealthKit Access
/**
Samples activity data in HealthKit (steps, flights climbed and active energy) and returns one HKQuantitySample per type in a callback.
Uses `c3_summaryOfSamplesOfTypeBetween(type:start:end:)` on the receiver's HKHealthStore instance.
*/
open func retrieveHealthKitActivitySummary(startingAt start: Date, until: Date, callback: @escaping ((_ samples: [HKQuantitySample]?, _ error: Error?) -> Void)) {
if HKHealthStore.isHealthDataAvailable() {
let queueGroup = DispatchGroup()
var quantities = [HKQuantitySample]()
var errors = [Error]()
let types = [HKQuantityTypeIdentifier.stepCount, HKQuantityTypeIdentifier.flightsClimbed, HKQuantityTypeIdentifier.activeEnergyBurned]
for type in types {
queueGroup.enter()
healthStore.c3_summaryOfSamplesOfTypeBetween(type, start: start, end: until) { result, error in
if let result = result {
quantities.append(result)
}
else if let error = error {
errors.append(error)
}
queueGroup.leave()
}
}
// on group notify, call the callback on the main queue
queueGroup.notify(queue: DispatchQueue.main) {
callback(quantities, (errors.count > 0) ? C3Error.multipleErrors(errors) : nil)
}
}
else {
c3_logIfDebug("HKHealthStorage is not available")
callback(nil, C3Error.healthKitNotAvailable)
}
}
}