mirror of
https://github.com/home-assistant/android
synced 2024-10-07 00:29:32 +00:00
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
This commit is contained in:
parent
33d1e30cb1
commit
494414eb87
|
@ -949,4 +949,10 @@
|
||||||
<string name="sensor_description_heart_rate">Current heart rate in beats per minute, an attribute also exists for the reported accuracy from the sensor</string>
|
<string name="sensor_description_heart_rate">Current heart rate in beats per minute, an attribute also exists for the reported accuracy from the sensor</string>
|
||||||
<string name="sensor_name_daily_floors">Daily Floors</string>
|
<string name="sensor_name_daily_floors">Daily Floors</string>
|
||||||
<string name="sensor_description_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</string>
|
<string name="sensor_description_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</string>
|
||||||
|
<string name="sensor_name_daily_distance">Daily Distance</string>
|
||||||
|
<string name="sensor_description_daily_distance">The total distance over a day, where the previous day ends and a new day begins at 12:00 AM local time.</string>
|
||||||
|
<string name="sensor_name_daily_calories">Daily Calories</string>
|
||||||
|
<string name="sensor_description_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.</string>
|
||||||
|
<string name="sensor_name_daily_steps">Daily Steps</string>
|
||||||
|
<string name="sensor_description_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.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -50,6 +50,36 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
|
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
updateType = SensorManager.BasicSensor.UpdateType.INTENT
|
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
|
private lateinit var latestContext: Context
|
||||||
|
@ -85,6 +115,12 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
|
|
||||||
if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.FLOORS_DAILY) == true)
|
if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.FLOORS_DAILY) == true)
|
||||||
supportedSensors += dailyFloors
|
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
|
return supportedSensors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +140,14 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
private fun updateHealthServices() {
|
private fun updateHealthServices() {
|
||||||
val activityStateEnabled = isEnabled(latestContext, userActivityState.id)
|
val activityStateEnabled = isEnabled(latestContext, userActivityState.id)
|
||||||
val dailyFloorEnabled = isEnabled(latestContext, dailyFloors.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()
|
clearHealthServicesCallBack()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -116,6 +158,12 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
val dataTypes = mutableSetOf<DataType<*, *>>()
|
val dataTypes = mutableSetOf<DataType<*, *>>()
|
||||||
if (dailyFloorEnabled)
|
if (dailyFloorEnabled)
|
||||||
dataTypes += DataType.FLOORS_DAILY
|
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()
|
passiveListenerConfig = PassiveListenerConfig.builder()
|
||||||
.setShouldUserActivityInfoBeRequested(activityStateEnabled)
|
.setShouldUserActivityInfoBeRequested(activityStateEnabled)
|
||||||
|
@ -155,10 +203,11 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
|
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
|
||||||
Log.d(TAG, "New data point received: ${dataPoints.dataTypes}")
|
Log.d(TAG, "New data point received: ${dataPoints.dataTypes}")
|
||||||
val floorsDaily = dataPoints.getData(DataType.FLOORS_DAILY)
|
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 =
|
val bootInstant =
|
||||||
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
|
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
|
||||||
var latest = 0
|
|
||||||
var lastIndex = 0
|
|
||||||
|
|
||||||
dataPoints.dataTypes.forEachIndexed { _, dataType ->
|
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)
|
SensorWorker.start(latestContext)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPermissionLost() {
|
override fun onPermissionLost() {
|
||||||
|
@ -277,4 +315,35 @@ class HealthServicesSensorManager : SensorManager {
|
||||||
else -> userActivityState.statelessIcon
|
else -> userActivityState.statelessIcon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processDataPoint(
|
||||||
|
dataPoints: List<IntervalDataPoint<*>>,
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue