使用 HealthConnect API 进行卡路里数据聚合的差异

问题描述 投票:0回答:1

我正在使用 HealthConnect API 根据各个记录中的手动求和值来验证聚合卡路里数据。我在 Kotlin 中实现了一个函数,用于获取过去 30 天内每一天的每日记录和汇总金额。然而,我一直发现这两个总数之间存在差异。

这是我如何获取和聚合数据的示例:

suspend fun validateCaloriesData(healthConnectClient: HealthConnectClient) {
    // Time zone and date setup
    val zoneId = ZoneId.systemDefault()
    val endTime = Instant.now().atZone(zoneId).truncatedTo(ChronoUnit.DAYS)
    val startTime = endTime.minusDays(30)

    var currentDay = startTime
    while (currentDay.isBefore(endTime)) {
        val startOfDay = currentDay.toInstant()
        val endOfDay = currentDay.plusDays(1).toInstant()

        val dailyRecords = mutableListOf<Double>()

        try {
            val records = healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = TotalCaloriesBurnedRecord::class,
                    timeRangeFilter = TimeRangeFilter.between(startOfDay, endOfDay),
                    pageSize = 2000,
                    pageToken = null,
                    ascendingOrder = true
                )
            )
            records.records.forEach {
                dailyRecords.add(it.energy.inKilocalories ?: 0.0)
            }

            val sumOfDailyRecords = dailyRecords.sum()
            val response = healthConnectClient.aggregate(
                AggregateRequest(
                    metrics = setOf(TotalCaloriesBurnedRecord.ENERGY_TOTAL),
                    timeRangeFilter = TimeRangeFilter.between(startOfDay, endOfDay)
                )
            )
            val aggregatedCalories = response[TotalCaloriesBurnedRecord.ENERGY_TOTAL]?.inKilocalories ?: 0.0

            if (sumOfDailyRecords != aggregatedCalories) {
                Log.e("DailyCaloriesValidation", "Discrepancy found on day $currentDay: Manual sum is $sumOfDailyRecords but aggregated is $aggregatedCalories")
            }

        } catch (e: Exception) {
            Log.e("DailyCaloriesValidation", "Error reading or aggregating calories for day $currentDay: ${e.message}")
        }

        currentDay = currentDay.plusDays(1)
    }
}

和日志:

E/DailyCaloriesValidation( 8147): Discrepancy found on day 2024-04-13T00:00+02:00[Europe/Paris]: Manual sum is 100.0 but aggregated is 1707.009
E/DailyCaloriesValidation( 8147): Discrepancy found on day 2024-04-10T00:00+02:00[Europe/Paris]: Manual sum is 188.0 but aggregated is 1780.543
android database kotlin healthconnect
1个回答
0
投票

尝试下面的代码

fun validateCaloriesData(healthConnectClient: HealthConnectClient) {
    // Time zone and date setup
    val zoneId = ZoneId.systemDefault()
    val endTime = Instant.now().atZone(zoneId).truncatedTo(ChronoUnit.DAYS)
    val startTime = endTime.minusDays(30)

    var currentDay = startTime
    while (currentDay.isBefore(endTime)) {
        val startOfDay = currentDay.toInstant()
        val endOfDay = currentDay.plusDays(1).toInstant()

        try {
            val dailyRecords = mutableListOf<Double>()
            
            // Fetch records for the current day
            val records = healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = TotalCaloriesBurnedRecord::class,
                    timeRangeFilter = TimeRangeFilter.between(startOfDay, endOfDay),
                    pageSize = 2000,
                    pageToken = null,
                    ascendingOrder = true
                )
            )
            
            // Iterate through the records and calculate the sum
            records.records.forEach {
                dailyRecords.add(it.energy.inKilocalories ?: 0.0)
            }

            val sumOfDailyRecords = dailyRecords.sum()

            // Aggregate the records for the current day
            val response = healthConnectClient.aggregate(
                AggregateRequest(
                    metrics = setOf(TotalCaloriesBurnedRecord.ENERGY_TOTAL),
                    timeRangeFilter = TimeRangeFilter.between(startOfDay, endOfDay)
                )
            )
            
            // Retrieve the aggregated sum for the current day
            val aggregatedCalories = response[TotalCaloriesBurnedRecord.ENERGY_TOTAL]?.inKilocalories ?: 0.0

            // Compare the manual sum with the aggregated sum
            if (Math.abs(sumOfDailyRecords - aggregatedCalories) > 0.001) {
                // Log a warning if there's a significant discrepancy
                Log.w("DailyCaloriesValidation", "Discrepancy found on day $currentDay: Manual sum is $sumOfDailyRecords but aggregated is $aggregatedCalories")
            }

        } catch (e: Exception) {
            // Log any errors that occur during data retrieval or aggregation
            Log.e("DailyCaloriesValidation", "Error processing data for day $currentDay: ${e.message}")
        }

        // Move to the next day
        currentDay = currentDay.plusDays(1)
    }
}

删除了不必要的变量 currentDay 并将初始化移至循环控制,删除了 try 块内 dailyRecords 列表的创建以确保其始终初始化。使用 Math.abs 以小容差(0.001)比较和来处理浮点精度问题

如果您仍然遇到问题,您可以在我的答案下面发表评论,我很乐意为您提供帮助。

© www.soinside.com 2019 - 2024. All rights reserved.