mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +00:00
Split Withings coordinators (#101766)
* Subscribe to Withings webhooks outside of coordinator * Subscribe to Withings webhooks outside of coordinator * Split Withings coordinator * Split Withings coordinator * Update homeassistant/components/withings/sensor.py * Fix merge * Rename MEASUREMENT_COORDINATOR * Update homeassistant/components/withings/__init__.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Fix feedback --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
03210d7f81
commit
d712a29052
@ -43,8 +43,22 @@ from homeassistant.helpers.issue_registry import IssueSeverity, async_create_iss
|
|||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .api import ConfigEntryWithingsApi
|
from .api import ConfigEntryWithingsApi
|
||||||
from .const import CONF_PROFILES, CONF_USE_WEBHOOK, DEFAULT_TITLE, DOMAIN, LOGGER
|
from .const import (
|
||||||
from .coordinator import WithingsDataUpdateCoordinator
|
BED_PRESENCE_COORDINATOR,
|
||||||
|
CONF_PROFILES,
|
||||||
|
CONF_USE_WEBHOOK,
|
||||||
|
DEFAULT_TITLE,
|
||||||
|
DOMAIN,
|
||||||
|
LOGGER,
|
||||||
|
MEASUREMENT_COORDINATOR,
|
||||||
|
SLEEP_COORDINATOR,
|
||||||
|
)
|
||||||
|
from .coordinator import (
|
||||||
|
WithingsBedPresenceDataUpdateCoordinator,
|
||||||
|
WithingsDataUpdateCoordinator,
|
||||||
|
WithingsMeasurementDataUpdateCoordinator,
|
||||||
|
WithingsSleepDataUpdateCoordinator,
|
||||||
|
)
|
||||||
|
|
||||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
||||||
|
|
||||||
@ -128,11 +142,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
hass, entry
|
hass, entry
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
coordinator = WithingsDataUpdateCoordinator(hass, client)
|
coordinators: dict[str, WithingsDataUpdateCoordinator] = {
|
||||||
|
MEASUREMENT_COORDINATOR: WithingsMeasurementDataUpdateCoordinator(hass, client),
|
||||||
|
SLEEP_COORDINATOR: WithingsSleepDataUpdateCoordinator(hass, client),
|
||||||
|
BED_PRESENCE_COORDINATOR: WithingsBedPresenceDataUpdateCoordinator(
|
||||||
|
hass, client
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
for coordinator in coordinators.values():
|
||||||
|
await coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinators
|
||||||
|
|
||||||
async def unregister_webhook(
|
async def unregister_webhook(
|
||||||
_: Any,
|
_: Any,
|
||||||
@ -140,7 +161,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
LOGGER.debug("Unregister Withings webhook (%s)", entry.data[CONF_WEBHOOK_ID])
|
LOGGER.debug("Unregister Withings webhook (%s)", entry.data[CONF_WEBHOOK_ID])
|
||||||
webhook_unregister(hass, entry.data[CONF_WEBHOOK_ID])
|
webhook_unregister(hass, entry.data[CONF_WEBHOOK_ID])
|
||||||
await async_unsubscribe_webhooks(client)
|
await async_unsubscribe_webhooks(client)
|
||||||
coordinator.webhook_subscription_listener(False)
|
for coordinator in coordinators.values():
|
||||||
|
coordinator.webhook_subscription_listener(False)
|
||||||
|
|
||||||
async def register_webhook(
|
async def register_webhook(
|
||||||
_: Any,
|
_: Any,
|
||||||
@ -166,11 +188,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
DOMAIN,
|
DOMAIN,
|
||||||
webhook_name,
|
webhook_name,
|
||||||
entry.data[CONF_WEBHOOK_ID],
|
entry.data[CONF_WEBHOOK_ID],
|
||||||
get_webhook_handler(coordinator),
|
get_webhook_handler(coordinators),
|
||||||
)
|
)
|
||||||
|
|
||||||
await async_subscribe_webhooks(client, webhook_url)
|
await async_subscribe_webhooks(client, webhook_url)
|
||||||
coordinator.webhook_subscription_listener(True)
|
for coordinator in coordinators.values():
|
||||||
|
coordinator.webhook_subscription_listener(True)
|
||||||
LOGGER.debug("Register Withings webhook: %s", webhook_url)
|
LOGGER.debug("Register Withings webhook: %s", webhook_url)
|
||||||
entry.async_on_unload(
|
entry.async_on_unload(
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, unregister_webhook)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, unregister_webhook)
|
||||||
@ -287,7 +310,7 @@ def json_message_response(message: str, message_code: int) -> Response:
|
|||||||
|
|
||||||
|
|
||||||
def get_webhook_handler(
|
def get_webhook_handler(
|
||||||
coordinator: WithingsDataUpdateCoordinator,
|
coordinators: dict[str, WithingsDataUpdateCoordinator],
|
||||||
) -> Callable[[HomeAssistant, str, Request], Awaitable[Response | None]]:
|
) -> Callable[[HomeAssistant, str, Request], Awaitable[Response | None]]:
|
||||||
"""Return webhook handler."""
|
"""Return webhook handler."""
|
||||||
|
|
||||||
@ -318,7 +341,9 @@ def get_webhook_handler(
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return json_message_response("Invalid appli provided", message_code=21)
|
return json_message_response("Invalid appli provided", message_code=21)
|
||||||
|
|
||||||
await coordinator.async_webhook_data_updated(appli)
|
for coordinator in coordinators.values():
|
||||||
|
if appli in coordinator.notification_categories:
|
||||||
|
await coordinator.async_webhook_data_updated(appli)
|
||||||
|
|
||||||
return json_message_response("Success", message_code=0)
|
return json_message_response("Success", message_code=0)
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import BED_PRESENCE_COORDINATOR, DOMAIN
|
||||||
from .coordinator import WithingsDataUpdateCoordinator
|
from .coordinator import WithingsBedPresenceDataUpdateCoordinator
|
||||||
from .entity import WithingsEntity
|
from .entity import WithingsEntity
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +20,9 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the sensor config entry."""
|
"""Set up the sensor config entry."""
|
||||||
coordinator: WithingsDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
coordinator: WithingsBedPresenceDataUpdateCoordinator = hass.data[DOMAIN][
|
||||||
|
entry.entry_id
|
||||||
|
][BED_PRESENCE_COORDINATOR]
|
||||||
|
|
||||||
entities = [WithingsBinarySensor(coordinator)]
|
entities = [WithingsBinarySensor(coordinator)]
|
||||||
|
|
||||||
@ -33,8 +35,9 @@ class WithingsBinarySensor(WithingsEntity, BinarySensorEntity):
|
|||||||
_attr_icon = "mdi:bed"
|
_attr_icon = "mdi:bed"
|
||||||
_attr_translation_key = "in_bed"
|
_attr_translation_key = "in_bed"
|
||||||
_attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
_attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
||||||
|
coordinator: WithingsBedPresenceDataUpdateCoordinator
|
||||||
|
|
||||||
def __init__(self, coordinator: WithingsDataUpdateCoordinator) -> None:
|
def __init__(self, coordinator: WithingsBedPresenceDataUpdateCoordinator) -> None:
|
||||||
"""Initialize binary sensor."""
|
"""Initialize binary sensor."""
|
||||||
super().__init__(coordinator, "in_bed")
|
super().__init__(coordinator, "in_bed")
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ LOG_NAMESPACE = "homeassistant.components.withings"
|
|||||||
PROFILE = "profile"
|
PROFILE = "profile"
|
||||||
PUSH_HANDLER = "push_handler"
|
PUSH_HANDLER = "push_handler"
|
||||||
|
|
||||||
|
MEASUREMENT_COORDINATOR = "measurement_coordinator"
|
||||||
|
SLEEP_COORDINATOR = "sleep_coordinator"
|
||||||
|
BED_PRESENCE_COORDINATOR = "bed_presence_coordinator"
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__package__)
|
LOGGER = logging.getLogger(__package__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""Withings coordinator."""
|
"""Withings coordinator."""
|
||||||
|
from abc import abstractmethod
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Any
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
from withings_api.common import (
|
from withings_api.common import (
|
||||||
AuthFailedException,
|
AuthFailedException,
|
||||||
@ -66,40 +67,66 @@ WITHINGS_MEASURE_TYPE_MAP: dict[
|
|||||||
NotifyAppli.BED_IN: Measurement.IN_BED,
|
NotifyAppli.BED_IN: Measurement.IN_BED,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
UPDATE_INTERVAL = timedelta(minutes=10)
|
UPDATE_INTERVAL = timedelta(minutes=10)
|
||||||
|
|
||||||
|
|
||||||
class WithingsDataUpdateCoordinator(DataUpdateCoordinator[dict[Measurement, Any]]):
|
class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]):
|
||||||
"""Base coordinator."""
|
"""Base coordinator."""
|
||||||
|
|
||||||
in_bed: bool | None = None
|
|
||||||
config_entry: ConfigEntry
|
config_entry: ConfigEntry
|
||||||
|
_default_update_interval: timedelta | None = UPDATE_INTERVAL
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, client: ConfigEntryWithingsApi) -> None:
|
def __init__(self, hass: HomeAssistant, client: ConfigEntryWithingsApi) -> None:
|
||||||
"""Initialize the Withings data coordinator."""
|
"""Initialize the Withings data coordinator."""
|
||||||
super().__init__(hass, LOGGER, name="Withings", update_interval=UPDATE_INTERVAL)
|
super().__init__(
|
||||||
|
hass, LOGGER, name="Withings", update_interval=self._default_update_interval
|
||||||
|
)
|
||||||
self._client = client
|
self._client = client
|
||||||
|
self.notification_categories: set[NotifyAppli] = set()
|
||||||
|
|
||||||
def webhook_subscription_listener(self, connected: bool) -> None:
|
def webhook_subscription_listener(self, connected: bool) -> None:
|
||||||
"""Call when webhook status changed."""
|
"""Call when webhook status changed."""
|
||||||
if connected:
|
if connected:
|
||||||
self.update_interval = None
|
self.update_interval = None
|
||||||
else:
|
else:
|
||||||
self.update_interval = UPDATE_INTERVAL
|
self.update_interval = self._default_update_interval
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[Measurement, Any]:
|
async def async_webhook_data_updated(
|
||||||
|
self, notification_category: NotifyAppli
|
||||||
|
) -> None:
|
||||||
|
"""Update data when webhook is called."""
|
||||||
|
LOGGER.debug("Withings webhook triggered for %s", notification_category)
|
||||||
|
await self.async_request_refresh()
|
||||||
|
|
||||||
|
async def _async_update_data(self) -> _T:
|
||||||
try:
|
try:
|
||||||
measurements = await self._get_measurements()
|
return await self._internal_update_data()
|
||||||
sleep_summary = await self._get_sleep_summary()
|
|
||||||
except (UnauthorizedException, AuthFailedException) as exc:
|
except (UnauthorizedException, AuthFailedException) as exc:
|
||||||
raise ConfigEntryAuthFailed from exc
|
raise ConfigEntryAuthFailed from exc
|
||||||
return {
|
|
||||||
**measurements,
|
@abstractmethod
|
||||||
**sleep_summary,
|
async def _internal_update_data(self) -> _T:
|
||||||
|
"""Update coordinator data."""
|
||||||
|
|
||||||
|
|
||||||
|
class WithingsMeasurementDataUpdateCoordinator(
|
||||||
|
WithingsDataUpdateCoordinator[dict[Measurement, Any]]
|
||||||
|
):
|
||||||
|
"""Withings measurement coordinator."""
|
||||||
|
|
||||||
|
def __init__(self, hass: HomeAssistant, client: ConfigEntryWithingsApi) -> None:
|
||||||
|
"""Initialize the Withings data coordinator."""
|
||||||
|
super().__init__(hass, client)
|
||||||
|
self.notification_categories = {
|
||||||
|
NotifyAppli.WEIGHT,
|
||||||
|
NotifyAppli.ACTIVITY,
|
||||||
|
NotifyAppli.CIRCULATORY,
|
||||||
}
|
}
|
||||||
|
|
||||||
async def _get_measurements(self) -> dict[Measurement, Any]:
|
async def _internal_update_data(self) -> dict[Measurement, Any]:
|
||||||
LOGGER.debug("Updating withings measures")
|
"""Retrieve measurement data."""
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
startdate = now - timedelta(days=7)
|
startdate = now - timedelta(days=7)
|
||||||
|
|
||||||
@ -125,7 +152,21 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[dict[Measurement, Any]
|
|||||||
if measure.type in WITHINGS_MEASURE_TYPE_MAP
|
if measure.type in WITHINGS_MEASURE_TYPE_MAP
|
||||||
}
|
}
|
||||||
|
|
||||||
async def _get_sleep_summary(self) -> dict[Measurement, Any]:
|
|
||||||
|
class WithingsSleepDataUpdateCoordinator(
|
||||||
|
WithingsDataUpdateCoordinator[dict[Measurement, Any]]
|
||||||
|
):
|
||||||
|
"""Withings sleep coordinator."""
|
||||||
|
|
||||||
|
def __init__(self, hass: HomeAssistant, client: ConfigEntryWithingsApi) -> None:
|
||||||
|
"""Initialize the Withings data coordinator."""
|
||||||
|
super().__init__(hass, client)
|
||||||
|
self.notification_categories = {
|
||||||
|
NotifyAppli.SLEEP,
|
||||||
|
}
|
||||||
|
|
||||||
|
async def _internal_update_data(self) -> dict[Measurement, Any]:
|
||||||
|
"""Retrieve sleep data."""
|
||||||
now = dt_util.now()
|
now = dt_util.now()
|
||||||
yesterday = now - timedelta(days=1)
|
yesterday = now - timedelta(days=1)
|
||||||
yesterday_noon = dt_util.start_of_local_day(yesterday) + timedelta(hours=12)
|
yesterday_noon = dt_util.start_of_local_day(yesterday) + timedelta(hours=12)
|
||||||
@ -202,18 +243,27 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[dict[Measurement, Any]
|
|||||||
for field, value in values.items()
|
for field, value in values.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WithingsBedPresenceDataUpdateCoordinator(WithingsDataUpdateCoordinator[None]):
|
||||||
|
"""Withings bed presence coordinator."""
|
||||||
|
|
||||||
|
in_bed: bool | None = None
|
||||||
|
_default_update_interval = None
|
||||||
|
|
||||||
|
def __init__(self, hass: HomeAssistant, client: ConfigEntryWithingsApi) -> None:
|
||||||
|
"""Initialize the Withings data coordinator."""
|
||||||
|
super().__init__(hass, client)
|
||||||
|
self.notification_categories = {
|
||||||
|
NotifyAppli.BED_IN,
|
||||||
|
NotifyAppli.BED_OUT,
|
||||||
|
}
|
||||||
|
|
||||||
async def async_webhook_data_updated(
|
async def async_webhook_data_updated(
|
||||||
self, notification_category: NotifyAppli
|
self, notification_category: NotifyAppli
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update data when webhook is called."""
|
"""Only set new in bed value instead of refresh."""
|
||||||
LOGGER.debug("Withings webhook triggered")
|
self.in_bed = notification_category == NotifyAppli.BED_IN
|
||||||
if notification_category in {
|
self.async_update_listeners()
|
||||||
NotifyAppli.WEIGHT,
|
|
||||||
NotifyAppli.CIRCULATORY,
|
|
||||||
NotifyAppli.SLEEP,
|
|
||||||
}:
|
|
||||||
await self.async_request_refresh()
|
|
||||||
|
|
||||||
elif notification_category in {NotifyAppli.BED_IN, NotifyAppli.BED_OUT}:
|
async def _internal_update_data(self) -> None:
|
||||||
self.in_bed = notification_category == NotifyAppli.BED_IN
|
"""Update coordinator data."""
|
||||||
self.async_update_listeners()
|
|
||||||
|
@ -25,14 +25,20 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
MEASUREMENT_COORDINATOR,
|
||||||
SCORE_POINTS,
|
SCORE_POINTS,
|
||||||
|
SLEEP_COORDINATOR,
|
||||||
UOM_BEATS_PER_MINUTE,
|
UOM_BEATS_PER_MINUTE,
|
||||||
UOM_BREATHS_PER_MINUTE,
|
UOM_BREATHS_PER_MINUTE,
|
||||||
UOM_FREQUENCY,
|
UOM_FREQUENCY,
|
||||||
UOM_MMHG,
|
UOM_MMHG,
|
||||||
Measurement,
|
Measurement,
|
||||||
)
|
)
|
||||||
from .coordinator import WithingsDataUpdateCoordinator
|
from .coordinator import (
|
||||||
|
WithingsDataUpdateCoordinator,
|
||||||
|
WithingsMeasurementDataUpdateCoordinator,
|
||||||
|
WithingsSleepDataUpdateCoordinator,
|
||||||
|
)
|
||||||
from .entity import WithingsEntity
|
from .entity import WithingsEntity
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +57,7 @@ class WithingsSensorEntityDescription(
|
|||||||
"""Immutable class for describing withings data."""
|
"""Immutable class for describing withings data."""
|
||||||
|
|
||||||
|
|
||||||
SENSORS = [
|
MEASUREMENT_SENSORS = [
|
||||||
WithingsSensorEntityDescription(
|
WithingsSensorEntityDescription(
|
||||||
key=Measurement.WEIGHT_KG.value,
|
key=Measurement.WEIGHT_KG.value,
|
||||||
measurement=Measurement.WEIGHT_KG,
|
measurement=Measurement.WEIGHT_KG,
|
||||||
@ -193,6 +199,8 @@ SENSORS = [
|
|||||||
device_class=SensorDeviceClass.SPEED,
|
device_class=SensorDeviceClass.SPEED,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
]
|
||||||
|
SLEEP_SENSORS = [
|
||||||
WithingsSensorEntityDescription(
|
WithingsSensorEntityDescription(
|
||||||
key=Measurement.SLEEP_BREATHING_DISTURBANCES_INTENSITY.value,
|
key=Measurement.SLEEP_BREATHING_DISTURBANCES_INTENSITY.value,
|
||||||
measurement=Measurement.SLEEP_BREATHING_DISTURBANCES_INTENSITY,
|
measurement=Measurement.SLEEP_BREATHING_DISTURBANCES_INTENSITY,
|
||||||
@ -369,9 +377,22 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the sensor config entry."""
|
"""Set up the sensor config entry."""
|
||||||
coordinator: WithingsDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
measurement_coordinator: WithingsMeasurementDataUpdateCoordinator = hass.data[
|
||||||
|
DOMAIN
|
||||||
|
][entry.entry_id][MEASUREMENT_COORDINATOR]
|
||||||
|
entities: list[SensorEntity] = []
|
||||||
|
entities.extend(
|
||||||
|
WithingsMeasurementSensor(measurement_coordinator, attribute)
|
||||||
|
for attribute in MEASUREMENT_SENSORS
|
||||||
|
)
|
||||||
|
sleep_coordinator: WithingsSleepDataUpdateCoordinator = hass.data[DOMAIN][
|
||||||
|
entry.entry_id
|
||||||
|
][SLEEP_COORDINATOR]
|
||||||
|
|
||||||
async_add_entities(WithingsSensor(coordinator, attribute) for attribute in SENSORS)
|
entities.extend(
|
||||||
|
WithingsSleepSensor(sleep_coordinator, attribute) for attribute in SLEEP_SENSORS
|
||||||
|
)
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
class WithingsSensor(WithingsEntity, SensorEntity):
|
class WithingsSensor(WithingsEntity, SensorEntity):
|
||||||
@ -400,3 +421,15 @@ class WithingsSensor(WithingsEntity, SensorEntity):
|
|||||||
super().available
|
super().available
|
||||||
and self.entity_description.measurement in self.coordinator.data
|
and self.entity_description.measurement in self.coordinator.data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WithingsMeasurementSensor(WithingsSensor):
|
||||||
|
"""Implementation of a Withings measurement sensor."""
|
||||||
|
|
||||||
|
coordinator: WithingsMeasurementDataUpdateCoordinator
|
||||||
|
|
||||||
|
|
||||||
|
class WithingsSleepSensor(WithingsSensor):
|
||||||
|
"""Implementation of a Withings sleep sensor."""
|
||||||
|
|
||||||
|
coordinator: WithingsSleepDataUpdateCoordinator
|
||||||
|
@ -223,13 +223,14 @@ async def test_triggering_reauth(
|
|||||||
withings: AsyncMock,
|
withings: AsyncMock,
|
||||||
polling_config_entry: MockConfigEntry,
|
polling_config_entry: MockConfigEntry,
|
||||||
error: Exception,
|
error: Exception,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test triggering reauth."""
|
"""Test triggering reauth."""
|
||||||
await setup_integration(hass, polling_config_entry, False)
|
await setup_integration(hass, polling_config_entry, False)
|
||||||
|
|
||||||
withings.async_measure_get_meas.side_effect = error
|
withings.async_measure_get_meas.side_effect = error
|
||||||
future = dt_util.utcnow() + timedelta(minutes=10)
|
freezer.tick(timedelta(minutes=10))
|
||||||
async_fire_time_changed(hass, future)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
flows = hass.config_entries.flow.async_progress()
|
flows = hass.config_entries.flow.async_progress()
|
||||||
|
@ -8,7 +8,7 @@ from syrupy import SnapshotAssertion
|
|||||||
|
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
from homeassistant.components.withings.const import DOMAIN
|
from homeassistant.components.withings.const import DOMAIN
|
||||||
from homeassistant.components.withings.sensor import SENSORS
|
from homeassistant.components.withings.sensor import MEASUREMENT_SENSORS, SLEEP_SENSORS
|
||||||
from homeassistant.const import STATE_UNAVAILABLE
|
from homeassistant.const import STATE_UNAVAILABLE
|
||||||
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
|
||||||
@ -42,7 +42,7 @@ async def test_all_entities(
|
|||||||
"""Test all entities."""
|
"""Test all entities."""
|
||||||
await setup_integration(hass, polling_config_entry)
|
await setup_integration(hass, polling_config_entry)
|
||||||
|
|
||||||
for sensor in SENSORS:
|
for sensor in MEASUREMENT_SENSORS + SLEEP_SENSORS:
|
||||||
entity_id = await async_get_entity_id(hass, sensor.key, USER_ID, SENSOR_DOMAIN)
|
entity_id = await async_get_entity_id(hass, sensor.key, USER_ID, SENSOR_DOMAIN)
|
||||||
assert hass.states.get(entity_id) == snapshot
|
assert hass.states.get(entity_id) == snapshot
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user