Reduce unnecessary fitbit RPCs on startup (#102504)

* Reduce unnecessary fitbit RPCs on startup

* Update comment about racing user profile rpcs
This commit is contained in:
Allen Porter 2023-10-21 22:00:40 -07:00 committed by GitHub
parent 1801a7738c
commit c4f562ff6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 14 deletions

View file

@ -1,7 +1,6 @@
"""Support for the Fitbit API."""
from __future__ import annotations
import asyncio
from collections.abc import Callable
from dataclasses import dataclass
import datetime
@ -620,10 +619,10 @@ async def async_setup_entry(
data: FitbitData = hass.data[DOMAIN][entry.entry_id]
api = data.api
# Note: This will only be one rpc since it will cache the user profile
(user_profile, unit_system) = await asyncio.gather(
api.async_get_user_profile(), api.async_get_unit_system()
)
# These are run serially to reuse the cached user profile, not gathered
# to avoid two racing requests.
user_profile = await api.async_get_user_profile()
unit_system = await api.async_get_unit_system()
fitbit_config = config_from_entry_data(entry.data)
@ -654,7 +653,7 @@ async def async_setup_entry(
for description in resource_list
if is_allowed_resource(description)
]
async_add_entities(entities, True)
async_add_entities(entities)
if data.device_coordinator and is_allowed_resource(FITBIT_RESOURCE_BATTERY):
async_add_entities(
@ -712,6 +711,14 @@ class FitbitSensor(SensorEntity):
self._attr_available = True
self._attr_native_value = self.entity_description.value_fn(result)
async def async_added_to_hass(self) -> None:
"""When entity is added to hass."""
await super().async_added_to_hass()
# We do not ask for an update with async_add_entities()
# because it will update disabled entities.
self.async_schedule_update_ha_state(force_refresh=True)
class FitbitBatterySensor(CoordinatorEntity, SensorEntity):
"""Implementation of a Fitbit sensor."""

View file

@ -538,15 +538,8 @@ async def test_settings_scope_config_entry(
integration_setup: Callable[[], Awaitable[bool]],
register_timeseries: Callable[[str, dict[str, Any]], None],
) -> None:
"""Test heartrate sensors are enabled."""
"""Test device sensors are enabled."""
for api_resource in ("activities/heart",):
register_timeseries(
api_resource,
timeseries_response(
api_resource.replace("/", "-"), {"restingHeartRate": "0"}
),
)
assert await integration_setup()
states = hass.states.async_all()
@ -617,6 +610,51 @@ async def test_sensor_update_failed_requires_reauth(
assert flows[0]["step_id"] == "reauth_confirm"
@pytest.mark.parametrize(
("scopes"),
[(["heartrate"])],
)
async def test_sensor_update_success(
hass: HomeAssistant,
setup_credentials: None,
integration_setup: Callable[[], Awaitable[bool]],
requests_mock: Mocker,
) -> None:
"""Test API failure for a battery level sensor for devices."""
requests_mock.register_uri(
"GET",
TIMESERIES_API_URL_FORMAT.format(resource="activities/heart"),
[
{
"status_code": HTTPStatus.OK,
"json": timeseries_response(
"activities-heart", {"restingHeartRate": "60"}
),
},
{
"status_code": HTTPStatus.OK,
"json": timeseries_response(
"activities-heart", {"restingHeartRate": "70"}
),
},
],
)
assert await integration_setup()
state = hass.states.get("sensor.resting_heart_rate")
assert state
assert state.state == "60"
await async_update_entity(hass, "sensor.resting_heart_rate")
await hass.async_block_till_done()
state = hass.states.get("sensor.resting_heart_rate")
assert state
assert state.state == "70"
@pytest.mark.parametrize(
("scopes", "mock_devices"),
[(["settings"], None)],