mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 10:47:10 +00:00
Add CoordinatorWeatherEntity (#98777)
This commit is contained in:
parent
92258b8e6f
commit
3e7ec88703
@ -11,8 +11,8 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_TIME,
|
ATTR_FORECAST_TIME,
|
||||||
ATTR_FORECAST_WIND_BEARING,
|
ATTR_FORECAST_WIND_BEARING,
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
|
CoordinatorWeatherEntity,
|
||||||
Forecast,
|
Forecast,
|
||||||
WeatherEntity,
|
|
||||||
WeatherEntityFeature,
|
WeatherEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -22,10 +22,9 @@ from homeassistant.const import (
|
|||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
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_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_API_CONDITION,
|
ATTR_API_CONDITION,
|
||||||
@ -111,7 +110,7 @@ async def async_setup_entry(
|
|||||||
async_add_entities(entities, False)
|
async_add_entities(entities, False)
|
||||||
|
|
||||||
|
|
||||||
class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
|
class AemetWeather(CoordinatorWeatherEntity[WeatherUpdateCoordinator]):
|
||||||
"""Implementation of an AEMET OpenData sensor."""
|
"""Implementation of an AEMET OpenData sensor."""
|
||||||
|
|
||||||
_attr_attribution = ATTRIBUTION
|
_attr_attribution = ATTRIBUTION
|
||||||
@ -139,15 +138,6 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
|
|||||||
self._attr_name = name
|
self._attr_name = name
|
||||||
self._attr_unique_id = unique_id
|
self._attr_unique_id = unique_id
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_coordinator_update(self) -> None:
|
|
||||||
"""Handle updated data from the coordinator."""
|
|
||||||
super()._handle_coordinator_update()
|
|
||||||
assert self.platform.config_entry
|
|
||||||
self.platform.config_entry.async_create_task(
|
|
||||||
self.hass, self.async_update_listeners(("daily", "hourly"))
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def condition(self):
|
def condition(self):
|
||||||
"""Return the current condition."""
|
"""Return the current condition."""
|
||||||
|
@ -22,8 +22,8 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
|
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
|
||||||
ATTR_FORECAST_TIME,
|
ATTR_FORECAST_TIME,
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
|
CoordinatorWeatherEntity,
|
||||||
Forecast,
|
Forecast,
|
||||||
WeatherEntity,
|
|
||||||
WeatherEntityFeature,
|
WeatherEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -33,10 +33,9 @@ from homeassistant.const import (
|
|||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
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_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import device_info
|
from . import device_info
|
||||||
@ -87,7 +86,7 @@ def _calculate_unique_id(config_entry_unique_id: str | None, hourly: bool) -> st
|
|||||||
return f"{config_entry_unique_id}{'-hourly' if hourly else '-daily'}"
|
return f"{config_entry_unique_id}{'-hourly' if hourly else '-daily'}"
|
||||||
|
|
||||||
|
|
||||||
class ECWeather(CoordinatorEntity, WeatherEntity):
|
class ECWeather(CoordinatorWeatherEntity):
|
||||||
"""Representation of a weather condition."""
|
"""Representation of a weather condition."""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
@ -112,15 +111,6 @@ class ECWeather(CoordinatorEntity, WeatherEntity):
|
|||||||
self._hourly = hourly
|
self._hourly = hourly
|
||||||
self._attr_device_info = device_info(coordinator.config_entry)
|
self._attr_device_info = device_info(coordinator.config_entry)
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_coordinator_update(self) -> None:
|
|
||||||
"""Handle updated data from the coordinator."""
|
|
||||||
super()._handle_coordinator_update()
|
|
||||||
assert self.platform.config_entry
|
|
||||||
self.platform.config_entry.async_create_task(
|
|
||||||
self.hass, self.async_update_listeners(("daily", "hourly"))
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_temperature(self):
|
def native_temperature(self):
|
||||||
"""Return the temperature."""
|
"""Return the temperature."""
|
||||||
|
@ -16,8 +16,8 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_WEATHER_WIND_GUST_SPEED,
|
ATTR_WEATHER_WIND_GUST_SPEED,
|
||||||
ATTR_WEATHER_WIND_SPEED,
|
ATTR_WEATHER_WIND_SPEED,
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
|
CoordinatorWeatherEntity,
|
||||||
Forecast,
|
Forecast,
|
||||||
WeatherEntity,
|
|
||||||
WeatherEntityFeature,
|
WeatherEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -30,11 +30,10 @@ from homeassistant.const import (
|
|||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||||
|
|
||||||
from . import MetDataUpdateCoordinator
|
from . import MetDataUpdateCoordinator
|
||||||
@ -92,7 +91,7 @@ def format_condition(condition: str) -> str:
|
|||||||
return condition
|
return condition
|
||||||
|
|
||||||
|
|
||||||
class MetWeather(CoordinatorEntity[MetDataUpdateCoordinator], WeatherEntity):
|
class MetWeather(CoordinatorWeatherEntity[MetDataUpdateCoordinator]):
|
||||||
"""Implementation of a Met.no weather condition."""
|
"""Implementation of a Met.no weather condition."""
|
||||||
|
|
||||||
_attr_attribution = (
|
_attr_attribution = (
|
||||||
@ -148,15 +147,6 @@ class MetWeather(CoordinatorEntity[MetDataUpdateCoordinator], WeatherEntity):
|
|||||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||||
return not self._hourly
|
return not self._hourly
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_coordinator_update(self) -> None:
|
|
||||||
"""Handle updated data from the coordinator."""
|
|
||||||
super()._handle_coordinator_update()
|
|
||||||
assert self.platform.config_entry
|
|
||||||
self.platform.config_entry.async_create_task(
|
|
||||||
self.hass, self.async_update_listeners(("daily", "hourly"))
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def condition(self) -> str | None:
|
def condition(self) -> str | None:
|
||||||
"""Return the current condition."""
|
"""Return the current condition."""
|
||||||
|
@ -7,8 +7,8 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_CONDITION,
|
ATTR_FORECAST_CONDITION,
|
||||||
ATTR_FORECAST_TIME,
|
ATTR_FORECAST_TIME,
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
|
CoordinatorWeatherEntity,
|
||||||
Forecast,
|
Forecast,
|
||||||
WeatherEntity,
|
|
||||||
WeatherEntityFeature,
|
WeatherEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -21,14 +21,11 @@ from homeassistant.const import (
|
|||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import (
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
CoordinatorEntity,
|
|
||||||
DataUpdateCoordinator,
|
|
||||||
)
|
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import MetEireannWeatherData
|
from . import MetEireannWeatherData
|
||||||
@ -78,7 +75,7 @@ def _calculate_unique_id(config: MappingProxyType[str, Any], hourly: bool) -> st
|
|||||||
|
|
||||||
|
|
||||||
class MetEireannWeather(
|
class MetEireannWeather(
|
||||||
CoordinatorEntity[DataUpdateCoordinator[MetEireannWeatherData]], WeatherEntity
|
CoordinatorWeatherEntity[DataUpdateCoordinator[MetEireannWeatherData]]
|
||||||
):
|
):
|
||||||
"""Implementation of a Met Éireann weather condition."""
|
"""Implementation of a Met Éireann weather condition."""
|
||||||
|
|
||||||
@ -98,15 +95,6 @@ class MetEireannWeather(
|
|||||||
self._config = config
|
self._config = config
|
||||||
self._hourly = hourly
|
self._hourly = hourly
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_coordinator_update(self) -> None:
|
|
||||||
"""Handle updated data from the coordinator."""
|
|
||||||
super()._handle_coordinator_update()
|
|
||||||
assert self.platform.config_entry
|
|
||||||
self.platform.config_entry.async_create_task(
|
|
||||||
self.hass, self.async_update_listeners(("daily", "hourly"))
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the sensor."""
|
"""Return the name of the sensor."""
|
||||||
|
@ -17,8 +17,8 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_TIME,
|
ATTR_FORECAST_TIME,
|
||||||
ATTR_FORECAST_WIND_BEARING,
|
ATTR_FORECAST_WIND_BEARING,
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
|
CoordinatorWeatherEntity,
|
||||||
Forecast,
|
Forecast,
|
||||||
WeatherEntity,
|
|
||||||
WeatherEntityFeature,
|
WeatherEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -31,7 +31,7 @@ from homeassistant.const import (
|
|||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
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_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.sun import is_up
|
from homeassistant.helpers.sun import is_up
|
||||||
@ -93,7 +93,7 @@ def _calculate_unique_id(config_entry_unique_id: str | None, forecast_type: str)
|
|||||||
return f"{config_entry_unique_id}_{forecast_type}"
|
return f"{config_entry_unique_id}_{forecast_type}"
|
||||||
|
|
||||||
|
|
||||||
class TomorrowioWeatherEntity(TomorrowioEntity, WeatherEntity):
|
class TomorrowioWeatherEntity(TomorrowioEntity, CoordinatorWeatherEntity):
|
||||||
"""Entity that talks to Tomorrow.io v4 API to retrieve weather data."""
|
"""Entity that talks to Tomorrow.io v4 API to retrieve weather data."""
|
||||||
|
|
||||||
_attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS
|
_attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS
|
||||||
@ -123,15 +123,6 @@ class TomorrowioWeatherEntity(TomorrowioEntity, WeatherEntity):
|
|||||||
config_entry.unique_id, forecast_type
|
config_entry.unique_id, forecast_type
|
||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_coordinator_update(self) -> None:
|
|
||||||
"""Handle updated data from the coordinator."""
|
|
||||||
super()._handle_coordinator_update()
|
|
||||||
assert self.platform.config_entry
|
|
||||||
self.platform.config_entry.async_create_task(
|
|
||||||
self.hass, self.async_update_listeners(("daily", "hourly"))
|
|
||||||
)
|
|
||||||
|
|
||||||
def _forecast_dict(
|
def _forecast_dict(
|
||||||
self,
|
self,
|
||||||
forecast_dt: datetime,
|
forecast_dt: datetime,
|
||||||
|
@ -8,7 +8,7 @@ from dataclasses import dataclass
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Final, Literal, Required, TypedDict, final
|
from typing import Any, Final, Literal, Required, TypedDict, TypeVar, final
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -37,6 +37,10 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
|
|||||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
from homeassistant.helpers.update_coordinator import (
|
||||||
|
CoordinatorEntity,
|
||||||
|
DataUpdateCoordinator,
|
||||||
|
)
|
||||||
from homeassistant.util.json import JsonValueType
|
from homeassistant.util.json import JsonValueType
|
||||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||||
|
|
||||||
@ -117,6 +121,10 @@ ROUNDING_PRECISION = 2
|
|||||||
|
|
||||||
SERVICE_GET_FORECAST: Final = "get_forecast"
|
SERVICE_GET_FORECAST: Final = "get_forecast"
|
||||||
|
|
||||||
|
_DataUpdateCoordinatorT = TypeVar(
|
||||||
|
"_DataUpdateCoordinatorT", bound="DataUpdateCoordinator[Any]"
|
||||||
|
)
|
||||||
|
|
||||||
# mypy: disallow-any-generics
|
# mypy: disallow-any-generics
|
||||||
|
|
||||||
|
|
||||||
@ -1155,3 +1163,18 @@ async def async_get_forecast_service(
|
|||||||
return {
|
return {
|
||||||
"forecast": converted_forecast_list,
|
"forecast": converted_forecast_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CoordinatorWeatherEntity(
|
||||||
|
CoordinatorEntity[_DataUpdateCoordinatorT], WeatherEntity
|
||||||
|
):
|
||||||
|
"""A class for weather entities using a single DataUpdateCoordinator."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle_coordinator_update(self) -> None:
|
||||||
|
"""Handle updated data from the coordinator."""
|
||||||
|
super()._handle_coordinator_update()
|
||||||
|
assert self.coordinator.config_entry
|
||||||
|
self.coordinator.config_entry.async_create_task(
|
||||||
|
self.hass, self.async_update_listeners(None)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user