From 494414eb87aa9f37255315d546af3c15e42034af Mon Sep 17 00:00:00 2001 From: Daniel Shokouhi Date: Sat, 12 Nov 2022 05:24:17 -0800 Subject: [PATCH] Add Daily Calories, Distance and Steps sensors for health services (#3054) * Add Daily Calories, Distance and Steps sensors for health services * Process data points before condition to push update --- common/src/main/res/values/strings.xml | 6 + .../sensors/HealthServicesSensorManager.kt | 109 ++++++++++++++---- 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 6462cd0dd..b368b8fb4 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -949,4 +949,10 @@ Current heart rate in beats per minute, an attribute also exists for the reported accuracy from the sensor Daily Floors The total number floors climbed over a day, where the previous day ends and a new day begins at 12:00 AM local time + Daily Distance + The total distance over a day, where the previous day ends and a new day begins at 12:00 AM local time. + Daily Calories + The total number of calories over a day (including both BMR and active calories), where the previous day ends and a new day begins at 12:00 AM local time. + Daily Steps + The total step count over a day, where the previous day ends and a new day begins at 12:00 AM local time. diff --git a/wear/src/main/java/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt b/wear/src/main/java/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt index b5dee2cb8..1be117d0b 100755 --- a/wear/src/main/java/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt @@ -50,6 +50,36 @@ class HealthServicesSensorManager : SensorManager { entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC, updateType = SensorManager.BasicSensor.UpdateType.INTENT ) + private val dailyDistance = SensorManager.BasicSensor( + "daily_distance", + "sensor", + commonR.string.sensor_name_daily_distance, + commonR.string.sensor_description_daily_distance, + "mdi:map-marker-distance", + unitOfMeasurement = "m", + entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC, + updateType = SensorManager.BasicSensor.UpdateType.INTENT + ) + private val dailyCalories = SensorManager.BasicSensor( + "daily_calories", + "sensor", + commonR.string.sensor_name_daily_calories, + commonR.string.sensor_description_daily_calories, + "mdi:fire", + unitOfMeasurement = "kcal", + entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC, + updateType = SensorManager.BasicSensor.UpdateType.INTENT + ) + private val dailySteps = SensorManager.BasicSensor( + "daily_steps", + "sensor", + commonR.string.sensor_name_daily_steps, + commonR.string.sensor_description_daily_steps, + "mdi:shoe-print", + unitOfMeasurement = "steps", + entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC, + updateType = SensorManager.BasicSensor.UpdateType.INTENT + ) } private lateinit var latestContext: Context @@ -85,6 +115,12 @@ class HealthServicesSensorManager : SensorManager { if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.FLOORS_DAILY) == true) supportedSensors += dailyFloors + if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.DISTANCE_DAILY) == true) + supportedSensors += dailyDistance + if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.CALORIES_DAILY) == true) + supportedSensors += dailyCalories + if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.STEPS_DAILY) == true) + supportedSensors += dailySteps return supportedSensors } @@ -104,8 +140,14 @@ class HealthServicesSensorManager : SensorManager { private fun updateHealthServices() { val activityStateEnabled = isEnabled(latestContext, userActivityState.id) val dailyFloorEnabled = isEnabled(latestContext, dailyFloors.id) + val dailyDistanceEnabled = isEnabled(latestContext, dailyDistance.id) + val dailyCaloriesEnabled = isEnabled(latestContext, dailyCalories.id) + val dailyStepsEnabled = isEnabled(latestContext, dailySteps.id) - if (!activityStateEnabled && !dailyFloorEnabled) { + if ( + !activityStateEnabled && !dailyFloorEnabled && !dailyDistanceEnabled && + !dailyCaloriesEnabled && !dailyStepsEnabled + ) { clearHealthServicesCallBack() return } @@ -116,6 +158,12 @@ class HealthServicesSensorManager : SensorManager { val dataTypes = mutableSetOf>() if (dailyFloorEnabled) dataTypes += DataType.FLOORS_DAILY + if (dailyDistanceEnabled) + dataTypes += DataType.DISTANCE_DAILY + if (dailyCaloriesEnabled) + dataTypes += DataType.CALORIES_DAILY + if (dailyStepsEnabled) + dataTypes += DataType.STEPS_DAILY passiveListenerConfig = PassiveListenerConfig.builder() .setShouldUserActivityInfoBeRequested(activityStateEnabled) @@ -155,10 +203,11 @@ class HealthServicesSensorManager : SensorManager { override fun onNewDataPointsReceived(dataPoints: DataPointContainer) { Log.d(TAG, "New data point received: ${dataPoints.dataTypes}") val floorsDaily = dataPoints.getData(DataType.FLOORS_DAILY) + val distanceDaily = dataPoints.getData(DataType.DISTANCE_DAILY) + val caloriesDaily = dataPoints.getData(DataType.CALORIES_DAILY) + val stepsDaily = dataPoints.getData(DataType.STEPS_DAILY) val bootInstant = Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime()) - var latest = 0 - var lastIndex = 0 dataPoints.dataTypes.forEachIndexed { _, dataType -> @@ -175,25 +224,14 @@ class HealthServicesSensorManager : SensorManager { } } } - if (floorsDaily.isNotEmpty()) { - floorsDaily.forEachIndexed { index, intervalDataPoint -> - val endTime = intervalDataPoint.getEndInstant(bootInstant) - Log.d(TAG, "Daily Floors data index: $index with value: ${intervalDataPoint.value} end time: ${endTime.toEpochMilli()}") - if (endTime.toEpochMilli() > latest) { - latest = endTime.toEpochMilli().toInt() - lastIndex = index - } - } - onSensorUpdated( - latestContext, - dailyFloors, - floorsDaily[lastIndex].value, - dailyFloors.statelessIcon, - mapOf() - ) + val hasFloorData = processDataPoint(floorsDaily, dailyFloors) + val hasDistanceData = processDataPoint(distanceDaily, dailyDistance) + val hasCalorieData = processDataPoint(caloriesDaily, dailyCalories) + val hasStepData = processDataPoint(stepsDaily, dailySteps) + + if (hasFloorData || hasDistanceData || hasCalorieData || hasStepData) SensorWorker.start(latestContext) - } } override fun onPermissionLost() { @@ -277,4 +315,35 @@ class HealthServicesSensorManager : SensorManager { else -> userActivityState.statelessIcon } } + + private fun processDataPoint( + dataPoints: List>, + basicSensor: SensorManager.BasicSensor + ): Boolean { + var sendUpdate = false + var latest = 0 + var lastIndex = 0 + val bootInstant = + Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime()) + + if (dataPoints.isNotEmpty()) { + dataPoints.forEachIndexed { index, intervalDataPoint -> + val endTime = intervalDataPoint.getEndInstant(bootInstant) + Log.d(TAG, "${basicSensor.id} data index: $index with value: ${intervalDataPoint.value} end time: ${endTime.toEpochMilli()}") + if (endTime.toEpochMilli() > latest) { + latest = endTime.toEpochMilli().toInt() + lastIndex = index + sendUpdate = true + } + } + onSensorUpdated( + latestContext, + basicSensor, + dataPoints[lastIndex].value, + basicSensor.statelessIcon, + mapOf() + ) + } + return sendUpdate + } }