From d54f9796121f2f543ee6c90ec1b884037d0a4a79 Mon Sep 17 00:00:00 2001 From: "Etienne C." <59794011+etiennec78@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:20:18 +0200 Subject: [PATCH] Add a coordinator to Waze Travel Time (#148585) --- .../components/waze_travel_time/__init__.py | 121 +-------- .../waze_travel_time/coordinator.py | 245 ++++++++++++++++++ .../components/waze_travel_time/sensor.py | 170 ++---------- tests/components/waze_travel_time/conftest.py | 2 +- .../waze_travel_time/test_config_flow.py | 12 +- .../components/waze_travel_time/test_init.py | 8 +- .../waze_travel_time/test_sensor.py | 3 +- 7 files changed, 293 insertions(+), 268 deletions(-) create mode 100644 homeassistant/components/waze_travel_time/coordinator.py diff --git a/homeassistant/components/waze_travel_time/__init__.py b/homeassistant/components/waze_travel_time/__init__.py index 3a91690ef07..2e719a41a21 100644 --- a/homeassistant/components/waze_travel_time/__init__.py +++ b/homeassistant/components/waze_travel_time/__init__.py @@ -1,15 +1,13 @@ """The waze_travel_time component.""" import asyncio -from collections.abc import Collection import logging -from typing import Literal -from pywaze.route_calculator import CalcRoutesResponse, WazeRouteCalculator, WRCError +from pywaze.route_calculator import WazeRouteCalculator import voluptuous as vol from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_REGION, Platform, UnitOfLength +from homeassistant.const import CONF_REGION, Platform from homeassistant.core import ( HomeAssistant, ServiceCall, @@ -27,7 +25,6 @@ from homeassistant.helpers.selector import ( TextSelectorConfig, TextSelectorType, ) -from homeassistant.util.unit_conversion import DistanceConverter from .const import ( CONF_AVOID_FERRIES, @@ -43,13 +40,13 @@ from .const import ( DEFAULT_FILTER, DEFAULT_VEHICLE_TYPE, DOMAIN, - IMPERIAL_UNITS, METRIC_UNITS, REGIONS, SEMAPHORE, UNITS, VEHICLE_TYPES, ) +from .coordinator import WazeTravelTimeCoordinator, async_get_travel_times PLATFORMS = [Platform.SENSOR] @@ -109,6 +106,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b if SEMAPHORE not in hass.data.setdefault(DOMAIN, {}): hass.data.setdefault(DOMAIN, {})[SEMAPHORE] = asyncio.Semaphore(1) + httpx_client = get_async_client(hass) + client = WazeRouteCalculator( + region=config_entry.data[CONF_REGION].upper(), client=httpx_client + ) + + coordinator = WazeTravelTimeCoordinator(hass, config_entry, client) + config_entry.runtime_data = coordinator + + await coordinator.async_config_entry_first_refresh() + await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) async def async_get_travel_times_service(service: ServiceCall) -> ServiceResponse: @@ -140,7 +147,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b incl_filters=service.data.get(CONF_INCL_FILTER, DEFAULT_FILTER), excl_filters=service.data.get(CONF_EXCL_FILTER, DEFAULT_FILTER), ) - return {"routes": [vars(route) for route in response]} if response else None + return {"routes": [vars(route) for route in response]} hass.services.async_register( DOMAIN, @@ -152,106 +159,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b return True -async def async_get_travel_times( - client: WazeRouteCalculator, - origin: str, - destination: str, - vehicle_type: str, - avoid_toll_roads: bool, - avoid_subscription_roads: bool, - avoid_ferries: bool, - realtime: bool, - units: Literal["metric", "imperial"] = "metric", - incl_filters: Collection[str] | None = None, - excl_filters: Collection[str] | None = None, -) -> list[CalcRoutesResponse] | None: - """Get all available routes.""" - - incl_filters = incl_filters or () - excl_filters = excl_filters or () - - _LOGGER.debug( - "Getting update for origin: %s destination: %s", - origin, - destination, - ) - routes = [] - vehicle_type = "" if vehicle_type.upper() == "CAR" else vehicle_type.upper() - try: - routes = await client.calc_routes( - origin, - destination, - vehicle_type=vehicle_type, - avoid_toll_roads=avoid_toll_roads, - avoid_subscription_roads=avoid_subscription_roads, - avoid_ferries=avoid_ferries, - real_time=realtime, - alternatives=3, - ) - _LOGGER.debug("Got routes: %s", routes) - - incl_routes: list[CalcRoutesResponse] = [] - - def should_include_route(route: CalcRoutesResponse) -> bool: - if len(incl_filters) < 1: - return True - should_include = any( - street_name in incl_filters or "" in incl_filters - for street_name in route.street_names - ) - if not should_include: - _LOGGER.debug( - "Excluding route [%s], because no inclusive filter matched any streetname", - route.name, - ) - return False - return True - - incl_routes = [route for route in routes if should_include_route(route)] - - filtered_routes: list[CalcRoutesResponse] = [] - - def should_exclude_route(route: CalcRoutesResponse) -> bool: - for street_name in route.street_names: - for excl_filter in excl_filters: - if excl_filter == street_name: - _LOGGER.debug( - "Excluding route, because exclusive filter [%s] matched streetname: %s", - excl_filter, - route.name, - ) - return True - return False - - filtered_routes = [ - route for route in incl_routes if not should_exclude_route(route) - ] - - if units == IMPERIAL_UNITS: - filtered_routes = [ - CalcRoutesResponse( - name=route.name, - distance=DistanceConverter.convert( - route.distance, UnitOfLength.KILOMETERS, UnitOfLength.MILES - ), - duration=route.duration, - street_names=route.street_names, - ) - for route in filtered_routes - if route.distance is not None - ] - - if len(filtered_routes) < 1: - _LOGGER.warning("No routes found") - return None - except WRCError as exp: - _LOGGER.warning("Error on retrieving data: %s", exp) - return None - - else: - return filtered_routes - - async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Unload a config entry.""" return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS) diff --git a/homeassistant/components/waze_travel_time/coordinator.py b/homeassistant/components/waze_travel_time/coordinator.py new file mode 100644 index 00000000000..23dfea86ed2 --- /dev/null +++ b/homeassistant/components/waze_travel_time/coordinator.py @@ -0,0 +1,245 @@ +"""The Waze Travel Time data coordinator.""" + +import asyncio +from collections.abc import Collection +from dataclasses import dataclass +from datetime import timedelta +import logging +from typing import Literal + +from pywaze.route_calculator import CalcRoutesResponse, WazeRouteCalculator, WRCError + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import UnitOfLength +from homeassistant.core import HomeAssistant +from homeassistant.helpers.location import find_coordinates +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed +from homeassistant.util.unit_conversion import DistanceConverter + +from .const import ( + CONF_AVOID_FERRIES, + CONF_AVOID_SUBSCRIPTION_ROADS, + CONF_AVOID_TOLL_ROADS, + CONF_DESTINATION, + CONF_EXCL_FILTER, + CONF_INCL_FILTER, + CONF_ORIGIN, + CONF_REALTIME, + CONF_UNITS, + CONF_VEHICLE_TYPE, + DOMAIN, + IMPERIAL_UNITS, + SEMAPHORE, +) + +_LOGGER = logging.getLogger(__name__) + +SCAN_INTERVAL = timedelta(minutes=5) + +SECONDS_BETWEEN_API_CALLS = 0.5 + + +async def async_get_travel_times( + client: WazeRouteCalculator, + origin: str, + destination: str, + vehicle_type: str, + avoid_toll_roads: bool, + avoid_subscription_roads: bool, + avoid_ferries: bool, + realtime: bool, + units: Literal["metric", "imperial"] = "metric", + incl_filters: Collection[str] | None = None, + excl_filters: Collection[str] | None = None, +) -> list[CalcRoutesResponse]: + """Get all available routes.""" + + incl_filters = incl_filters or () + excl_filters = excl_filters or () + + _LOGGER.debug( + "Getting update for origin: %s destination: %s", + origin, + destination, + ) + routes = [] + vehicle_type = "" if vehicle_type.upper() == "CAR" else vehicle_type.upper() + try: + routes = await client.calc_routes( + origin, + destination, + vehicle_type=vehicle_type, + avoid_toll_roads=avoid_toll_roads, + avoid_subscription_roads=avoid_subscription_roads, + avoid_ferries=avoid_ferries, + real_time=realtime, + alternatives=3, + ) + + if len(routes) < 1: + _LOGGER.warning("No routes found") + return routes + + _LOGGER.debug("Got routes: %s", routes) + + incl_routes: list[CalcRoutesResponse] = [] + + def should_include_route(route: CalcRoutesResponse) -> bool: + if len(incl_filters) < 1: + return True + should_include = any( + street_name in incl_filters or "" in incl_filters + for street_name in route.street_names + ) + if not should_include: + _LOGGER.debug( + "Excluding route [%s], because no inclusive filter matched any streetname", + route.name, + ) + return False + return True + + incl_routes = [route for route in routes if should_include_route(route)] + + filtered_routes: list[CalcRoutesResponse] = [] + + def should_exclude_route(route: CalcRoutesResponse) -> bool: + for street_name in route.street_names: + for excl_filter in excl_filters: + if excl_filter == street_name: + _LOGGER.debug( + "Excluding route, because exclusive filter [%s] matched streetname: %s", + excl_filter, + route.name, + ) + return True + return False + + filtered_routes = [ + route for route in incl_routes if not should_exclude_route(route) + ] + + if len(filtered_routes) < 1: + _LOGGER.warning("No routes matched your filters") + return filtered_routes + + if units == IMPERIAL_UNITS: + filtered_routes = [ + CalcRoutesResponse( + name=route.name, + distance=DistanceConverter.convert( + route.distance, UnitOfLength.KILOMETERS, UnitOfLength.MILES + ), + duration=route.duration, + street_names=route.street_names, + ) + for route in filtered_routes + if route.distance is not None + ] + + except WRCError as exp: + raise UpdateFailed(f"Error on retrieving data: {exp}") from exp + + else: + return filtered_routes + + +@dataclass +class WazeTravelTimeData: + """WazeTravelTime data class.""" + + origin: str + destination: str + duration: float | None + distance: float | None + route: str | None + + +class WazeTravelTimeCoordinator(DataUpdateCoordinator[WazeTravelTimeData]): + """Waze Travel Time DataUpdateCoordinator.""" + + config_entry: ConfigEntry + + def __init__( + self, + hass: HomeAssistant, + config_entry: ConfigEntry, + client: WazeRouteCalculator, + ) -> None: + """Initialize.""" + super().__init__( + hass, + _LOGGER, + name=DOMAIN, + config_entry=config_entry, + update_interval=SCAN_INTERVAL, + ) + self.client = client + self._origin = config_entry.data[CONF_ORIGIN] + self._destination = config_entry.data[CONF_DESTINATION] + + async def _async_update_data(self) -> WazeTravelTimeData: + """Get the latest data from Waze.""" + origin_coordinates = find_coordinates(self.hass, self._origin) + destination_coordinates = find_coordinates(self.hass, self._destination) + + _LOGGER.debug( + "Fetching Route for %s, from %s to %s", + self.config_entry.title, + self._origin, + self._destination, + ) + await self.hass.data[DOMAIN][SEMAPHORE].acquire() + try: + if origin_coordinates is None or destination_coordinates is None: + raise UpdateFailed("Unable to determine origin or destination") + + # Grab options on every update + incl_filter = self.config_entry.options[CONF_INCL_FILTER] + excl_filter = self.config_entry.options[CONF_EXCL_FILTER] + realtime = self.config_entry.options[CONF_REALTIME] + vehicle_type = self.config_entry.options[CONF_VEHICLE_TYPE] + avoid_toll_roads = self.config_entry.options[CONF_AVOID_TOLL_ROADS] + avoid_subscription_roads = self.config_entry.options[ + CONF_AVOID_SUBSCRIPTION_ROADS + ] + avoid_ferries = self.config_entry.options[CONF_AVOID_FERRIES] + routes = await async_get_travel_times( + self.client, + origin_coordinates, + destination_coordinates, + vehicle_type, + avoid_toll_roads, + avoid_subscription_roads, + avoid_ferries, + realtime, + self.config_entry.options[CONF_UNITS], + incl_filter, + excl_filter, + ) + if len(routes) < 1: + travel_data = WazeTravelTimeData( + origin=origin_coordinates, + destination=destination_coordinates, + duration=None, + distance=None, + route=None, + ) + + else: + route = routes[0] + + travel_data = WazeTravelTimeData( + origin=origin_coordinates, + destination=destination_coordinates, + duration=route.duration, + distance=route.distance, + route=route.name, + ) + + await asyncio.sleep(SECONDS_BETWEEN_API_CALLS) + + finally: + self.hass.data[DOMAIN][SEMAPHORE].release() + + return travel_data diff --git a/homeassistant/components/waze_travel_time/sensor.py b/homeassistant/components/waze_travel_time/sensor.py index 1f21cc2ea78..e56edfae53d 100644 --- a/homeassistant/components/waze_travel_time/sensor.py +++ b/homeassistant/components/waze_travel_time/sensor.py @@ -2,56 +2,22 @@ from __future__ import annotations -import asyncio -from datetime import timedelta -import logging from typing import Any -import httpx -from pywaze.route_calculator import WazeRouteCalculator - from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - CONF_NAME, - CONF_REGION, - EVENT_HOMEASSISTANT_STARTED, - UnitOfTime, -) -from homeassistant.core import CoreState, HomeAssistant +from homeassistant.const import CONF_NAME, UnitOfTime +from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from homeassistant.helpers.httpx_client import get_async_client -from homeassistant.helpers.location import find_coordinates +from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import async_get_travel_times -from .const import ( - CONF_AVOID_FERRIES, - CONF_AVOID_SUBSCRIPTION_ROADS, - CONF_AVOID_TOLL_ROADS, - CONF_DESTINATION, - CONF_EXCL_FILTER, - CONF_INCL_FILTER, - CONF_ORIGIN, - CONF_REALTIME, - CONF_UNITS, - CONF_VEHICLE_TYPE, - DEFAULT_NAME, - DOMAIN, - SEMAPHORE, -) - -_LOGGER = logging.getLogger(__name__) - -SCAN_INTERVAL = timedelta(minutes=5) - -PARALLEL_UPDATES = 1 - -SECONDS_BETWEEN_API_CALLS = 0.5 +from .const import DEFAULT_NAME, DOMAIN +from .coordinator import WazeTravelTimeCoordinator async def async_setup_entry( @@ -60,23 +26,15 @@ async def async_setup_entry( async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up a Waze travel time sensor entry.""" - destination = config_entry.data[CONF_DESTINATION] - origin = config_entry.data[CONF_ORIGIN] - region = config_entry.data[CONF_REGION] name = config_entry.data.get(CONF_NAME, DEFAULT_NAME) + coordinator = config_entry.runtime_data - data = WazeTravelTimeData( - region, - get_async_client(hass), - config_entry, - ) - - sensor = WazeTravelTime(config_entry.entry_id, name, origin, destination, data) + sensor = WazeTravelTimeSensor(config_entry.entry_id, name, coordinator) async_add_entities([sensor], False) -class WazeTravelTime(SensorEntity): +class WazeTravelTimeSensor(CoordinatorEntity[WazeTravelTimeCoordinator], SensorEntity): """Representation of a Waze travel time sensor.""" _attr_attribution = "Powered by Waze" @@ -95,119 +53,33 @@ class WazeTravelTime(SensorEntity): self, unique_id: str, name: str, - origin: str, - destination: str, - waze_data: WazeTravelTimeData, + coordinator: WazeTravelTimeCoordinator, ) -> None: """Initialize the Waze travel time sensor.""" + super().__init__(coordinator) self._attr_unique_id = unique_id - self._waze_data = waze_data self._attr_name = name - self._origin = origin - self._destination = destination - self._state = None - - async def async_added_to_hass(self) -> None: - """Handle when entity is added.""" - if self.hass.state is not CoreState.running: - self.hass.bus.async_listen_once( - EVENT_HOMEASSISTANT_STARTED, self.first_update - ) - else: - await self.first_update() @property def native_value(self) -> float | None: """Return the state of the sensor.""" - if self._waze_data.duration is not None: - return round(self._waze_data.duration) - + if ( + self.coordinator.data is not None + and self.coordinator.data.duration is not None + ): + return round(self.coordinator.data.duration) return None @property def extra_state_attributes(self) -> dict[str, Any] | None: """Return the state attributes of the last update.""" - if self._waze_data.duration is None: + if self.coordinator.data is None: return None return { - "duration": self._waze_data.duration, - "distance": self._waze_data.distance, - "route": self._waze_data.route, - "origin": self._waze_data.origin, - "destination": self._waze_data.destination, + "duration": self.coordinator.data.duration, + "distance": self.coordinator.data.distance, + "route": self.coordinator.data.route, + "origin": self.coordinator.data.origin, + "destination": self.coordinator.data.destination, } - - async def first_update(self, _=None) -> None: - """Run first update and write state.""" - await self.async_update() - self.async_write_ha_state() - - async def async_update(self) -> None: - """Fetch new state data for the sensor.""" - _LOGGER.debug("Fetching Route for %s", self._attr_name) - self._waze_data.origin = find_coordinates(self.hass, self._origin) - self._waze_data.destination = find_coordinates(self.hass, self._destination) - await self.hass.data[DOMAIN][SEMAPHORE].acquire() - try: - await self._waze_data.async_update() - await asyncio.sleep(SECONDS_BETWEEN_API_CALLS) - finally: - self.hass.data[DOMAIN][SEMAPHORE].release() - - -class WazeTravelTimeData: - """WazeTravelTime Data object.""" - - def __init__( - self, region: str, client: httpx.AsyncClient, config_entry: ConfigEntry - ) -> None: - """Set up WazeRouteCalculator.""" - self.config_entry = config_entry - self.client = WazeRouteCalculator(region=region, client=client) - self.origin: str | None = None - self.destination: str | None = None - self.duration = None - self.distance = None - self.route = None - - async def async_update(self): - """Update WazeRouteCalculator Sensor.""" - _LOGGER.debug( - "Getting update for origin: %s destination: %s", - self.origin, - self.destination, - ) - if self.origin is not None and self.destination is not None: - # Grab options on every update - incl_filter = self.config_entry.options[CONF_INCL_FILTER] - excl_filter = self.config_entry.options[CONF_EXCL_FILTER] - realtime = self.config_entry.options[CONF_REALTIME] - vehicle_type = self.config_entry.options[CONF_VEHICLE_TYPE] - avoid_toll_roads = self.config_entry.options[CONF_AVOID_TOLL_ROADS] - avoid_subscription_roads = self.config_entry.options[ - CONF_AVOID_SUBSCRIPTION_ROADS - ] - avoid_ferries = self.config_entry.options[CONF_AVOID_FERRIES] - routes = await async_get_travel_times( - self.client, - self.origin, - self.destination, - vehicle_type, - avoid_toll_roads, - avoid_subscription_roads, - avoid_ferries, - realtime, - self.config_entry.options[CONF_UNITS], - incl_filter, - excl_filter, - ) - if routes: - route = routes[0] - else: - _LOGGER.warning("No routes found") - return - - self.duration = route.duration - self.distance = route.distance - self.route = route.name diff --git a/tests/components/waze_travel_time/conftest.py b/tests/components/waze_travel_time/conftest.py index c9214ed8b71..fbaa7519ea8 100644 --- a/tests/components/waze_travel_time/conftest.py +++ b/tests/components/waze_travel_time/conftest.py @@ -53,7 +53,7 @@ def mock_update_fixture(): @pytest.fixture(name="validate_config_entry") def validate_config_entry_fixture(mock_update): """Return valid config entry.""" - mock_update.return_value = None + mock_update.return_value = [] return mock_update diff --git a/tests/components/waze_travel_time/test_config_flow.py b/tests/components/waze_travel_time/test_config_flow.py index 9ff7509a52c..da718a98983 100644 --- a/tests/components/waze_travel_time/test_config_flow.py +++ b/tests/components/waze_travel_time/test_config_flow.py @@ -116,8 +116,8 @@ async def test_options(hass: HomeAssistant) -> None: CONF_AVOID_FERRIES: True, CONF_AVOID_SUBSCRIPTION_ROADS: True, CONF_AVOID_TOLL_ROADS: True, - CONF_EXCL_FILTER: ["exclude"], - CONF_INCL_FILTER: ["include"], + CONF_EXCL_FILTER: ["ExcludeThis"], + CONF_INCL_FILTER: ["IncludeThis"], CONF_REALTIME: False, CONF_UNITS: IMPERIAL_UNITS, CONF_VEHICLE_TYPE: "taxi", @@ -129,8 +129,8 @@ async def test_options(hass: HomeAssistant) -> None: CONF_AVOID_FERRIES: True, CONF_AVOID_SUBSCRIPTION_ROADS: True, CONF_AVOID_TOLL_ROADS: True, - CONF_EXCL_FILTER: ["exclude"], - CONF_INCL_FILTER: ["include"], + CONF_EXCL_FILTER: ["ExcludeThis"], + CONF_INCL_FILTER: ["IncludeThis"], CONF_REALTIME: False, CONF_UNITS: IMPERIAL_UNITS, CONF_VEHICLE_TYPE: "taxi", @@ -140,8 +140,8 @@ async def test_options(hass: HomeAssistant) -> None: CONF_AVOID_FERRIES: True, CONF_AVOID_SUBSCRIPTION_ROADS: True, CONF_AVOID_TOLL_ROADS: True, - CONF_EXCL_FILTER: ["exclude"], - CONF_INCL_FILTER: ["include"], + CONF_EXCL_FILTER: ["ExcludeThis"], + CONF_INCL_FILTER: ["IncludeThis"], CONF_REALTIME: False, CONF_UNITS: IMPERIAL_UNITS, CONF_VEHICLE_TYPE: "taxi", diff --git a/tests/components/waze_travel_time/test_init.py b/tests/components/waze_travel_time/test_init.py index 89bccc00985..d11bca524e9 100644 --- a/tests/components/waze_travel_time/test_init.py +++ b/tests/components/waze_travel_time/test_init.py @@ -101,8 +101,8 @@ async def test_migrate_entry_v1_v2(hass: HomeAssistant) -> None: CONF_AVOID_FERRIES: DEFAULT_AVOID_FERRIES, CONF_AVOID_SUBSCRIPTION_ROADS: DEFAULT_AVOID_SUBSCRIPTION_ROADS, CONF_AVOID_TOLL_ROADS: DEFAULT_AVOID_TOLL_ROADS, - CONF_INCL_FILTER: "include", - CONF_EXCL_FILTER: "exclude", + CONF_INCL_FILTER: "IncludeThis", + CONF_EXCL_FILTER: "ExcludeThis", }, ) @@ -114,5 +114,5 @@ async def test_migrate_entry_v1_v2(hass: HomeAssistant) -> None: assert updated_entry.state is ConfigEntryState.LOADED assert updated_entry.version == 2 - assert updated_entry.options[CONF_INCL_FILTER] == ["include"] - assert updated_entry.options[CONF_EXCL_FILTER] == ["exclude"] + assert updated_entry.options[CONF_INCL_FILTER] == ["IncludeThis"] + assert updated_entry.options[CONF_EXCL_FILTER] == ["ExcludeThis"] diff --git a/tests/components/waze_travel_time/test_sensor.py b/tests/components/waze_travel_time/test_sensor.py index 94e3a0cf9d7..0aa99196c48 100644 --- a/tests/components/waze_travel_time/test_sensor.py +++ b/tests/components/waze_travel_time/test_sensor.py @@ -18,6 +18,7 @@ from homeassistant.components.waze_travel_time.const import ( IMPERIAL_UNITS, METRIC_UNITS, ) +from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant from .const import MOCK_CONFIG @@ -153,5 +154,5 @@ async def test_sensor_failed_wrcerror( await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - assert hass.states.get("sensor.waze_travel_time").state == "unknown" + assert config_entry.state is ConfigEntryState.SETUP_RETRY assert "Error on retrieving data: " in caplog.text