capacitor-plugin-healthapp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapacitorPluginHealthapp.podspec +17 -0
- package/README.md +119 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/managemyhealth/healthapp/Example.java +11 -0
- package/android/src/main/java/com/managemyhealth/healthapp/ExamplePlugin.java +22 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +354 -0
- package/dist/esm/definitions.d.ts +13 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +15 -0
- package/dist/esm/web.js +16 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +32 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +35 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/HealthApp.swift +911 -0
- package/ios/Plugin/HealthAppPlugin.h +10 -0
- package/ios/Plugin/HealthAppPlugin.m +11 -0
- package/ios/Plugin/HealthAppPlugin.swift +156 -0
- package/ios/Plugin/Info.plist +24 -0
- package/package.json +78 -0
@@ -0,0 +1,911 @@
|
|
1
|
+
import Foundation
|
2
|
+
import UIKit
|
3
|
+
import HealthKit
|
4
|
+
|
5
|
+
struct HealthValue {
|
6
|
+
static let kNoData : String = "nodata"
|
7
|
+
static let kIdentifierTypeName : String = "type"
|
8
|
+
static let kIdentifierValue : String = "value"
|
9
|
+
static let kIdentifierDisplayUnit : String = "unit"
|
10
|
+
static let kRecordDate : String = "date"
|
11
|
+
}
|
12
|
+
|
13
|
+
@available(iOS 8.0, *)
|
14
|
+
struct HealthKitData {
|
15
|
+
static let BloodType: HKCharacteristicType = HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.bloodType)!
|
16
|
+
|
17
|
+
static let DateOfBirth: HKCharacteristicType = HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.dateOfBirth)!
|
18
|
+
|
19
|
+
static let BiologicalSex: HKCharacteristicType = HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.biologicalSex)!
|
20
|
+
|
21
|
+
static let BloodAlcoholContent: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodAlcoholContent)!
|
22
|
+
|
23
|
+
static let BloodAlcoholContentUnit : String = "%"
|
24
|
+
static let BloodAlcoholContentDisplayUnit : String = "ml"
|
25
|
+
|
26
|
+
@available(iOS 15.0, *)
|
27
|
+
static let NumberOfAlcoholicBeverages: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.numberOfAlcoholicBeverages)!
|
28
|
+
|
29
|
+
static let NumberOfAlcoholicBeveragesUnit : String = "count"
|
30
|
+
static let NumberOfAlcoholicBeveragesDisplayUnit : String = "drinks"
|
31
|
+
|
32
|
+
|
33
|
+
static let BloodGlucose: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodGlucose)!
|
34
|
+
static let BloodGlucoseUnit : String = "mmol/L"
|
35
|
+
static let BloodGlucoseDisplayUnit : String = "mmol/L"
|
36
|
+
|
37
|
+
static let BloodPressureSystolic: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!
|
38
|
+
static let BloodPressureSystolicUnit : String = "mmHg"
|
39
|
+
static let BloodPressureSystolicDisplayUnit : String = "mmHg"
|
40
|
+
|
41
|
+
static let BloodPressureDiastolic: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!
|
42
|
+
static let BloodPressureDiastolicUnit : String = "mmHg"
|
43
|
+
static let BloodPressureDiastolicDisplayUnit : String = "mmHg"
|
44
|
+
|
45
|
+
static let BodyMass: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!
|
46
|
+
static let BodyMassUnit : String = "kg"
|
47
|
+
static let BodyMassDisplayUnit : String = "Kg"
|
48
|
+
|
49
|
+
static let BodyMassIndex: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex)!
|
50
|
+
static let BodyMassIndexUnit : String = "count"
|
51
|
+
static let BodyMassIndexDisplayUnit : String = "BMI"
|
52
|
+
|
53
|
+
static let BodyTemperature: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyTemperature)!
|
54
|
+
static let BodyTemperatureUnit : String = "degC"
|
55
|
+
static let BodyTemperatureDisplayUnit : String = "Celcius"
|
56
|
+
|
57
|
+
static let DistanceCycling: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceCycling)!
|
58
|
+
static let DistanceCyclingUnit : String = "km"
|
59
|
+
static let DistanceCyclingDisplayUnit : String = "Km"
|
60
|
+
|
61
|
+
static let DietaryCholesterol: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryCholesterol)!
|
62
|
+
static let DietaryCholesterolUnit : String = "mg"
|
63
|
+
static let DietaryCholesterolDisplayUnit : String = "mg/dl"
|
64
|
+
|
65
|
+
static let HeartRate: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
|
66
|
+
static let HeartRateUnit : String = "count/min"
|
67
|
+
static let HeartRateDisplayUnit : String = "bpm"
|
68
|
+
|
69
|
+
static let Height: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!
|
70
|
+
static let HeightUnit : String = "cm"
|
71
|
+
static let HeightDisplayUnit : String = "cm"
|
72
|
+
|
73
|
+
static let OxygenSaturation: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.oxygenSaturation)!
|
74
|
+
static let OxygenSaturationUnit : String = "%"
|
75
|
+
static let OxygenSaturationDisplayUnit : String = "%"
|
76
|
+
|
77
|
+
static let PeakExpiratoryFlowRate: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.peakExpiratoryFlowRate)!
|
78
|
+
static let PeakExpiratoryFlowRateUnit : String = "L/min"
|
79
|
+
static let PeakExpiratoryFlowRateDisplayUnit : String = "L/min"
|
80
|
+
|
81
|
+
static let RespiratoryRate: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.respiratoryRate)!
|
82
|
+
static let RespiratoryRateUnit : String = "count/min"
|
83
|
+
static let RespiratoryRateDisplayUnit : String = "breaths/min"
|
84
|
+
|
85
|
+
static let Steps: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
|
86
|
+
static let StepsUnit : String = "count"
|
87
|
+
static let StepsDisplayUnit : String = "Steps"
|
88
|
+
|
89
|
+
@available(iOS 9.0, *)
|
90
|
+
static let DietaryWater: HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)!
|
91
|
+
static let DietaryWaterUnit : String = "ml"
|
92
|
+
static let DietaryWaterDisplayUnit : String = "L"
|
93
|
+
}
|
94
|
+
|
95
|
+
@objc public class HealthApp: NSObject {
|
96
|
+
var HealthStore : AnyObject
|
97
|
+
var healthIndicators = [
|
98
|
+
[
|
99
|
+
"key": HealthKitData.BloodAlcoholContent,
|
100
|
+
"unit": HealthKitData.BloodAlcoholContentUnit
|
101
|
+
],
|
102
|
+
[
|
103
|
+
"key": HealthKitData.BloodPressureSystolic,
|
104
|
+
"unit": HealthKitData.BloodPressureSystolicUnit
|
105
|
+
],
|
106
|
+
[
|
107
|
+
"key": HealthKitData.BloodPressureDiastolic,
|
108
|
+
"unit": HealthKitData.BloodPressureDiastolicUnit
|
109
|
+
],
|
110
|
+
[
|
111
|
+
"key": HealthKitData.BloodGlucose,
|
112
|
+
"unit": HealthKitData.BloodGlucoseUnit
|
113
|
+
],
|
114
|
+
[
|
115
|
+
"key": HealthKitData.BodyMass,
|
116
|
+
"unit": HealthKitData.BodyMassUnit
|
117
|
+
],
|
118
|
+
[
|
119
|
+
"key": HealthKitData.BodyMassIndex,
|
120
|
+
"unit": HealthKitData.BodyMassIndexUnit
|
121
|
+
],
|
122
|
+
[
|
123
|
+
"key": HealthKitData.BodyTemperature,
|
124
|
+
"unit": HealthKitData.BodyTemperatureUnit
|
125
|
+
],
|
126
|
+
[
|
127
|
+
"key": HealthKitData.HeartRate,
|
128
|
+
"unit": HealthKitData.HeartRateUnit
|
129
|
+
],
|
130
|
+
[
|
131
|
+
"key": HealthKitData.Height,
|
132
|
+
"unit": HealthKitData.HeightUnit
|
133
|
+
],
|
134
|
+
[
|
135
|
+
"key": HealthKitData.OxygenSaturation,
|
136
|
+
"unit": HealthKitData.OxygenSaturationUnit
|
137
|
+
],
|
138
|
+
[
|
139
|
+
"key": HealthKitData.RespiratoryRate,
|
140
|
+
"unit": HealthKitData.RespiratoryRateUnit
|
141
|
+
],
|
142
|
+
[
|
143
|
+
"key": HealthKitData.Steps,
|
144
|
+
"unit": HealthKitData.StepsUnit
|
145
|
+
]
|
146
|
+
]
|
147
|
+
override init() {
|
148
|
+
HealthStore = HKHealthStore()
|
149
|
+
if #available(iOS 15.0, *) {
|
150
|
+
healthIndicators.append([
|
151
|
+
"key": HealthKitData.NumberOfAlcoholicBeverages,
|
152
|
+
"unit": HealthKitData.NumberOfAlcoholicBeveragesUnit
|
153
|
+
])
|
154
|
+
}
|
155
|
+
}
|
156
|
+
@objc public func isHealthAvailable ( ) -> Bool {
|
157
|
+
return HKHealthStore.isHealthDataAvailable()
|
158
|
+
}
|
159
|
+
fileprivate func dataTypesToRead() -> Set<HKObjectType> {
|
160
|
+
var healthKitTypesToRead : Set<HKObjectType>
|
161
|
+
|
162
|
+
if #available(iOS 9.0, *) {
|
163
|
+
healthKitTypesToRead = Set(arrayLiteral:
|
164
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodAlcoholContent)!,
|
165
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodGlucose)!,
|
166
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!,
|
167
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!,
|
168
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!,
|
169
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex)!,
|
170
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyTemperature)!,
|
171
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!,
|
172
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!,
|
173
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.oxygenSaturation)!,
|
174
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.respiratoryRate)!,
|
175
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
|
176
|
+
)
|
177
|
+
} else {
|
178
|
+
// Fallback on earlier versions
|
179
|
+
healthKitTypesToRead = Set(arrayLiteral:
|
180
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodAlcoholContent)!,
|
181
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodGlucose)!,
|
182
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!,
|
183
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!,
|
184
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!,
|
185
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex)!,
|
186
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyTemperature)!,
|
187
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!,
|
188
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!,
|
189
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.oxygenSaturation)!,
|
190
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.respiratoryRate)!,
|
191
|
+
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
|
192
|
+
)
|
193
|
+
}
|
194
|
+
if #available(iOS 15.0, *) {
|
195
|
+
healthKitTypesToRead.insert(HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.numberOfAlcoholicBeverages)!)
|
196
|
+
}
|
197
|
+
|
198
|
+
return healthKitTypesToRead
|
199
|
+
}
|
200
|
+
@objc public func CheckAuthorizationStatusFor ( _ readWriteTypes : Set<HKObjectType>) -> Void {
|
201
|
+
for demoType in readWriteTypes {
|
202
|
+
// let dbType = HKQuantityType.quantityTypeForIdentifier(HKCharacteristicTypeIdentifierDateOfBirth)
|
203
|
+
let status : HKAuthorizationStatus = (HealthStore as! HKHealthStore).authorizationStatus(for: demoType)
|
204
|
+
|
205
|
+
if(status == HKAuthorizationStatus.sharingAuthorized) {
|
206
|
+
} else if(status == HKAuthorizationStatus.sharingDenied) {
|
207
|
+
} else if(status == HKAuthorizationStatus.notDetermined) {
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
@objc public func authorizeHealthKit (_ SuccessCompletion: @escaping (((_ success : Bool) -> Void)), FailureCompletion: @escaping ((( _ err : NSError? ) -> Void))) {
|
212
|
+
if !isHealthAvailable() {
|
213
|
+
let error = NSError(domain: "com.mangemyhealth", code: 2, userInfo: [NSLocalizedDescriptionKey:"HealthKit is not available in this Device"])
|
214
|
+
|
215
|
+
FailureCompletion(error)
|
216
|
+
return;
|
217
|
+
}
|
218
|
+
|
219
|
+
// 4. Request HealthKit authorization
|
220
|
+
(HealthStore as! HKHealthStore).requestAuthorization(toShare: nil, read: dataTypesToRead()) { (success, error) -> Void in
|
221
|
+
//self.CheckAuthorizationStatusFor(self.dataTypesToRead())
|
222
|
+
|
223
|
+
if (success) {
|
224
|
+
SuccessCompletion(success)
|
225
|
+
return;
|
226
|
+
} else {
|
227
|
+
(self.HealthStore as! HKHealthStore).requestAuthorization(toShare: nil, read: self.dataTypesToRead()) { success, error in
|
228
|
+
if (success) {
|
229
|
+
SuccessCompletion(success)
|
230
|
+
return;
|
231
|
+
} else {
|
232
|
+
FailureCompletion(error! as NSError)
|
233
|
+
return
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
//FailureCompletion(error! as NSError)
|
238
|
+
return;
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
@objc public func getHealthDataValuesForGraph (strStartDate : String ,strEndDate : String, GetBackFinalhealthData: @escaping ((( _ healthValues : [Any] ) -> Void))) {
|
243
|
+
|
244
|
+
}
|
245
|
+
func TodayTotalSteps(completion: @escaping (_ stepRetrieved: Double) -> Void) {
|
246
|
+
|
247
|
+
let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount) // The type of data we are requesting
|
248
|
+
let calendar = NSCalendar.current
|
249
|
+
let interval = NSDateComponents()
|
250
|
+
interval.day = 1
|
251
|
+
var anchorComponents = calendar.dateComponents([.day,.month,.year], from: NSDate() as Date)
|
252
|
+
|
253
|
+
anchorComponents.hour = 0
|
254
|
+
let anchorDate = calendar.date(from: anchorComponents)
|
255
|
+
let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: .cumulativeSum, anchorDate: anchorDate!, intervalComponents: interval as DateComponents)
|
256
|
+
stepsQuery.initialResultsHandler = { query, results, error in
|
257
|
+
let endDate = NSDate()
|
258
|
+
var totalSteps = 0.0
|
259
|
+
|
260
|
+
let startDate = calendar.date(byAdding: .day, value: -50, to: endDate as Date)
|
261
|
+
if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
|
262
|
+
if let quantity = statistics.sumQuantity(){
|
263
|
+
let date = statistics.startDate
|
264
|
+
let steps = quantity.doubleValue(for: HKUnit.count())
|
265
|
+
print("\(date): steps = \(steps)")
|
266
|
+
}
|
267
|
+
completion(totalSteps)
|
268
|
+
}
|
269
|
+
} else {
|
270
|
+
completion(totalSteps)
|
271
|
+
}
|
272
|
+
}
|
273
|
+
//executeQuery(stepsQuery)
|
274
|
+
(self.HealthStore as! HKHealthStore).execute(stepsQuery)
|
275
|
+
}
|
276
|
+
@objc public func getindividualHealthAppValues(quantityType:String,strStartDate : String ,strEndDate : String, GetBackFinalhealthData: @escaping ((( _ healthValues : [Any] ) -> Void))) {
|
277
|
+
//var vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"No Data Found"]
|
278
|
+
var finalHealthData:[Any] = []
|
279
|
+
let dateFormatter = DateFormatter()
|
280
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
281
|
+
let vitalDateFormatter = DateFormatter()
|
282
|
+
vitalDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
283
|
+
var selectedStartDate = Date()
|
284
|
+
var selectedEndDate = Date()
|
285
|
+
if(strStartDate.count > 0) {
|
286
|
+
selectedStartDate = dateFormatter.date(from: strStartDate)!
|
287
|
+
selectedEndDate = dateFormatter.date(from: strEndDate)!
|
288
|
+
}
|
289
|
+
if let healthObj = healthIndicators.first(where: {($0["key"] as! HKQuantityType).identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "") == quantityType}) {
|
290
|
+
// do something with foo
|
291
|
+
let HealthQuantityType = healthObj["key"] as! HKQuantityType
|
292
|
+
|
293
|
+
if let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier)) {
|
294
|
+
if (HKHealthStore.isHealthDataAvailable()) {
|
295
|
+
let identifier = HealthQuantityType.identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "")
|
296
|
+
let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier))// The type of data we are requesting
|
297
|
+
let calendar = NSCalendar.current
|
298
|
+
let interval = NSDateComponents()
|
299
|
+
interval.day = 1
|
300
|
+
var anchorComponents = calendar.dateComponents([.day,.month,.year], from: NSDate() as Date)
|
301
|
+
|
302
|
+
anchorComponents.hour = 0
|
303
|
+
let anchorDate = calendar.date(from: anchorComponents)
|
304
|
+
var arrHealthValues = [[String:Any]]()
|
305
|
+
let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: [.discreteMin,.discreteMax,.discreteAverage], anchorDate: anchorDate!, intervalComponents: interval as DateComponents)
|
306
|
+
stepsQuery.initialResultsHandler = { query, results, error in
|
307
|
+
let endDate = NSDate()
|
308
|
+
let calendar = NSCalendar.current
|
309
|
+
let totalDays = calendar.numberOfDaysBetween(selectedStartDate, and: selectedEndDate)
|
310
|
+
let startDate = calendar.date(byAdding: .day, value: -totalDays, to: endDate as Date)
|
311
|
+
|
312
|
+
let strUnitType = healthObj["unit"] as! String
|
313
|
+
if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
|
314
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: statistics.startDate))"
|
315
|
+
if(quantityType == "Height" || quantityType == "BodyTemperature" || quantityType == "BodyMass" || quantityType == "BodyMassIndex"){
|
316
|
+
if let quantity = statistics.averageQuantity(){
|
317
|
+
let tempActualhealthData = "\(quantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal(1))"
|
318
|
+
//let uuid = statistics.uuid
|
319
|
+
if (tempActualhealthData.count > 0) {
|
320
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:tempActualhealthData]
|
321
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
322
|
+
|
323
|
+
arrHealthValues.append(dicHealth)
|
324
|
+
}
|
325
|
+
}
|
326
|
+
}else{
|
327
|
+
|
328
|
+
var minMaxValues = []
|
329
|
+
if let minQuantity = statistics.minimumQuantity(){
|
330
|
+
let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? "\(minQuantity.doubleValue(for: HKUnit.init(from: strUnitType))*100)" : identifier == "BloodGlucose" ? "\(minQuantity.doubleValue(for: HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter())).roundToDecimal(1))" : "\(minQuantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal( identifier == "HeartRate" ? 0 : 2))"
|
331
|
+
|
332
|
+
minMaxValues.append(tempActualhealthData)
|
333
|
+
|
334
|
+
}
|
335
|
+
if let maxQuantity = statistics.maximumQuantity(){
|
336
|
+
let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? "\(maxQuantity.doubleValue(for: HKUnit.init(from: strUnitType))*100)" : identifier == "BloodGlucose" ? "\(maxQuantity.doubleValue(for: HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter())).roundToDecimal(1))" : "\(maxQuantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal(identifier == "HeartRate" ? 0 : 2))"
|
337
|
+
minMaxValues.append(tempActualhealthData)
|
338
|
+
|
339
|
+
}
|
340
|
+
if(minMaxValues.count > 0){
|
341
|
+
let dicHealth : [String:Any] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:minMaxValues]
|
342
|
+
|
343
|
+
arrHealthValues.append(dicHealth)
|
344
|
+
}
|
345
|
+
|
346
|
+
|
347
|
+
}
|
348
|
+
|
349
|
+
|
350
|
+
}
|
351
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
352
|
+
finalHealthData.append(vitalData)
|
353
|
+
|
354
|
+
GetBackFinalhealthData(finalHealthData)
|
355
|
+
} else {
|
356
|
+
//completion(totalSteps)
|
357
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
358
|
+
finalHealthData.append(vitalData)
|
359
|
+
GetBackFinalhealthData(finalHealthData)
|
360
|
+
}
|
361
|
+
}
|
362
|
+
(self.HealthStore as! HKHealthStore).execute(stepsQuery)
|
363
|
+
|
364
|
+
}else{
|
365
|
+
let vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"nodata"]
|
366
|
+
finalHealthData.append(vitalData)
|
367
|
+
GetBackFinalhealthData(finalHealthData)
|
368
|
+
}
|
369
|
+
}
|
370
|
+
} else {
|
371
|
+
let vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"nodata"]
|
372
|
+
finalHealthData.append(vitalData)
|
373
|
+
GetBackFinalhealthData(finalHealthData)
|
374
|
+
}
|
375
|
+
}
|
376
|
+
@objc public func getaverageHealthValues(quantityType:String,strStartDate : String ,strEndDate : String, GetBackFinalhealthData: @escaping ((( _ healthValues : [String:Any] ) -> Void))) {
|
377
|
+
//var vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"No Data Found"]
|
378
|
+
let dateFormatter = DateFormatter()
|
379
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
380
|
+
let vitalDateFormatter = DateFormatter()
|
381
|
+
vitalDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
382
|
+
var selectedStartDate = Date()
|
383
|
+
var selectedEndDate = Date()
|
384
|
+
if(strStartDate.count > 0) {
|
385
|
+
selectedStartDate = dateFormatter.date(from: strStartDate)!
|
386
|
+
selectedEndDate = dateFormatter.date(from: strEndDate)!
|
387
|
+
}
|
388
|
+
if let healthObj = healthIndicators.first(where: {($0["key"] as! HKQuantityType).identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "") == quantityType}) {
|
389
|
+
// do something with foo
|
390
|
+
let HealthQuantityType = healthObj["key"] as! HKQuantityType
|
391
|
+
|
392
|
+
if let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier)) {
|
393
|
+
if (HKHealthStore.isHealthDataAvailable()) {
|
394
|
+
let identifier = HealthQuantityType.identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "")
|
395
|
+
let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier))// The type of data we are requesting
|
396
|
+
let calendar = NSCalendar.current
|
397
|
+
let interval = NSDateComponents()
|
398
|
+
interval.day = 1
|
399
|
+
var anchorComponents = calendar.dateComponents([.day,.month,.year], from: NSDate() as Date)
|
400
|
+
|
401
|
+
anchorComponents.hour = 0
|
402
|
+
let anchorDate = calendar.date(from: anchorComponents)
|
403
|
+
|
404
|
+
let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: .discreteAverage, anchorDate: anchorDate!, intervalComponents: interval as DateComponents)
|
405
|
+
stepsQuery.initialResultsHandler = { query, results, error in
|
406
|
+
let endDate = NSDate()
|
407
|
+
let calendar = NSCalendar.current
|
408
|
+
let totalDays = calendar.numberOfDaysBetween(selectedStartDate, and: selectedEndDate)
|
409
|
+
let startDate = calendar.date(byAdding: .day, value: -totalDays, to: endDate as Date)
|
410
|
+
var arrHealthValues = [[String:String]]()
|
411
|
+
let strUnitType = healthObj["unit"] as! String
|
412
|
+
if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
|
413
|
+
|
414
|
+
if let quantity = statistics.averageQuantity(){
|
415
|
+
|
416
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: statistics.startDate))"
|
417
|
+
let tempActualhealthData = "\(quantity.doubleValue(for: HKUnit.init(from: strUnitType)))"
|
418
|
+
//let uuid = statistics.uuid
|
419
|
+
if (tempActualhealthData.count > 0) {
|
420
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:tempActualhealthData]
|
421
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
422
|
+
|
423
|
+
arrHealthValues.append(dicHealth)
|
424
|
+
}
|
425
|
+
}
|
426
|
+
|
427
|
+
}
|
428
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
429
|
+
GetBackFinalhealthData(vitalData)
|
430
|
+
} else {
|
431
|
+
//completion(totalSteps)
|
432
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
433
|
+
GetBackFinalhealthData(vitalData)
|
434
|
+
}
|
435
|
+
}
|
436
|
+
(self.HealthStore as! HKHealthStore).execute(stepsQuery)
|
437
|
+
|
438
|
+
}else{
|
439
|
+
let vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"nodata"]
|
440
|
+
GetBackFinalhealthData(vitalData)
|
441
|
+
}
|
442
|
+
}
|
443
|
+
} else {
|
444
|
+
let vitalData = ["VitalName":quantityType,"Unit":"Count","VitalData":"nodata"]
|
445
|
+
GetBackFinalhealthData(vitalData)
|
446
|
+
}
|
447
|
+
}
|
448
|
+
@objc public func getLatestHealthValues(strStartDate : String ,strEndDate : String, GetBackFinalhealthData: @escaping ((( _ healthValues : [Any] ) -> Void))) {
|
449
|
+
var dicHealth : [String:AnyObject] = [:]
|
450
|
+
var finalHealthData:[Any] = []
|
451
|
+
|
452
|
+
let dateFormatter = DateFormatter()
|
453
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
454
|
+
let vitalDateFormatter = DateFormatter()
|
455
|
+
vitalDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
456
|
+
var selectedStartDate = Date()
|
457
|
+
var selectedEndDate = Date()
|
458
|
+
if(strStartDate.count > 0) {
|
459
|
+
selectedStartDate = dateFormatter.date(from: strStartDate)!
|
460
|
+
selectedEndDate = dateFormatter.date(from: strEndDate)!
|
461
|
+
}
|
462
|
+
|
463
|
+
for (index, indicator) in healthIndicators.enumerated() {
|
464
|
+
// var dicHealth : [String:AnyObject] = [:]
|
465
|
+
let HealthQuantityType = indicator["key"] as! HKQuantityType
|
466
|
+
|
467
|
+
if let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier)) {
|
468
|
+
if (HKHealthStore.isHealthDataAvailable()) {
|
469
|
+
let identifier = HealthQuantityType.identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "")
|
470
|
+
let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier))// The type of data we are requesting
|
471
|
+
let calendar = NSCalendar.current
|
472
|
+
let interval = NSDateComponents()
|
473
|
+
interval.day = 1
|
474
|
+
var anchorComponents = calendar.dateComponents([.day,.month,.year], from: NSDate() as Date)
|
475
|
+
|
476
|
+
anchorComponents.hour = 0
|
477
|
+
let anchorDate = calendar.date(from: anchorComponents)
|
478
|
+
|
479
|
+
let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: .mostRecent, anchorDate: anchorDate!, intervalComponents: interval as DateComponents)
|
480
|
+
stepsQuery.initialResultsHandler = { query, results, error in
|
481
|
+
let endDate = NSDate()
|
482
|
+
let calendar = NSCalendar.current
|
483
|
+
let totalDays = calendar.numberOfDaysBetween(selectedStartDate, and: selectedEndDate)
|
484
|
+
print("diffrence bt days \(totalDays)")
|
485
|
+
let startDate = calendar.date(byAdding: .day, value: -totalDays, to: endDate as Date)
|
486
|
+
var arrHealthValues = [[String:String]]()
|
487
|
+
let strUnitType = indicator["unit"] as! String
|
488
|
+
if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
|
489
|
+
|
490
|
+
if let quantity = statistics.mostRecentQuantity(){
|
491
|
+
|
492
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: statistics.startDate))"
|
493
|
+
let tempActualhealthData = "\(quantity.doubleValue(for: HKUnit.init(from: strUnitType)))"
|
494
|
+
//let uuid = statistics.uuid
|
495
|
+
if (tempActualhealthData.count > 0) {
|
496
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:tempActualhealthData]
|
497
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
498
|
+
|
499
|
+
arrHealthValues.append(dicHealth)
|
500
|
+
}
|
501
|
+
} else{
|
502
|
+
dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
503
|
+
}
|
504
|
+
|
505
|
+
}
|
506
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
507
|
+
finalHealthData.append(vitalData)
|
508
|
+
if(finalHealthData.count == 16) {
|
509
|
+
// print(dicHealth)
|
510
|
+
GetBackFinalhealthData (finalHealthData)
|
511
|
+
}
|
512
|
+
} else {
|
513
|
+
//completion(totalSteps)
|
514
|
+
}
|
515
|
+
}
|
516
|
+
(self.HealthStore as! HKHealthStore).execute(stepsQuery)
|
517
|
+
|
518
|
+
}
|
519
|
+
}
|
520
|
+
}
|
521
|
+
|
522
|
+
}
|
523
|
+
@objc public func getHealthDataValuesFor (strStartDate : String ,strEndDate : String, GetBackFinalhealthData: @escaping ((( _ healthValues : [Any] ) -> Void))) {
|
524
|
+
var dicHealth : [String:AnyObject] = [:]
|
525
|
+
var finalHealthData:[Any] = []
|
526
|
+
var heartRateRecentValue = ""
|
527
|
+
var heartRateRecentDate = ""
|
528
|
+
var predicate : NSPredicate = HKQuery.predicateForSamples(withStart: nil, end: nil, options: [])
|
529
|
+
|
530
|
+
let dateFormatter = DateFormatter()
|
531
|
+
//dateFormatter.locale = Locale.current
|
532
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
533
|
+
//dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
|
534
|
+
//dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
535
|
+
let vitalDateFormatter = DateFormatter()
|
536
|
+
vitalDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
537
|
+
var selectedStartDate = Date()
|
538
|
+
var selectedEndDate = Date()
|
539
|
+
if(strStartDate.count > 0) {
|
540
|
+
//let SelectedStartDate = dateFormatter.date(from: "2021-08-01T23:53:00")!
|
541
|
+
//let SelectedEndDate = dateFormatter.date(from: "2022-05-01T17:00:00")!
|
542
|
+
selectedStartDate = dateFormatter.date(from: strStartDate)!
|
543
|
+
//let endDate = NSDate()
|
544
|
+
selectedEndDate = dateFormatter.date(from: strEndDate)!
|
545
|
+
|
546
|
+
//print(SelectedStartDate)
|
547
|
+
//print(SelectedEndDate)
|
548
|
+
|
549
|
+
// let now = Date()
|
550
|
+
// let exactlySevenDaysAgo = Calendar.current.date(byAdding: DateComponents(day: -7), to: now)!
|
551
|
+
// let startOfSevenDaysAgo = Calendar.current.startOfDay(for: exactlySevenDaysAgo)
|
552
|
+
predicate = HKQuery.predicateForSamples(withStart: selectedStartDate, end: selectedEndDate, options: [])
|
553
|
+
|
554
|
+
}
|
555
|
+
|
556
|
+
let sortByTime = NSSortDescriptor(key:HKSampleSortIdentifierEndDate, ascending: false)
|
557
|
+
|
558
|
+
for (index, indicator) in healthIndicators.enumerated() {
|
559
|
+
// var dicHealth : [String:AnyObject] = [:]
|
560
|
+
let HealthQuantityType = indicator["key"] as! HKQuantityType
|
561
|
+
|
562
|
+
if let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier)) {
|
563
|
+
if (HKHealthStore.isHealthDataAvailable()) {
|
564
|
+
// let timeFormatter = NSDateFormatter()
|
565
|
+
// timeFormatter.dateFormat = "hh:mm:ss"
|
566
|
+
//yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ
|
567
|
+
let identifier = HealthQuantityType.identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "")
|
568
|
+
if(identifier == "StepCount" || identifier == "NumberOfAlcoholicBeverages" || identifier == "HeartRate"){
|
569
|
+
// let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
|
570
|
+
let type = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier))// The type of data we are requesting
|
571
|
+
let calendar = NSCalendar.current
|
572
|
+
let interval = NSDateComponents()
|
573
|
+
interval.day = 1
|
574
|
+
var anchorComponents = calendar.dateComponents([.day,.month,.year], from: NSDate() as Date)
|
575
|
+
|
576
|
+
anchorComponents.hour = 0
|
577
|
+
let anchorDate = calendar.date(from: anchorComponents)
|
578
|
+
|
579
|
+
let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: identifier == "StepCount" || identifier == "DistanceCycling" || identifier == "DietaryWater" || identifier == "DietaryCholesterol" || identifier == "NumberOfAlcoholicBeverages" ? [.cumulativeSum,.mostRecent] : [.mostRecent,.discreteMax,.discreteMin,.discreteAverage], anchorDate: anchorDate!, intervalComponents: interval as DateComponents)
|
580
|
+
stepsQuery.initialResultsHandler = { query, results, error in
|
581
|
+
let endDate = NSDate()
|
582
|
+
let calendar = NSCalendar.current
|
583
|
+
let totalDays = calendar.numberOfDaysBetween(selectedStartDate, and: selectedEndDate)
|
584
|
+
print("diffrence bt days \(totalDays)")
|
585
|
+
let startDate = calendar.date(byAdding: .day, value: -totalDays, to: endDate as Date)
|
586
|
+
var arrHealthValues = [[String:String]]()
|
587
|
+
let strUnitType = indicator["unit"] as! String
|
588
|
+
if let myResults = results{
|
589
|
+
|
590
|
+
// for stats in myResults.statistics(){
|
591
|
+
// if let quantity = stats.sumQuantity(){
|
592
|
+
// let tempActualRecordedDate = "\(vitalDateFormatter.string(from: stats.startDate))"
|
593
|
+
// let tempActualhealthData = "\(quantity.doubleValue(for: HKUnit.init(from: strUnitType)))"
|
594
|
+
// print("tempActualRecordedDate \(tempActualRecordedDate) and tempActualhealthData \(tempActualhealthData)")
|
595
|
+
// }
|
596
|
+
// }
|
597
|
+
myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
|
598
|
+
if(identifier == "StepCount" || identifier == "DistanceCycling" || identifier == "DietaryCholesterol" || identifier == "DietaryWater" || identifier == "NumberOfAlcoholicBeverages"){
|
599
|
+
if let quantity = statistics.sumQuantity(){
|
600
|
+
|
601
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: statistics.startDate))"
|
602
|
+
let tempActualhealthData = quantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal(1)
|
603
|
+
//let uuid = statistics.uuid
|
604
|
+
if (tempActualhealthData > 0) {
|
605
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:floor(tempActualhealthData) == tempActualhealthData ? "\(Int(tempActualhealthData))" : "\(tempActualhealthData)"]
|
606
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
607
|
+
|
608
|
+
arrHealthValues.append(dicHealth)
|
609
|
+
}
|
610
|
+
} else{
|
611
|
+
dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
612
|
+
}
|
613
|
+
|
614
|
+
}else{
|
615
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: statistics.startDate))"
|
616
|
+
//if(heartRateRecentValue.count == 0){
|
617
|
+
if let recentQuantity = statistics.mostRecentQuantity(){
|
618
|
+
|
619
|
+
heartRateRecentValue = "\(Int(recentQuantity.doubleValue(for: HKUnit.init(from: strUnitType))))"
|
620
|
+
heartRateRecentDate = tempActualRecordedDate
|
621
|
+
}
|
622
|
+
//}
|
623
|
+
|
624
|
+
if let minQuantity = statistics.minimumQuantity(),let maxQuantity = statistics.maximumQuantity(){
|
625
|
+
// let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? "\(minQuantity.doubleValue(for: HKUnit.init(from: strUnitType))*100)" : identifier == "BloodGlucose" ? "\(minQuantity.doubleValue(for: HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter())).roundToDecimal(1))" : "\(minQuantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal( identifier == "HeartRate" ? 0 : 2))"
|
626
|
+
|
627
|
+
let tempActualhealthData = Int(minQuantity.doubleValue(for: HKUnit.init(from: strUnitType)))
|
628
|
+
|
629
|
+
// minMaxValues.append(tempActualhealthData)
|
630
|
+
if (tempActualhealthData > 0) {
|
631
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue:"\(tempActualhealthData)"]
|
632
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
633
|
+
|
634
|
+
arrHealthValues.append(dicHealth)
|
635
|
+
}
|
636
|
+
let tempMaxActualhealthData = Int(maxQuantity.doubleValue(for: HKUnit.init(from: strUnitType)))
|
637
|
+
// minMaxValues.append(tempActualhealthData)
|
638
|
+
let maxDate = calendar.date(byAdding: .minute, value: 1, to: statistics.startDate)
|
639
|
+
let tempMaxActualRecordedDate = "\(vitalDateFormatter.string(from: maxDate!))"
|
640
|
+
if (tempMaxActualhealthData > 0 && tempMaxActualhealthData != tempActualhealthData) {
|
641
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempMaxActualRecordedDate,HealthValue.kIdentifierValue:"\(tempMaxActualhealthData)"]
|
642
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
643
|
+
|
644
|
+
arrHealthValues.append(dicHealth)
|
645
|
+
}
|
646
|
+
|
647
|
+
}
|
648
|
+
// if let maxQuantity = statistics.maximumQuantity(){
|
649
|
+
// let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? "\(maxQuantity.doubleValue(for: HKUnit.init(from: strUnitType))*100)" : identifier == "BloodGlucose" ? "\(maxQuantity.doubleValue(for: HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter())).roundToDecimal(1))" : "\(maxQuantity.doubleValue(for: HKUnit.init(from: strUnitType)).roundToDecimal(identifier == "HeartRate" ? 0 : 2))"
|
650
|
+
// // minMaxValues.append(tempActualhealthData)
|
651
|
+
// let maxDate = calendar.date(byAdding: .minute, value: 1, to: statistics.startDate)
|
652
|
+
// let tempMaxActualRecordedDate = "\(vitalDateFormatter.string(from: maxDate!))"
|
653
|
+
// if (tempActualhealthData.count > 0) {
|
654
|
+
// let dicHealth : [String:String] = [HealthValue.kRecordDate:tempMaxActualRecordedDate,HealthValue.kIdentifierValue:tempActualhealthData]
|
655
|
+
// // Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
656
|
+
//
|
657
|
+
// arrHealthValues.append(dicHealth)
|
658
|
+
// }
|
659
|
+
// }
|
660
|
+
}
|
661
|
+
|
662
|
+
}
|
663
|
+
let vitalData = identifier == "HeartRate" ? ["VitalName":identifier,"latestValue": heartRateRecentValue,"latestDate":heartRateRecentDate, "Unit":strUnitType,"VitalData":arrHealthValues] : ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
664
|
+
finalHealthData.append(vitalData)
|
665
|
+
if(finalHealthData.count == self.healthIndicators.count) {
|
666
|
+
// print(dicHealth)
|
667
|
+
GetBackFinalhealthData (finalHealthData)
|
668
|
+
}
|
669
|
+
} else {
|
670
|
+
//completion(totalSteps)
|
671
|
+
}
|
672
|
+
}
|
673
|
+
(self.HealthStore as! HKHealthStore).execute(stepsQuery)
|
674
|
+
|
675
|
+
}else{
|
676
|
+
let query = HKSampleQuery(sampleType: heartRateType, predicate: strStartDate.count > 0 ? predicate : nil, limit: HKObjectQueryNoLimit, sortDescriptors: [sortByTime], resultsHandler:{(query, results, error) in
|
677
|
+
|
678
|
+
guard let results = results else {
|
679
|
+
//include the healthkit error in log
|
680
|
+
if(error.debugDescription.count > 0) {
|
681
|
+
dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
682
|
+
}
|
683
|
+
return
|
684
|
+
}
|
685
|
+
|
686
|
+
var arrHealthValues = [[String:String]]()
|
687
|
+
let strUnitType = indicator["unit"] as! String
|
688
|
+
//let latestHeartRateDate = ""
|
689
|
+
for quantitySample in results {
|
690
|
+
let quantity = (quantitySample as! HKQuantitySample).quantity
|
691
|
+
let healthDataUnit : HKUnit
|
692
|
+
if (strUnitType.count > 0 ) {
|
693
|
+
healthDataUnit = identifier == "BloodGlucose" ? HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter()) : HKUnit(from: strUnitType)
|
694
|
+
} else {
|
695
|
+
healthDataUnit = HKUnit.count()
|
696
|
+
}
|
697
|
+
// let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? "\(quantity.doubleValue(for: healthDataUnit) * 100)" : "\(quantity.doubleValue(for: healthDataUnit))"
|
698
|
+
let tempActualhealthData = identifier == "BloodAlcoholContent" || identifier == "OxygenSaturation" ? quantity.doubleValue(for: healthDataUnit) * 100 : quantity.doubleValue(for: healthDataUnit).roundToDecimal(2)
|
699
|
+
let tempActualRecordedDate = "\(vitalDateFormatter.string(from: quantitySample.startDate))"
|
700
|
+
let uuid = quantitySample.uuid
|
701
|
+
if (tempActualhealthData > 0) {
|
702
|
+
let dicHealth : [String:String] = [HealthValue.kRecordDate:tempActualRecordedDate,HealthValue.kIdentifierValue: floor(tempActualhealthData) == tempActualhealthData ? "\(Int(tempActualhealthData))" : String(format: "%g", tempActualhealthData)]
|
703
|
+
// Item(date: tempActualRecordedDate, value: tempActualhealthData)
|
704
|
+
|
705
|
+
arrHealthValues.append(dicHealth)
|
706
|
+
}
|
707
|
+
}
|
708
|
+
if(identifier == "StepCount"){
|
709
|
+
let data = self.sumAmounts(arrHealthValues)
|
710
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":data]
|
711
|
+
finalHealthData.append(vitalData)
|
712
|
+
}else{
|
713
|
+
let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
714
|
+
finalHealthData.append(vitalData)
|
715
|
+
//print("vitalData \(vitalData) for name \(identifier)")
|
716
|
+
}
|
717
|
+
// let vitalData = ["VitalName":identifier,"Unit":strUnitType,"VitalData":arrHealthValues]
|
718
|
+
// finalHealthData.append(vitalData)
|
719
|
+
// print("vitalData \(vitalData) for name \(identifier)")
|
720
|
+
// if (arrHealthValues.count > 0) {
|
721
|
+
//
|
722
|
+
// dicHealth[identifier] = arrHealthValues as AnyObject
|
723
|
+
// // GetBackFinalhealthData (arrHealthValues)
|
724
|
+
// } else {
|
725
|
+
// dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
726
|
+
// // GetBackFinalhealthData ([HealthValue.kNoData as AnyObject])
|
727
|
+
// }
|
728
|
+
|
729
|
+
//if(index == self.healthIndicators.count - 1) {
|
730
|
+
if(finalHealthData.count == self.healthIndicators.count) {
|
731
|
+
// print(dicHealth)
|
732
|
+
GetBackFinalhealthData (finalHealthData)
|
733
|
+
}
|
734
|
+
})
|
735
|
+
|
736
|
+
(self.HealthStore as! HKHealthStore).execute(query)
|
737
|
+
}
|
738
|
+
}
|
739
|
+
}
|
740
|
+
}
|
741
|
+
}
|
742
|
+
@objc public func getHealthValuesUsingAnchorQuery(isFirstCall : Bool ,GetBackFinalhealthData: @escaping ((( _ healthValues : [String:AnyObject] ) -> Void)) ) {
|
743
|
+
var dicHealth : [String:AnyObject] = [:]
|
744
|
+
let dateFormatter = DateFormatter()
|
745
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"
|
746
|
+
|
747
|
+
for (index, indicator) in healthIndicators.enumerated() {
|
748
|
+
let HealthQuantityType = indicator["key"] as! HKQuantityType
|
749
|
+
|
750
|
+
if let heartRateType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: HealthQuantityType.identifier)) {
|
751
|
+
if (HKHealthStore.isHealthDataAvailable()) {
|
752
|
+
var anchor = HKQueryAnchor.init(fromValue: 0)
|
753
|
+
|
754
|
+
let identifier = HealthQuantityType.identifier.replacingOccurrences(of: "HKQuantityTypeIdentifier", with: "")
|
755
|
+
|
756
|
+
if UserDefaults.standard.object(forKey: identifier) != nil && !isFirstCall {
|
757
|
+
let data = UserDefaults.standard.object(forKey: identifier) as! Data
|
758
|
+
anchor = NSKeyedUnarchiver.unarchiveObject(with: data) as! HKQueryAnchor
|
759
|
+
}
|
760
|
+
|
761
|
+
let query = HKAnchoredObjectQuery(type: heartRateType,
|
762
|
+
predicate: nil,
|
763
|
+
anchor: anchor,
|
764
|
+
limit: HKObjectQueryNoLimit) { (query, results, deletedObjectsOrNil, newAnchor, error) in
|
765
|
+
guard let results = results else {
|
766
|
+
//include the healthkit error in log
|
767
|
+
if error.debugDescription.count > 0 {
|
768
|
+
dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
769
|
+
}
|
770
|
+
|
771
|
+
return
|
772
|
+
}
|
773
|
+
|
774
|
+
anchor = newAnchor!
|
775
|
+
|
776
|
+
let data : Data = NSKeyedArchiver.archivedData(withRootObject: newAnchor as Any)
|
777
|
+
|
778
|
+
UserDefaults.standard.set(data, forKey: identifier)
|
779
|
+
|
780
|
+
var arrHealthValues = [AnyObject]()
|
781
|
+
let strUnitType = indicator["unit"] as! String
|
782
|
+
|
783
|
+
for quantitySample in results {
|
784
|
+
let quantity = (quantitySample as! HKQuantitySample).quantity
|
785
|
+
let healthDataUnit : HKUnit
|
786
|
+
|
787
|
+
if (strUnitType.count > 0 ) {
|
788
|
+
healthDataUnit = HKUnit(from: strUnitType)
|
789
|
+
} else {
|
790
|
+
healthDataUnit = HKUnit.count()
|
791
|
+
}
|
792
|
+
|
793
|
+
let tempActualhealthData = "\(quantity.doubleValue(for: healthDataUnit))"
|
794
|
+
let tempActualRecordedDate = "\(dateFormatter.string(from: quantitySample.startDate))"
|
795
|
+
//print("quantity start date \(quantitySample.startDate)")
|
796
|
+
|
797
|
+
if (tempActualhealthData.count > 0) {
|
798
|
+
let dicHealth : [String:AnyObject] = [HealthValue.kIdentifierValue :tempActualhealthData as AnyObject, HealthValue.kRecordDate :tempActualRecordedDate as AnyObject, HealthValue.kIdentifierDisplayUnit : strUnitType as AnyObject ]
|
799
|
+
|
800
|
+
arrHealthValues.append(dicHealth as AnyObject)
|
801
|
+
}
|
802
|
+
}
|
803
|
+
|
804
|
+
if (arrHealthValues.count > 0) {
|
805
|
+
dicHealth[identifier] = arrHealthValues as AnyObject
|
806
|
+
} else {
|
807
|
+
dicHealth[identifier] = HealthValue.kNoData as AnyObject
|
808
|
+
}
|
809
|
+
|
810
|
+
if(dicHealth.count == 16) {
|
811
|
+
print(self.healthIndicators.count)
|
812
|
+
print(index)
|
813
|
+
|
814
|
+
GetBackFinalhealthData (dicHealth)
|
815
|
+
}
|
816
|
+
}
|
817
|
+
|
818
|
+
(self.HealthStore as! HKHealthStore).execute(query)
|
819
|
+
}
|
820
|
+
}
|
821
|
+
}
|
822
|
+
}
|
823
|
+
@objc public func echo(_ value: String) -> String {
|
824
|
+
print(value)
|
825
|
+
return value
|
826
|
+
}
|
827
|
+
func sumAmounts(_ data: [[String:String]]) -> [[String:String]] {
|
828
|
+
let dateFormatter = DateFormatter()
|
829
|
+
dateFormatter.dateFormat = "yyyy-MM-dd"
|
830
|
+
var dict = [String: Double]()
|
831
|
+
data.forEach { item in
|
832
|
+
|
833
|
+
if let key = item[HealthValue.kRecordDate]?.prefix(10),let value = item[HealthValue.kIdentifierValue] {
|
834
|
+
var amount = dict[String(key)] ?? 0
|
835
|
+
amount += Double(value) ?? 0
|
836
|
+
dict[String(key)] = amount
|
837
|
+
}
|
838
|
+
}
|
839
|
+
|
840
|
+
var newData = [[String:String]]()
|
841
|
+
for (key, val) in dict {
|
842
|
+
newData.append([HealthValue.kRecordDate: key, HealthValue.kIdentifierValue: String(val)])
|
843
|
+
}
|
844
|
+
|
845
|
+
return newData
|
846
|
+
}
|
847
|
+
func getVitalName(name:String) -> String{
|
848
|
+
var vitalName = ""
|
849
|
+
switch(name){
|
850
|
+
case "BloodAlcoholContent":
|
851
|
+
vitalName = "Alcohol Consumption"
|
852
|
+
break;
|
853
|
+
case "BloodGlucose":
|
854
|
+
vitalName = "Blood Glucose"
|
855
|
+
break;
|
856
|
+
case "BodyMass":
|
857
|
+
vitalName = "Weight"
|
858
|
+
break;
|
859
|
+
case "BodyMassIndex":
|
860
|
+
vitalName = "Body Mass Index"
|
861
|
+
break;
|
862
|
+
case "BodyTemperature":
|
863
|
+
vitalName = "Blood Temperature"
|
864
|
+
break;
|
865
|
+
case "HeartRate":
|
866
|
+
vitalName = "HeartRate"
|
867
|
+
break;
|
868
|
+
case "Height":
|
869
|
+
vitalName = "Height"
|
870
|
+
break;
|
871
|
+
case "OxygenSaturation":
|
872
|
+
vitalName = "Blood Oxygen"
|
873
|
+
break;
|
874
|
+
case "RespiratoryRate":
|
875
|
+
vitalName = "Respiratory Rate"
|
876
|
+
break;
|
877
|
+
case "Steps":
|
878
|
+
vitalName = "Steps"
|
879
|
+
break;
|
880
|
+
case "BloodPressure":
|
881
|
+
vitalName = "Blood Pressure"
|
882
|
+
break;
|
883
|
+
default:
|
884
|
+
vitalName = name
|
885
|
+
break;
|
886
|
+
}
|
887
|
+
return vitalName
|
888
|
+
|
889
|
+
}
|
890
|
+
}
|
891
|
+
extension String {
|
892
|
+
func toJSON() -> Any? {
|
893
|
+
guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
|
894
|
+
return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
|
895
|
+
}
|
896
|
+
}
|
897
|
+
extension Calendar {
|
898
|
+
func numberOfDaysBetween(_ from: Date, and to: Date) -> Int {
|
899
|
+
let fromDate = startOfDay(for: from)
|
900
|
+
let toDate = startOfDay(for: to)
|
901
|
+
let numberOfDays = dateComponents([.day], from: fromDate, to: toDate)
|
902
|
+
|
903
|
+
return numberOfDays.day! + 1 // <1>
|
904
|
+
}
|
905
|
+
}
|
906
|
+
extension Double {
|
907
|
+
func roundToDecimal(_ fractionDigits: Int) -> Double {
|
908
|
+
let multiplier = pow(10, Double(fractionDigits))
|
909
|
+
return Darwin.round(self * multiplier) / multiplier
|
910
|
+
}
|
911
|
+
}
|