From a2d95d6b18bba070c0c452f66e704d33082b5e79 Mon Sep 17 00:00:00 2001 From: Taisuke J Date: Wed, 9 Oct 2024 23:46:38 +0900 Subject: [PATCH] feat: add aggregateGroupByPeriod API (#157) * feat: add aggregateGroupByPeriod API * fix: replace mapPeriodStringToPeriod with mapJsPeriodToPeriod --- .../healthconnect/HealthConnectManager.kt | 18 +++ .../healthconnect/HealthConnectModule.kt | 5 + .../ReactActiveCaloriesBurnedRecord.kt | 30 ++++- .../ReactBasalBodyTemperatureRecord.kt | 11 ++ .../records/ReactBasalMetabolicRateRecord.kt | 30 ++++- .../records/ReactBloodGlucoseRecord.kt | 11 ++ .../records/ReactBloodPressureRecord.kt | 43 +++++-- .../records/ReactBodyFatRecord.kt | 11 ++ .../records/ReactBodyTemperatureRecord.kt | 11 ++ .../records/ReactBodyWaterMassRecord.kt | 11 ++ .../records/ReactBoneMassRecord.kt | 11 ++ .../records/ReactCervicalMucusRecord.kt | 11 ++ .../ReactCyclingPedalingCadenceRecord.kt | 36 +++++- .../records/ReactDistanceRecord.kt | 34 +++++- .../records/ReactElevationGainedRecord.kt | 31 ++++- .../records/ReactExerciseSessionRecord.kt | 29 ++++- .../records/ReactFloorsClimbedRecord.kt | 29 ++++- .../records/ReactHealthRecord.kt | 14 +++ .../records/ReactHealthRecordImpl.kt | 5 + .../records/ReactHeartRateRecord.kt | 38 +++++- .../ReactHeartRateVariabilityRmssdRecord.kt | 11 ++ .../records/ReactHeightRecord.kt | 37 +++++- .../records/ReactHydrationRecord.kt | 31 ++++- .../ReactIntermenstrualBleedingRecord.kt | 11 ++ .../records/ReactLeanBodyMassRecord.kt | 11 ++ .../records/ReactMenstruationFlowRecord.kt | 11 ++ .../records/ReactMenstruationPeriodRecord.kt | 11 ++ .../records/ReactNutritionRecord.kt | 111 +++++++++++------- .../records/ReactOvulationTestRecord.kt | 11 ++ .../records/ReactOxygenSaturationRecord.kt | 11 ++ .../healthconnect/records/ReactPowerRecord.kt | 36 +++++- .../records/ReactRespiratoryRateRecord.kt | 11 ++ .../records/ReactRestingHeartRateRecord.kt | 37 +++++- .../records/ReactSexualActivityRecord.kt | 11 ++ .../records/ReactSleepSessionRecord.kt | 30 ++++- .../healthconnect/records/ReactSpeedRecord.kt | 36 +++++- .../records/ReactStepsCadenceRecord.kt | 36 +++++- .../healthconnect/records/ReactStepsRecord.kt | 31 ++++- .../records/ReactTotalCaloriesBurnedRecord.kt | 31 ++++- .../records/ReactVo2MaxRecord.kt | 11 ++ .../records/ReactWeightRecord.kt | 37 +++++- .../records/ReactWheelchairPushesRecord.kt | 31 ++++- .../healthconnect/utils/HealthConnectUtils.kt | 15 +++ android/src/oldarch/HealthConnectSpec.kt | 3 + example/src/App.tsx | 98 ++++++++++++---- src/NativeHealthConnect.ts | 7 ++ src/index.tsx | 8 ++ src/types/aggregate.types.ts | 20 +++- src/types/base.types.ts | 5 + 49 files changed, 1028 insertions(+), 141 deletions(-) diff --git a/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt b/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt index 8440535..074f083 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt @@ -148,6 +148,24 @@ class HealthConnectManager(private val applicationContext: ReactApplicationConte } } + fun aggregateGroupByPeriod(record: ReadableMap, promise: Promise) { + throwUnlessClientIsAvailable(promise) { + coroutineScope.launch { + try { + val recordType = record.getString("recordType") ?: "" + val response = healthConnectClient.aggregateGroupByPeriod( + ReactHealthRecord.getAggregateGroupByPeriodRequest( + recordType, record + ) + ) + promise.resolve(ReactHealthRecord.parseAggregationResultGroupedByPeriod(recordType, response)) + } catch (e: Exception) { + promise.rejectWithException(e) + } + } + } + } + fun getChanges(options: ReadableMap, promise: Promise) { throwUnlessClientIsAvailable(promise) { coroutineScope.launch { diff --git a/android/src/main/java/dev/matinzd/healthconnect/HealthConnectModule.kt b/android/src/main/java/dev/matinzd/healthconnect/HealthConnectModule.kt index ea871a8..0001418 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/HealthConnectModule.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/HealthConnectModule.kt @@ -70,6 +70,11 @@ class HealthConnectModule internal constructor(context: ReactApplicationContext) return manager.aggregateRecord(record, promise) } + @ReactMethod + override fun aggregateGroupByPeriod(record: ReadableMap, promise: Promise) { + return manager.aggregateGroupByPeriod(record, promise) + } + @ReactMethod override fun getChanges(options: ReadableMap, promise: Promise) { return manager.getChanges(options, promise) diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactActiveCaloriesBurnedRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactActiveCaloriesBurnedRecord.kt index 77c5fab..36dc0fd 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactActiveCaloriesBurnedRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactActiveCaloriesBurnedRecord.kt @@ -1,11 +1,14 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.ActiveCaloriesBurnedRecord import androidx.health.connect.client.request.AggregateRequest +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableNativeMap +import com.facebook.react.bridge.WritableNativeArray import dev.matinzd.healthconnect.utils.convertDataOriginsToJsArray import dev.matinzd.healthconnect.utils.convertJsToDataOriginSet import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -14,9 +17,12 @@ import dev.matinzd.healthconnect.utils.energyToJsMap import dev.matinzd.healthconnect.utils.getEnergyFromJsMap import dev.matinzd.healthconnect.utils.getTimeRangeFilter import dev.matinzd.healthconnect.utils.toMapList +import dev.matinzd.healthconnect.utils.mapJsPeriodToPeriod import java.time.Instant class ReactActiveCaloriesBurnedRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(ActiveCaloriesBurnedRecord.ACTIVE_CALORIES_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { ActiveCaloriesBurnedRecord( @@ -41,8 +47,17 @@ class ReactActiveCaloriesBurnedRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalBodyTemperatureRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalBodyTemperatureRecord.kt index 76345c3..bb4f5c4 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalBodyTemperatureRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalBodyTemperatureRecord.kt @@ -1,12 +1,15 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BasalBodyTemperatureRecord import androidx.health.connect.client.records.BodyTemperatureMeasurementLocation +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Temperature import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.InvalidTemperature @@ -45,10 +48,18 @@ class ReactBasalBodyTemperatureRecord : ReactHealthRecordImpl): WritableNativeArray { + throw AggregationNotSupported() + } + private fun getTemperatureFromJsMap(temperatureMap: ReadableMap?): Temperature { if (temperatureMap == null) { throw InvalidTemperature() diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalMetabolicRateRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalMetabolicRateRecord.kt index 081b260..70b1f80 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalMetabolicRateRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBasalMetabolicRateRecord.kt @@ -1,11 +1,14 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BasalMetabolicRateRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Power import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.InvalidPower import dev.matinzd.healthconnect.utils.convertDataOriginsToJsArray @@ -13,10 +16,13 @@ import dev.matinzd.healthconnect.utils.convertJsToDataOriginSet import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap import dev.matinzd.healthconnect.utils.convertMetadataToJSMap import dev.matinzd.healthconnect.utils.getTimeRangeFilter +import dev.matinzd.healthconnect.utils.mapJsPeriodToPeriod import dev.matinzd.healthconnect.utils.toMapList import java.time.Instant class ReactBasalMetabolicRateRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(BasalMetabolicRateRecord.BASAL_CALORIES_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { BasalMetabolicRateRecord( @@ -38,12 +44,34 @@ class ReactBasalMetabolicRateRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { val map = WritableNativeMap().apply { diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodGlucoseRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodGlucoseRecord.kt index 4883fa5..621c3f0 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodGlucoseRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodGlucoseRecord.kt @@ -1,12 +1,15 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BloodGlucoseRecord import androidx.health.connect.client.records.MealType.MEAL_TYPE_UNKNOWN +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.BloodGlucose import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.InvalidBloodGlucoseLevel @@ -50,10 +53,18 @@ class ReactBloodGlucoseRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } + private fun bloodGlucoseToJsMap(bloodGlucose: BloodGlucose): WritableNativeMap { return WritableNativeMap().apply { putDouble("inMillimolesPerLiter", bloodGlucose.inMillimolesPerLiter) diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodPressureRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodPressureRecord.kt index 967feeb..d956a6c 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodPressureRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBloodPressureRecord.kt @@ -1,16 +1,28 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BloodPressureRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Pressure import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactBloodPressureRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + BloodPressureRecord.SYSTOLIC_AVG, + BloodPressureRecord.SYSTOLIC_MIN, + BloodPressureRecord.SYSTOLIC_MAX, + BloodPressureRecord.DIASTOLIC_AVG, + BloodPressureRecord.DIASTOLIC_MIN, + BloodPressureRecord.DIASTOLIC_MAX + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { BloodPressureRecord( @@ -40,19 +52,21 @@ class ReactBloodPressureRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - BloodPressureRecord.SYSTOLIC_AVG, - BloodPressureRecord.SYSTOLIC_MIN, - BloodPressureRecord.SYSTOLIC_MAX, - BloodPressureRecord.DIASTOLIC_AVG, - BloodPressureRecord.DIASTOLIC_MIN, - BloodPressureRecord.DIASTOLIC_MAX - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { @@ -80,6 +94,19 @@ class ReactBloodPressureRecord : ReactHealthRecordImpl { } } + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } + private fun bloodPressureToJsMap(pressure: Pressure): WritableNativeMap { return WritableNativeMap().apply { putDouble("inMillimetersOfMercury", pressure.inMillimetersOfMercury) diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyFatRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyFatRecord.kt index b76bc77..a04ea9b 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyFatRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyFatRecord.kt @@ -1,11 +1,14 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BodyFatRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Percentage import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,6 +40,14 @@ class ReactBodyFatRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyTemperatureRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyTemperatureRecord.kt index d4d3942..49807a3 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyTemperatureRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyTemperatureRecord.kt @@ -1,12 +1,15 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BodyTemperatureMeasurementLocation import androidx.health.connect.client.records.BodyTemperatureRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Temperature import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.InvalidTemperature @@ -45,10 +48,18 @@ class ReactBodyTemperatureRecord : ReactHealthRecordImpl throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } + private fun getTemperatureFromJsMap(temperatureMap: ReadableMap?): Temperature { if (temperatureMap == null) { throw InvalidTemperature() diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyWaterMassRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyWaterMassRecord.kt index 589100b..d8bd886 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyWaterMassRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBodyWaterMassRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BodyWaterMassRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant @@ -33,7 +36,15 @@ class ReactBodyWaterMassRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBoneMassRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBoneMassRecord.kt index b4d7cc8..e5c27ae 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactBoneMassRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactBoneMassRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.BoneMassRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -38,7 +41,15 @@ class ReactBoneMassRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactCervicalMucusRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactCervicalMucusRecord.kt index 08942be..ec4977f 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactCervicalMucusRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactCervicalMucusRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.CervicalMucusRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -39,7 +42,15 @@ class ReactCervicalMucusRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactCyclingPedalingCadenceRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactCyclingPedalingCadenceRecord.kt index 2fe0913..8967b50 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactCyclingPedalingCadenceRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactCyclingPedalingCadenceRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.CyclingPedalingCadenceRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,12 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactCyclingPedalingCadenceRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + CyclingPedalingCadenceRecord.RPM_AVG, + CyclingPedalingCadenceRecord.RPM_MAX, + CyclingPedalingCadenceRecord.RPM_MIN + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> CyclingPedalingCadenceRecord( @@ -48,12 +56,17 @@ class ReactCyclingPedalingCadenceRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactDistanceRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactDistanceRecord.kt index 7ce02e2..7c66b0a 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactDistanceRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactDistanceRecord.kt @@ -1,15 +1,22 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.DistanceRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactDistanceRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + DistanceRecord.DISTANCE_TOTAL, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> DistanceRecord( @@ -23,7 +30,6 @@ class ReactDistanceRecord : ReactHealthRecordImpl { } } - override fun parseRecord(record: DistanceRecord): WritableNativeMap { return WritableNativeMap().apply { putString("startTime", record.startTime.toString()) @@ -35,10 +41,17 @@ class ReactDistanceRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - DistanceRecord.DISTANCE_TOTAL, - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -49,4 +62,17 @@ class ReactDistanceRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactElevationGainedRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactElevationGainedRecord.kt index 8114d7f..3382037 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactElevationGainedRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactElevationGainedRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.ElevationGainedRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactElevationGainedRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(ElevationGainedRecord.ELEVATION_GAINED_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { ElevationGainedRecord( @@ -34,18 +39,38 @@ class ReactElevationGainedRecord : ReactHealthRecordImpl override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - ElevationGainedRecord.ELEVATION_GAINED_TOTAL - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putMap("ELEVATION_GAINED_TOTAL", lengthToJsMap(record[ElevationGainedRecord.ELEVATION_GAINED_TOTAL])) putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactExerciseSessionRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactExerciseSessionRecord.kt index 2f01df1..ae8704f 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactExerciseSessionRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactExerciseSessionRecord.kt @@ -1,12 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.ExerciseLap import androidx.health.connect.client.records.ExerciseRoute import androidx.health.connect.client.records.ExerciseRouteResult import androidx.health.connect.client.records.ExerciseSegment import androidx.health.connect.client.records.ExerciseSessionRecord -import androidx.health.connect.client.records.PowerRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -16,6 +17,8 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactExerciseSessionRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(ExerciseSessionRecord.EXERCISE_DURATION_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { val routeList = it.getMap("exerciseRoute")?.getArray("route")?.toMapList()?.map { sample -> @@ -135,8 +138,17 @@ class ReactExerciseSessionRecord : ReactHealthRecordImpl override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf(ExerciseSessionRecord.EXERCISE_DURATION_TOTAL), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -153,4 +165,17 @@ class ReactExerciseSessionRecord : ReactHealthRecordImpl putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactFloorsClimbedRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactFloorsClimbedRecord.kt index 88f21cf..3156710 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactFloorsClimbedRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactFloorsClimbedRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.FloorsClimbedRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactFloorsClimbedRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(FloorsClimbedRecord.FLOORS_CLIMBED_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { FloorsClimbedRecord( @@ -34,16 +39,38 @@ class ReactFloorsClimbedRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf(FloorsClimbedRecord.FLOORS_CLIMBED_TOTAL), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putDouble("FLOORS_CLIMBED_TOTAL", record[FloorsClimbedRecord.FLOORS_CLIMBED_TOTAL] ?: 0.0) putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecord.kt index d8660ef..7812689 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecord.kt @@ -1,8 +1,10 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.Record import androidx.health.connect.client.request.AggregateRequest +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.ReadRecordsRequest import androidx.health.connect.client.response.InsertRecordsResponse import androidx.health.connect.client.response.ReadRecordResponse @@ -71,12 +73,24 @@ class ReactHealthRecord { return recordClass.getAggregateRequest(reactRequest) } + fun getAggregateGroupByPeriodRequest(recordType: String, reactRequest: ReadableMap): AggregateGroupByPeriodRequest { + val recordClass = createReactHealthRecordInstance(recordType) + + return recordClass.getAggregateGroupByPeriodRequest(reactRequest) + } + fun parseAggregationResult(recordType: String, result: AggregationResult): WritableNativeMap { val recordClass = createReactHealthRecordInstance(recordType) return recordClass.parseAggregationResult(result) } + fun parseAggregationResultGroupedByPeriod(recordType: String, result: List): WritableNativeArray { + val recordClass = createReactHealthRecordInstance(recordType) + + return recordClass.parseAggregationResultGroupedByPeriod(result) + } + fun parseRecords( recordType: String, response: ReadRecordsResponse diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecordImpl.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecordImpl.kt index 0ad3ae9..36c2a14 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecordImpl.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHealthRecordImpl.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.Record import androidx.health.connect.client.request.AggregateRequest +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableNativeMap +import com.facebook.react.bridge.WritableNativeArray interface ReactHealthRecordImpl { fun parseWriteRecord(records: ReadableArray): List fun parseRecord(record: T): WritableNativeMap fun getAggregateRequest(record: ReadableMap): AggregateRequest + fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest fun parseAggregationResult(record: AggregationResult): WritableNativeMap + fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateRecord.kt index 739d92c..d292f93 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.HeartRateRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,13 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactHeartRateRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + HeartRateRecord.BPM_AVG, + HeartRateRecord.BPM_MAX, + HeartRateRecord.BPM_MIN, + HeartRateRecord.MEASUREMENTS_COUNT + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> HeartRateRecord( @@ -48,13 +57,17 @@ class ReactHeartRateRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - HeartRateRecord.BPM_AVG, - HeartRateRecord.BPM_MAX, - HeartRateRecord.BPM_MIN, - HeartRateRecord.MEASUREMENTS_COUNT - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -68,4 +81,17 @@ class ReactHeartRateRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateVariabilityRmssdRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateVariabilityRmssdRecord.kt index 8335bb0..d4d7f95 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateVariabilityRmssdRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeartRateVariabilityRmssdRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.HeartRateVariabilityRmssdRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,7 +40,15 @@ class ReactHeartRateVariabilityRmssdRecord : throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeightRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeightRecord.kt index 4058285..6d05598 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeightRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHeightRecord.kt @@ -1,15 +1,24 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.HeightRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactHeightRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + HeightRecord.HEIGHT_AVG, + HeightRecord.HEIGHT_MAX, + HeightRecord.HEIGHT_MIN, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> HeightRecord( @@ -31,16 +40,21 @@ class ReactHeightRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - HeightRecord.HEIGHT_AVG, - HeightRecord.HEIGHT_MAX, - HeightRecord.HEIGHT_MIN, - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putMap("HEIGHT_AVG", lengthToJsMap(record[HeightRecord.HEIGHT_AVG])) @@ -49,4 +63,17 @@ class ReactHeightRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHydrationRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHydrationRecord.kt index 7ea9b65..bac39e0 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactHydrationRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactHydrationRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.HydrationRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactHydrationRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(HydrationRecord.VOLUME_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> HydrationRecord( @@ -34,18 +39,38 @@ class ReactHydrationRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - HydrationRecord.VOLUME_TOTAL, - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putMap("VOLUME_TOTAL", volumeToJsMap(record[HydrationRecord.VOLUME_TOTAL])) putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactIntermenstrualBleedingRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactIntermenstrualBleedingRecord.kt index 13c8630..1b16a8f 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactIntermenstrualBleedingRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactIntermenstrualBleedingRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.IntermenstrualBleedingRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -34,7 +37,15 @@ class ReactIntermenstrualBleedingRecord : ReactHealthRecordImpl): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactLeanBodyMassRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactLeanBodyMassRecord.kt index 2cf1eaf..94daacc 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactLeanBodyMassRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactLeanBodyMassRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.LeanBodyMassRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant @@ -33,7 +36,15 @@ class ReactLeanBodyMassRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationFlowRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationFlowRecord.kt index 0bda1fe..753e4a5 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationFlowRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationFlowRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.MenstruationFlowRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,7 +40,15 @@ class ReactMenstruationFlowRecord : ReactHealthRecordImpl): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationPeriodRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationPeriodRecord.kt index 85f8a50..ab11c2b 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationPeriodRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactMenstruationPeriodRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.MenstruationPeriodRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,7 +40,15 @@ class ReactMenstruationPeriodRecord : ReactHealthRecordImpl): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactNutritionRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactNutritionRecord.kt index f0811cb..2cbe287 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactNutritionRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactNutritionRecord.kt @@ -1,16 +1,62 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.MealType import androidx.health.connect.client.records.NutritionRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactNutritionRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + NutritionRecord.BIOTIN_TOTAL, + NutritionRecord.CAFFEINE_TOTAL, + NutritionRecord.CALCIUM_TOTAL, + NutritionRecord.ENERGY_TOTAL, + NutritionRecord.ENERGY_FROM_FAT_TOTAL, + NutritionRecord.CHLORIDE_TOTAL, + NutritionRecord.CHOLESTEROL_TOTAL, + NutritionRecord.CHROMIUM_TOTAL, + NutritionRecord.COPPER_TOTAL, + NutritionRecord.DIETARY_FIBER_TOTAL, + NutritionRecord.FOLATE_TOTAL, + NutritionRecord.FOLIC_ACID_TOTAL, + NutritionRecord.IODINE_TOTAL, + NutritionRecord.IRON_TOTAL, + NutritionRecord.MAGNESIUM_TOTAL, + NutritionRecord.MANGANESE_TOTAL, + NutritionRecord.MOLYBDENUM_TOTAL, + NutritionRecord.MONOUNSATURATED_FAT_TOTAL, + NutritionRecord.NIACIN_TOTAL, + NutritionRecord.PANTOTHENIC_ACID_TOTAL, + NutritionRecord.PHOSPHORUS_TOTAL, + NutritionRecord.POLYUNSATURATED_FAT_TOTAL, + NutritionRecord.POTASSIUM_TOTAL, + NutritionRecord.PROTEIN_TOTAL, + NutritionRecord.RIBOFLAVIN_TOTAL, + NutritionRecord.SATURATED_FAT_TOTAL, + NutritionRecord.SELENIUM_TOTAL, + NutritionRecord.SODIUM_TOTAL, + NutritionRecord.SUGAR_TOTAL, + NutritionRecord.THIAMIN_TOTAL, + NutritionRecord.TOTAL_CARBOHYDRATE_TOTAL, + NutritionRecord.TOTAL_FAT_TOTAL, + NutritionRecord.ZINC_TOTAL, + NutritionRecord.VITAMIN_A_TOTAL, + NutritionRecord.VITAMIN_B12_TOTAL, + NutritionRecord.VITAMIN_B6_TOTAL, + NutritionRecord.VITAMIN_C_TOTAL, + NutritionRecord.VITAMIN_D_TOTAL, + NutritionRecord.VITAMIN_E_TOTAL, + NutritionRecord.VITAMIN_K_TOTAL, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> NutritionRecord( @@ -121,53 +167,21 @@ class ReactNutritionRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - NutritionRecord.BIOTIN_TOTAL, - NutritionRecord.CAFFEINE_TOTAL, - NutritionRecord.CALCIUM_TOTAL, - NutritionRecord.ENERGY_TOTAL, - NutritionRecord.ENERGY_FROM_FAT_TOTAL, - NutritionRecord.CHLORIDE_TOTAL, - NutritionRecord.CHOLESTEROL_TOTAL, - NutritionRecord.CHROMIUM_TOTAL, - NutritionRecord.COPPER_TOTAL, - NutritionRecord.DIETARY_FIBER_TOTAL, - NutritionRecord.FOLATE_TOTAL, - NutritionRecord.FOLIC_ACID_TOTAL, - NutritionRecord.IODINE_TOTAL, - NutritionRecord.IRON_TOTAL, - NutritionRecord.MAGNESIUM_TOTAL, - NutritionRecord.MANGANESE_TOTAL, - NutritionRecord.MOLYBDENUM_TOTAL, - NutritionRecord.MONOUNSATURATED_FAT_TOTAL, - NutritionRecord.NIACIN_TOTAL, - NutritionRecord.PANTOTHENIC_ACID_TOTAL, - NutritionRecord.PHOSPHORUS_TOTAL, - NutritionRecord.POLYUNSATURATED_FAT_TOTAL, - NutritionRecord.POTASSIUM_TOTAL, - NutritionRecord.PROTEIN_TOTAL, - NutritionRecord.RIBOFLAVIN_TOTAL, - NutritionRecord.SATURATED_FAT_TOTAL, - NutritionRecord.SELENIUM_TOTAL, - NutritionRecord.SODIUM_TOTAL, - NutritionRecord.SUGAR_TOTAL, - NutritionRecord.THIAMIN_TOTAL, - NutritionRecord.TOTAL_CARBOHYDRATE_TOTAL, - NutritionRecord.TOTAL_FAT_TOTAL, - NutritionRecord.ZINC_TOTAL, - NutritionRecord.VITAMIN_A_TOTAL, - NutritionRecord.VITAMIN_B12_TOTAL, - NutritionRecord.VITAMIN_B6_TOTAL, - NutritionRecord.VITAMIN_C_TOTAL, - NutritionRecord.VITAMIN_D_TOTAL, - NutritionRecord.VITAMIN_E_TOTAL, - NutritionRecord.VITAMIN_K_TOTAL, - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putMap("BIOTIN_TOTAL", massToJsMap(record[NutritionRecord.BIOTIN_TOTAL])) @@ -221,4 +235,17 @@ class ReactNutritionRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactOvulationTestRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactOvulationTestRecord.kt index 1eae7c6..ac1adc6 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactOvulationTestRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactOvulationTestRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.OvulationTestRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,7 +40,15 @@ class ReactOvulationTestRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactOxygenSaturationRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactOxygenSaturationRecord.kt index 4dba951..23ea818 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactOxygenSaturationRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactOxygenSaturationRecord.kt @@ -1,11 +1,14 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.OxygenSaturationRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.units.Percentage import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -37,7 +40,15 @@ class ReactOxygenSaturationRecord : ReactHealthRecordImpl): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactPowerRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactPowerRecord.kt index 88f9f4c..0082c28 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactPowerRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactPowerRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.PowerRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,12 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactPowerRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + PowerRecord.POWER_AVG, + PowerRecord.POWER_MAX, + PowerRecord.POWER_MIN, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> PowerRecord( @@ -48,12 +56,17 @@ class ReactPowerRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - PowerRecord.POWER_AVG, - PowerRecord.POWER_MAX, - PowerRecord.POWER_MIN, - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -66,4 +79,17 @@ class ReactPowerRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactRespiratoryRateRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactRespiratoryRateRecord.kt index 48cc963..fedfc3b 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactRespiratoryRateRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactRespiratoryRateRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.RespiratoryRateRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -34,7 +37,15 @@ class ReactRespiratoryRateRecord : ReactHealthRecordImpl throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactRestingHeartRateRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactRestingHeartRateRecord.kt index b0126a0..5fe0368 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactRestingHeartRateRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactRestingHeartRateRecord.kt @@ -1,15 +1,24 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.RestingHeartRateRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactRestingHeartRateRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + RestingHeartRateRecord.BPM_AVG, + RestingHeartRateRecord.BPM_MAX, + RestingHeartRateRecord.BPM_MIN, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> RestingHeartRateRecord( @@ -31,16 +40,21 @@ class ReactRestingHeartRateRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSexualActivityRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSexualActivityRecord.kt index edea4aa..fa4bbe6 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSexualActivityRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSexualActivityRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.SexualActivityRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -36,7 +39,15 @@ class ReactSexualActivityRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSleepSessionRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSleepSessionRecord.kt index 4fc592e..a317368 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSleepSessionRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSleepSessionRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.SleepSessionRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,8 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactSleepSessionRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(SleepSessionRecord.SLEEP_DURATION_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> SleepSessionRecord( @@ -53,10 +57,17 @@ class ReactSleepSessionRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - SleepSessionRecord.SLEEP_DURATION_TOTAL - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -70,4 +81,17 @@ class ReactSleepSessionRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSpeedRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSpeedRecord.kt index 83f3231..fae1ea4 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactSpeedRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactSpeedRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.SpeedRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,12 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactSpeedRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + SpeedRecord.SPEED_AVG, + SpeedRecord.SPEED_MIN, + SpeedRecord.SPEED_MAX, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> SpeedRecord( @@ -48,12 +56,17 @@ class ReactSpeedRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - SpeedRecord.SPEED_AVG, - SpeedRecord.SPEED_MIN, - SpeedRecord.SPEED_MAX, - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -66,4 +79,17 @@ class ReactSpeedRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsCadenceRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsCadenceRecord.kt index fd3cab2..e34d207 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsCadenceRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsCadenceRecord.kt @@ -1,7 +1,9 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.StepsCadenceRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -11,6 +13,12 @@ import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactStepsCadenceRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + StepsCadenceRecord.RATE_AVG, + StepsCadenceRecord.RATE_MAX, + StepsCadenceRecord.RATE_MIN, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> StepsCadenceRecord( @@ -48,12 +56,17 @@ class ReactStepsCadenceRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - StepsCadenceRecord.RATE_AVG, - StepsCadenceRecord.RATE_MAX, - StepsCadenceRecord.RATE_MIN, - ), + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } @@ -66,4 +79,17 @@ class ReactStepsCadenceRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsRecord.kt index 53b5c6c..90b6452 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactStepsRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.StepsRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactStepsRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(StepsRecord.COUNT_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> StepsRecord( @@ -34,18 +39,38 @@ class ReactStepsRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - StepsRecord.COUNT_TOTAL - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putDouble("COUNT_TOTAL", record[StepsRecord.COUNT_TOTAL]?.toDouble() ?: 0.0) putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactTotalCaloriesBurnedRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactTotalCaloriesBurnedRecord.kt index 8b299d0..170539b 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactTotalCaloriesBurnedRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactTotalCaloriesBurnedRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.TotalCaloriesBurnedRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactTotalCaloriesBurnedRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(TotalCaloriesBurnedRecord.ENERGY_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> TotalCaloriesBurnedRecord( @@ -34,10 +39,17 @@ class ReactTotalCaloriesBurnedRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactVo2MaxRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactVo2MaxRecord.kt index 6ebb121..6b95c2f 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactVo2MaxRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactVo2MaxRecord.kt @@ -1,10 +1,13 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.Vo2MaxRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.AggregationNotSupported import dev.matinzd.healthconnect.utils.convertMetadataFromJSMap @@ -42,7 +45,15 @@ class ReactVo2MaxRecord : ReactHealthRecordImpl { throw AggregationNotSupported() } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + throw AggregationNotSupported() + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { throw AggregationNotSupported() } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + throw AggregationNotSupported() + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactWeightRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactWeightRecord.kt index 5cc5568..c8e2532 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactWeightRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactWeightRecord.kt @@ -1,15 +1,24 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.WeightRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactWeightRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf( + WeightRecord.WEIGHT_AVG, + WeightRecord.WEIGHT_MAX, + WeightRecord.WEIGHT_MIN, + ) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> WeightRecord( @@ -31,16 +40,21 @@ class ReactWeightRecord : ReactHealthRecordImpl { override fun getAggregateRequest(record: ReadableMap): AggregateRequest { return AggregateRequest( - metrics = setOf( - WeightRecord.WEIGHT_AVG, - WeightRecord.WEIGHT_MAX, - WeightRecord.WEIGHT_MIN, - ), + metrics = aggregateMetrics, timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) ) } + override fun getAggregateGroupByPeriodRequest(record: ReadableMap): AggregateGroupByPeriodRequest { + return AggregateGroupByPeriodRequest( + metrics = aggregateMetrics, + timeRangeFilter = record.getTimeRangeFilter("timeRangeFilter"), + timeRangeSlicer = mapJsPeriodToPeriod(record.getMap("timeRangeSlicer")), + dataOriginFilter = convertJsToDataOriginSet(record.getArray("dataOriginFilter")) + ) + } + override fun parseAggregationResult(record: AggregationResult): WritableNativeMap { return WritableNativeMap().apply { putMap("WEIGHT_AVG", massToJsMap(record[WeightRecord.WEIGHT_AVG])) @@ -49,4 +63,17 @@ class ReactWeightRecord : ReactHealthRecordImpl { putArray("dataOrigins", convertDataOriginsToJsArray(record.dataOrigins)) } } + + override fun parseAggregationResultGroupedByPeriod(record: List): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/records/ReactWheelchairPushesRecord.kt b/android/src/main/java/dev/matinzd/healthconnect/records/ReactWheelchairPushesRecord.kt index d377c06..dd6e765 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/records/ReactWheelchairPushesRecord.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/records/ReactWheelchairPushesRecord.kt @@ -1,15 +1,20 @@ package dev.matinzd.healthconnect.records import androidx.health.connect.client.aggregate.AggregationResult +import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod import androidx.health.connect.client.records.WheelchairPushesRecord +import androidx.health.connect.client.request.AggregateGroupByPeriodRequest import androidx.health.connect.client.request.AggregateRequest import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableNativeArray import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.utils.* import java.time.Instant class ReactWheelchairPushesRecord : ReactHealthRecordImpl { + private val aggregateMetrics = setOf(WheelchairPushesRecord.COUNT_TOTAL) + override fun parseWriteRecord(records: ReadableArray): List { return records.toMapList().map { map -> WheelchairPushesRecord( @@ -34,18 +39,38 @@ class ReactWheelchairPushesRecord : ReactHealthRecordImpl): WritableNativeArray { + return WritableNativeArray().apply { + record.forEach { + val map = WritableNativeMap().apply { + putMap("result", parseAggregationResult(it.result)) + putString("startTime", it.startTime.toString()) + putString("endTime", it.endTime.toString()) + } + pushMap(map) + } + } + } } diff --git a/android/src/main/java/dev/matinzd/healthconnect/utils/HealthConnectUtils.kt b/android/src/main/java/dev/matinzd/healthconnect/utils/HealthConnectUtils.kt index be55e9c..ec07b5b 100644 --- a/android/src/main/java/dev/matinzd/healthconnect/utils/HealthConnectUtils.kt +++ b/android/src/main/java/dev/matinzd/healthconnect/utils/HealthConnectUtils.kt @@ -15,6 +15,7 @@ import com.facebook.react.bridge.WritableNativeMap import dev.matinzd.healthconnect.records.* import java.time.Instant import java.time.ZoneOffset +import java.time.Period import kotlin.reflect.KClass fun convertReactRequestOptionsFromJS( @@ -455,3 +456,17 @@ fun convertChangesTokenRequestOptionsFromJS(options: ReadableMap): ChangesTokenR dataOriginFilters = convertJsToDataOriginSet(options.getArray("dataOriginFilters")), ) } + +fun mapJsPeriodToPeriod(period: ReadableMap?): Period { + if (period == null) { + return Period.ofDays(0) + } + val duration = period.getInt("duration") + return when (period.getString("period")) { + "DAYS" -> Period.ofDays(duration) + "WEEKS" -> Period.ofWeeks(duration) + "MONTHS" -> Period.ofMonths(duration) + "YEARS" -> Period.ofYears(duration) + else -> Period.ofDays(duration) + } +} diff --git a/android/src/oldarch/HealthConnectSpec.kt b/android/src/oldarch/HealthConnectSpec.kt index 9363122..b54692c 100644 --- a/android/src/oldarch/HealthConnectSpec.kt +++ b/android/src/oldarch/HealthConnectSpec.kt @@ -38,6 +38,9 @@ abstract class HealthConnectSpec internal constructor(context: ReactApplicationC @ReactMethod abstract fun aggregateRecord(record: ReadableMap, promise: Promise); + @ReactMethod + abstract fun aggregateGroupByPeriod(record: ReadableMap, promise: Promise); + @ReactMethod abstract fun getChanges(options: ReadableMap, promise: Promise); diff --git a/example/src/App.tsx b/example/src/App.tsx index 51aa75e..eeb211a 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { Button, StyleSheet, View } from 'react-native'; import { aggregateRecord, + aggregateGroupByPeriod, getGrantedPermissions, initialize, insertRecords, @@ -16,14 +17,21 @@ import { readRecord, RecordingMethod, DeviceType, + HealthConnectRecord, } from 'react-native-health-connect'; -const getLastWeekDate = (): Date => { - return new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000); +const getBeginningOfLast7Days = () => { + const day = new Date(); + day.setDate(day.getDate() - 7); + day.setHours(0, 0, 0, 0); + return day; }; -const getLastTwoWeeksDate = (): Date => { - return new Date(new Date().getTime() - 2 * 7 * 24 * 60 * 60 * 1000); +const getBeginningOfLast14Days = () => { + const day = new Date(); + day.setDate(day.getDate() - 14); + day.setHours(0, 0, 0, 0); + return day; }; const getTodayDate = (): Date => { @@ -58,24 +66,49 @@ export default function App() { }; const insertSampleData = () => { - insertRecords([ - { - recordType: 'Steps', - count: 1000, - startTime: getLastWeekDate().toISOString(), - endTime: getTodayDate().toISOString(), - metadata: { - clientRecordId: random64BitString(), - recordingMethod: - RecordingMethod.RECORDING_METHOD_AUTOMATICALLY_RECORDED, - device: { - manufacturer: 'Google', - model: 'Pixel 4', - type: DeviceType.TYPE_PHONE, + const days = 7; + const startingStepCount = 1000; + + const records = Array.from({ length: days }).reduce( + (acc: HealthConnectRecord[], _, i) => { + // Step count increases by 1000 starting from the first day (7 days ago) + const stepCount = startingStepCount + i * 1000; + const day = new Date(); + + // Get the date for each of the last 7 days, starting from 7 days ago (excluding today) + day.setDate(day.getDate() - (days - i)); + + // Set start time to 9am + const startTime = new Date(day); + startTime.setHours(9, 0, 0, 0); + + // Set end time to 11am + const endTime = new Date(day); + endTime.setHours(11, 0, 0, 0); + + const record: HealthConnectRecord = { + recordType: 'Steps', + count: stepCount, + startTime: startTime.toISOString(), + endTime: endTime.toISOString(), + metadata: { + clientRecordId: random64BitString(), + recordingMethod: + RecordingMethod.RECORDING_METHOD_AUTOMATICALLY_RECORDED, + device: { + manufacturer: 'Google', + model: 'Pixel 4', + type: DeviceType.TYPE_PHONE, + }, }, - }, + }; + + return [...acc, record]; }, - ]) + [] + ); + + insertRecords(records) .then((ids) => { console.log('Records inserted ', { ids }); }) @@ -88,7 +121,7 @@ export default function App() { readRecords('Steps', { timeRangeFilter: { operator: 'between', - startTime: getLastTwoWeeksDate().toISOString(), + startTime: getBeginningOfLast14Days().toISOString(), endTime: getTodayDate().toISOString(), }, }) @@ -115,7 +148,7 @@ export default function App() { recordType: 'Steps', timeRangeFilter: { operator: 'between', - startTime: getLastWeekDate().toISOString(), + startTime: getBeginningOfLast7Days().toISOString(), endTime: getTodayDate().toISOString(), }, }).then((result) => { @@ -123,6 +156,23 @@ export default function App() { }); }; + const aggregateSampleGroupByPeriod = () => { + aggregateGroupByPeriod({ + recordType: 'Steps', + timeRangeFilter: { + operator: 'between', + startTime: getBeginningOfLast7Days().toISOString(), + endTime: getTodayDate().toISOString(), + }, + timeRangeSlicer: { + period: 'DAYS', + duration: 1, + }, + }).then((result) => { + console.log('Aggregated Group: ', JSON.stringify({ result }, null, 2)); + }); + }; + const requestSamplePermissions = () => { requestPermission([ { @@ -174,6 +224,10 @@ export default function App() {