diff --git a/homeassistant/components/fitbit/sensor.py b/homeassistant/components/fitbit/sensor.py index c7c5e3258ed..51b1b64a391 100644 --- a/homeassistant/components/fitbit/sensor.py +++ b/homeassistant/components/fitbit/sensor.py @@ -33,6 +33,7 @@ from homeassistant.const import ( UnitOfLength, UnitOfMass, UnitOfTime, + UnitOfVolume, ) from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType @@ -122,6 +123,13 @@ def _elevation_unit(unit_system: FitbitUnitSystem) -> UnitOfLength: 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 class FitbitSensorEntityDescription(SensorEntityDescription): """Describes Fitbit sensor entity.""" @@ -453,6 +461,24 @@ FITBIT_RESOURCES_LIST: Final[tuple[FitbitSensorEntityDescription, ...]] = ( state_class=SensorStateClass.TOTAL_INCREASING, 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 diff --git a/tests/components/fitbit/snapshots/test_sensor.ambr b/tests/components/fitbit/snapshots/test_sensor.ambr index 4af82c6815a..55b2639a56d 100644 --- a/tests/components/fitbit/snapshots/test_sensor.ambr +++ b/tests/components/fitbit/snapshots/test_sensor.ambr @@ -1,4 +1,52 @@ # 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': , + 'unit_of_measurement': , + }), + ) +# --- +# 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': , + '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': , + 'unit_of_measurement': , + }), + ) +# --- +# 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': , + 'unit_of_measurement': 'cal', + }), + ) +# --- # name: test_sensors[monitored_resources0-sensor.activity_calories-activities/activityCalories-135] tuple( '135', diff --git a/tests/components/fitbit/test_sensor.py b/tests/components/fitbit/test_sensor.py index 2eb29db43de..7c980ac84a7 100644 --- a/tests/components/fitbit/test_sensor.py +++ b/tests/components/fitbit/test_sensor.py @@ -14,6 +14,11 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.helpers.entity_component import async_update_entity +from homeassistant.util.unit_system import ( + METRIC_SYSTEM, + US_CUSTOMARY_SYSTEM, + UnitSystem, +) from .conftest import ( 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( ("scopes"), [(["sleep"])],