mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Add fitbit nutrition sensors (#101626)
* Add fitbit nutrition sensors * Add test coverage for unit systems
This commit is contained in:
parent
d3a67cd984
commit
7d202f78f5
@ -33,6 +33,7 @@ from homeassistant.const import (
|
|||||||
UnitOfLength,
|
UnitOfLength,
|
||||||
UnitOfMass,
|
UnitOfMass,
|
||||||
UnitOfTime,
|
UnitOfTime,
|
||||||
|
UnitOfVolume,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
@ -122,6 +123,13 @@ def _elevation_unit(unit_system: FitbitUnitSystem) -> UnitOfLength:
|
|||||||
return UnitOfLength.METERS
|
return UnitOfLength.METERS
|
||||||
|
|
||||||
|
|
||||||
|
def _water_unit(unit_system: FitbitUnitSystem) -> UnitOfVolume:
|
||||||
|
"""Determine the water unit."""
|
||||||
|
if unit_system == FitbitUnitSystem.EN_US:
|
||||||
|
return UnitOfVolume.FLUID_OUNCES
|
||||||
|
return UnitOfVolume.MILLILITERS
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FitbitSensorEntityDescription(SensorEntityDescription):
|
class FitbitSensorEntityDescription(SensorEntityDescription):
|
||||||
"""Describes Fitbit sensor entity."""
|
"""Describes Fitbit sensor entity."""
|
||||||
@ -453,6 +461,24 @@ FITBIT_RESOURCES_LIST: Final[tuple[FitbitSensorEntityDescription, ...]] = (
|
|||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
|
FitbitSensorEntityDescription(
|
||||||
|
key="foods/log/caloriesIn",
|
||||||
|
name="Calories In",
|
||||||
|
native_unit_of_measurement="cal",
|
||||||
|
icon="mdi:food-apple",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
scope="nutrition",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
FitbitSensorEntityDescription(
|
||||||
|
key="foods/log/water",
|
||||||
|
name="Water",
|
||||||
|
icon="mdi:cup-water",
|
||||||
|
unit_fn=_water_unit,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
scope="nutrition",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Different description depending on clock format
|
# Different description depending on clock format
|
||||||
|
@ -1,4 +1,52 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
|
# name: test_nutrition_scope_config_entry[scopes0-unit_system0]
|
||||||
|
tuple(
|
||||||
|
'99',
|
||||||
|
ReadOnlyDict({
|
||||||
|
'attribution': 'Data provided by Fitbit.com',
|
||||||
|
'friendly_name': 'Water',
|
||||||
|
'icon': 'mdi:cup-water',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfVolume.MILLILITERS: 'mL'>,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
# ---
|
||||||
|
# name: test_nutrition_scope_config_entry[scopes0-unit_system0].1
|
||||||
|
tuple(
|
||||||
|
'1600',
|
||||||
|
ReadOnlyDict({
|
||||||
|
'attribution': 'Data provided by Fitbit.com',
|
||||||
|
'friendly_name': 'Calories In',
|
||||||
|
'icon': 'mdi:food-apple',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': 'cal',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
# ---
|
||||||
|
# name: test_nutrition_scope_config_entry[scopes1-unit_system1]
|
||||||
|
tuple(
|
||||||
|
'99',
|
||||||
|
ReadOnlyDict({
|
||||||
|
'attribution': 'Data provided by Fitbit.com',
|
||||||
|
'friendly_name': 'Water',
|
||||||
|
'icon': 'mdi:cup-water',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfVolume.FLUID_OUNCES: 'fl. oz.'>,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
# ---
|
||||||
|
# name: test_nutrition_scope_config_entry[scopes1-unit_system1].1
|
||||||
|
tuple(
|
||||||
|
'1600',
|
||||||
|
ReadOnlyDict({
|
||||||
|
'attribution': 'Data provided by Fitbit.com',
|
||||||
|
'friendly_name': 'Calories In',
|
||||||
|
'icon': 'mdi:food-apple',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': 'cal',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
# ---
|
||||||
# name: test_sensors[monitored_resources0-sensor.activity_calories-activities/activityCalories-135]
|
# name: test_sensors[monitored_resources0-sensor.activity_calories-activities/activityCalories-135]
|
||||||
tuple(
|
tuple(
|
||||||
'135',
|
'135',
|
||||||
|
@ -14,6 +14,11 @@ from homeassistant.const import Platform
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.entity_component import async_update_entity
|
from homeassistant.helpers.entity_component import async_update_entity
|
||||||
|
from homeassistant.util.unit_system import (
|
||||||
|
METRIC_SYSTEM,
|
||||||
|
US_CUSTOMARY_SYSTEM,
|
||||||
|
UnitSystem,
|
||||||
|
)
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
DEVICES_API_URL,
|
DEVICES_API_URL,
|
||||||
@ -426,6 +431,39 @@ async def test_heartrate_scope_config_entry(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("scopes", "unit_system"),
|
||||||
|
[(["nutrition"], METRIC_SYSTEM), (["nutrition"], US_CUSTOMARY_SYSTEM)],
|
||||||
|
)
|
||||||
|
async def test_nutrition_scope_config_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_credentials: None,
|
||||||
|
integration_setup: Callable[[], Awaitable[bool]],
|
||||||
|
register_timeseries: Callable[[str, dict[str, Any]], None],
|
||||||
|
unit_system: UnitSystem,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test nutrition sensors are enabled."""
|
||||||
|
hass.config.units = unit_system
|
||||||
|
register_timeseries(
|
||||||
|
"foods/log/water",
|
||||||
|
timeseries_response("foods-log-water", "99"),
|
||||||
|
)
|
||||||
|
register_timeseries(
|
||||||
|
"foods/log/caloriesIn",
|
||||||
|
timeseries_response("foods-log-caloriesIn", "1600"),
|
||||||
|
)
|
||||||
|
assert await integration_setup()
|
||||||
|
|
||||||
|
state = hass.states.get("sensor.water")
|
||||||
|
assert state
|
||||||
|
assert (state.state, state.attributes) == snapshot
|
||||||
|
|
||||||
|
state = hass.states.get("sensor.calories_in")
|
||||||
|
assert state
|
||||||
|
assert (state.state, state.attributes) == snapshot
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("scopes"),
|
("scopes"),
|
||||||
[(["sleep"])],
|
[(["sleep"])],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user