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.
@@ -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
+ }