Add CoordinatorWeatherEntity (#98777)

This commit is contained in:
Erik Montnemery 2023-08-21 23:10:16 +02:00 committed by GitHub
parent 92258b8e6f
commit 3e7ec88703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 68 deletions

View File

@ -11,8 +11,8 @@ from homeassistant.components.weather import (
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
DOMAIN as WEATHER_DOMAIN,
CoordinatorWeatherEntity,
Forecast,
WeatherEntity,
WeatherEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
@ -22,10 +22,9 @@ from homeassistant.const import (
UnitOfSpeed,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import (
ATTR_API_CONDITION,
@ -111,7 +110,7 @@ async def async_setup_entry(
async_add_entities(entities, False)
class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
class AemetWeather(CoordinatorWeatherEntity[WeatherUpdateCoordinator]):
"""Implementation of an AEMET OpenData sensor."""
_attr_attribution = ATTRIBUTION
@ -139,15 +138,6 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
self._attr_name = name
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
def condition(self):
"""Return the current condition."""

View File

@ -22,8 +22,8 @@ from homeassistant.components.weather import (
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
ATTR_FORECAST_TIME,
DOMAIN as WEATHER_DOMAIN,
CoordinatorWeatherEntity,
Forecast,
WeatherEntity,
WeatherEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
@ -33,10 +33,9 @@ from homeassistant.const import (
UnitOfSpeed,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import dt as dt_util
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'}"
class ECWeather(CoordinatorEntity, WeatherEntity):
class ECWeather(CoordinatorWeatherEntity):
"""Representation of a weather condition."""
_attr_has_entity_name = True
@ -112,15 +111,6 @@ class ECWeather(CoordinatorEntity, WeatherEntity):
self._hourly = hourly
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
def native_temperature(self):
"""Return the temperature."""

View File

@ -16,8 +16,8 @@ from homeassistant.components.weather import (
ATTR_WEATHER_WIND_GUST_SPEED,
ATTR_WEATHER_WIND_SPEED,
DOMAIN as WEATHER_DOMAIN,
CoordinatorWeatherEntity,
Forecast,
WeatherEntity,
WeatherEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
@ -30,11 +30,10 @@ from homeassistant.const import (
UnitOfSpeed,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util.unit_system import METRIC_SYSTEM
from . import MetDataUpdateCoordinator
@ -92,7 +91,7 @@ def format_condition(condition: str) -> str:
return condition
class MetWeather(CoordinatorEntity[MetDataUpdateCoordinator], WeatherEntity):
class MetWeather(CoordinatorWeatherEntity[MetDataUpdateCoordinator]):
"""Implementation of a Met.no weather condition."""
_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 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
def condition(self) -> str | None:
"""Return the current condition."""

View File

@ -7,8 +7,8 @@ from homeassistant.components.weather import (
ATTR_FORECAST_CONDITION,
ATTR_FORECAST_TIME,
DOMAIN as WEATHER_DOMAIN,
CoordinatorWeatherEntity,
Forecast,
WeatherEntity,
WeatherEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
@ -21,14 +21,11 @@ from homeassistant.const import (
UnitOfSpeed,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.util import dt as dt_util
from . import MetEireannWeatherData
@ -78,7 +75,7 @@ def _calculate_unique_id(config: MappingProxyType[str, Any], hourly: bool) -> st
class MetEireannWeather(
CoordinatorEntity[DataUpdateCoordinator[MetEireannWeatherData]], WeatherEntity
CoordinatorWeatherEntity[DataUpdateCoordinator[MetEireannWeatherData]]
):
"""Implementation of a Met Éireann weather condition."""
@ -98,15 +95,6 @@ class MetEireannWeather(
self._config = config
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
def name(self):
"""Return the name of the sensor."""

View File

@ -17,8 +17,8 @@ from homeassistant.components.weather import (
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
DOMAIN as WEATHER_DOMAIN,
CoordinatorWeatherEntity,
Forecast,
WeatherEntity,
WeatherEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
@ -31,7 +31,7 @@ from homeassistant.const import (
UnitOfSpeed,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
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}"
class TomorrowioWeatherEntity(TomorrowioEntity, WeatherEntity):
class TomorrowioWeatherEntity(TomorrowioEntity, CoordinatorWeatherEntity):
"""Entity that talks to Tomorrow.io v4 API to retrieve weather data."""
_attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS
@ -123,15 +123,6 @@ class TomorrowioWeatherEntity(TomorrowioEntity, WeatherEntity):
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(
self,
forecast_dt: datetime,

View File

@ -8,7 +8,7 @@ from dataclasses import dataclass
from datetime import timedelta
import inspect
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
@ -37,6 +37,10 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
from homeassistant.util.json import JsonValueType
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
@ -117,6 +121,10 @@ ROUNDING_PRECISION = 2
SERVICE_GET_FORECAST: Final = "get_forecast"
_DataUpdateCoordinatorT = TypeVar(
"_DataUpdateCoordinatorT", bound="DataUpdateCoordinator[Any]"
)
# mypy: disallow-any-generics
@ -1155,3 +1163,18 @@ async def async_get_forecast_service(
return {
"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)
)