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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/health/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 13.1.2

* Fix [#1250](https://github.com/cph-cachet/flutter-plugins/issues/1250)
* Fix [#1233](https://github.com/cph-cachet/flutter-plugins/issues/1233)

## 13.1.1

* Fix [#1207](https://github.com/cph-cachet/flutter-plugins/issues/1207) - (**Important**: Some property names might have changed compared to before for `Nutrition`)
Expand Down

Large diffs are not rendered by default.

258 changes: 64 additions & 194 deletions packages/health/example/lib/main.dart

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/health/example/lib/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const List<HealthDataType> dataTypesIOS = [
HealthDataType.LEAN_BODY_MASS,

// note that a phone cannot write these ECG-based types - only read them
// HealthDataType.ELECTROCARDIOGRAM,
HealthDataType.ELECTROCARDIOGRAM,
// HealthDataType.HIGH_HEART_RATE_EVENT,
// HealthDataType.IRREGULAR_HEART_RATE_EVENT,
// HealthDataType.LOW_HEART_RATE_EVENT,
Expand Down
90 changes: 56 additions & 34 deletions packages/health/ios/Classes/HealthDataReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,16 +303,14 @@ class HealthDataReader {
}
} else {
if #available(iOS 14.0, *), let ecgSamples = samples as? [HKElectrocardiogram] {
let dictionaries = ecgSamples.map(self.fetchEcgMeasurements)
DispatchQueue.main.async {
result(dictionaries)
}
self.fetchEcgMeasurements(ecgSamples, result)
} else {
DispatchQueue.main.async {
print("Error getting ECG - only available on iOS 14.0 and above!")
result(nil)
}
}

}
}

Expand Down Expand Up @@ -546,38 +544,62 @@ class HealthDataReader {
/// - Parameter sample: ECG sample
/// - Returns: Dictionary with ECG data
@available(iOS 14.0, *)
private func fetchEcgMeasurements(_ sample: HKElectrocardiogram) -> NSDictionary {
let semaphore = DispatchSemaphore(value: 0)
var voltageValues = [NSDictionary]()
let voltageQuery = HKElectrocardiogramQuery(sample) { query, result in
switch result {
case let .measurement(measurement):
if let voltageQuantity = measurement.quantity(for: .appleWatchSimilarToLeadI) {
let voltage = voltageQuantity.doubleValue(for: HKUnit.volt())
let timeSinceSampleStart = measurement.timeSinceSampleStart
voltageValues.append(["voltage": voltage, "timeSinceSampleStart": timeSinceSampleStart])
private func fetchEcgMeasurements(_ ecgSample: [HKElectrocardiogram], _ result: @escaping FlutterResult) {
let group = DispatchGroup()
var dictionaries = [NSDictionary]()
let lock = NSLock()

for ecg in ecgSample {
group.enter()

var voltageValues = [[String: Any]]()
let expected = Int(ecg.numberOfVoltageMeasurements)
if expected > 0 {
voltageValues.reserveCapacity(expected)
}

let q = HKElectrocardiogramQuery(ecg) { _, res in
switch res {
case .measurement(let m):
if let v = m.quantity(for: .appleWatchSimilarToLeadI)?
.doubleValue(for: HKUnit.volt()) {
voltageValues.append([
"voltage": v,
"timeSinceSampleStart": m.timeSinceSampleStart
])
}
case .done:
let dict: NSDictionary = [
"uuid": "\(ecg.uuid)",
"voltageValues": voltageValues,
"averageHeartRate": ecg.averageHeartRate?
.doubleValue(for: HKUnit.count()
.unitDivided(by: HKUnit.minute())),
"samplingFrequency": ecg.samplingFrequency?
.doubleValue(for: HKUnit.hertz()),
"classification": ecg.classification.rawValue,
"date_from": Int(ecg.startDate.timeIntervalSince1970 * 1000),
"date_to": Int(ecg.endDate.timeIntervalSince1970 * 1000),
"source_id": ecg.sourceRevision.source.bundleIdentifier,
"source_name": ecg.sourceRevision.source.name
]
lock.lock()
dictionaries.append(dict)
lock.unlock()
group.leave()
case .error(let e):
print("ECG query error: \(e)")
group.leave()
@unknown default:
print("ECG query unknown result")
group.leave()
}
case .done:
semaphore.signal()
case let .error(error):
print(error)
@unknown default:
print("Unknown error occurred")
}
self.healthStore.execute(q)
}

group.notify(queue: .main) {
result(dictionaries)
}
healthStore.execute(voltageQuery)
semaphore.wait()
return [
"uuid": "\(sample.uuid)",
"voltageValues": voltageValues,
"averageHeartRate": sample.averageHeartRate?.doubleValue(
for: HKUnit.count().unitDivided(by: HKUnit.minute())),
"samplingFrequency": sample.samplingFrequency?.doubleValue(for: HKUnit.hertz()),
"classification": sample.classification.rawValue,
"date_from": Int(sample.startDate.timeIntervalSince1970 * 1000),
"date_to": Int(sample.endDate.timeIntervalSince1970 * 1000),
"source_id": sample.sourceRevision.source.bundleIdentifier,
"source_name": sample.sourceRevision.source.name,
]
}
}
2 changes: 1 addition & 1 deletion packages/health/ios/health.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
Pod::Spec.new do |s|
s.name = 'health'
s.version = '13.1.1'
s.version = '13.1.2'
s.summary = 'Wrapper for Apple\'s HealthKit on iOS and Google\'s Health Connect on Android.'
s.description = <<-DESC
Wrapper for Apple's HealthKit on iOS and Google's Health Connect on Android.
Expand Down
2 changes: 1 addition & 1 deletion packages/health/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: health
description: Wrapper for Apple's HealthKit on iOS and Google's Health Connect on Android.
version: 13.1.1
version: 13.1.2
homepage: https://github.com/cph-cachet/flutter-plugins/tree/master/packages/health

environment:
Expand Down