Move coordinator to own file in Open-Meteo (#134197)

This commit is contained in:
G Johansson 2024-12-29 15:25:40 +01:00 committed by GitHub
parent 7704ef95a4
commit 409dc4ad48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 57 deletions

View File

@ -2,71 +2,20 @@
from __future__ import annotations
from open_meteo import (
DailyParameters,
Forecast,
HourlyParameters,
OpenMeteo,
OpenMeteoError,
PrecipitationUnit,
TemperatureUnit,
WindSpeedUnit,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, CONF_ZONE, Platform
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN, LOGGER, SCAN_INTERVAL
from .const import DOMAIN
from .coordinator import OpenMeteoDataUpdateCoordinator
PLATFORMS = [Platform.WEATHER]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Open-Meteo from a config entry."""
session = async_get_clientsession(hass)
open_meteo = OpenMeteo(session=session)
async def async_update_forecast() -> Forecast:
if (zone := hass.states.get(entry.data[CONF_ZONE])) is None:
raise UpdateFailed(f"Zone '{entry.data[CONF_ZONE]}' not found")
try:
return await open_meteo.forecast(
latitude=zone.attributes[ATTR_LATITUDE],
longitude=zone.attributes[ATTR_LONGITUDE],
current_weather=True,
daily=[
DailyParameters.PRECIPITATION_SUM,
DailyParameters.TEMPERATURE_2M_MAX,
DailyParameters.TEMPERATURE_2M_MIN,
DailyParameters.WEATHER_CODE,
DailyParameters.WIND_DIRECTION_10M_DOMINANT,
DailyParameters.WIND_SPEED_10M_MAX,
],
hourly=[
HourlyParameters.PRECIPITATION,
HourlyParameters.TEMPERATURE_2M,
HourlyParameters.WEATHER_CODE,
],
precipitation_unit=PrecipitationUnit.MILLIMETERS,
temperature_unit=TemperatureUnit.CELSIUS,
timezone="UTC",
wind_speed_unit=WindSpeedUnit.KILOMETERS_PER_HOUR,
)
except OpenMeteoError as err:
raise UpdateFailed("Open-Meteo API communication error") from err
coordinator: DataUpdateCoordinator[Forecast] = DataUpdateCoordinator(
hass,
LOGGER,
config_entry=entry,
name=f"{DOMAIN}_{entry.data[CONF_ZONE]}",
update_interval=SCAN_INTERVAL,
update_method=async_update_forecast,
)
coordinator = OpenMeteoDataUpdateCoordinator(hass, entry)
await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

View File

@ -0,0 +1,71 @@
"""DataUpdateCoordinator for the Open-Meteo integration."""
from __future__ import annotations
from open_meteo import (
DailyParameters,
Forecast,
HourlyParameters,
OpenMeteo,
OpenMeteoError,
PrecipitationUnit,
TemperatureUnit,
WindSpeedUnit,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, CONF_ZONE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN, LOGGER, SCAN_INTERVAL
class OpenMeteoDataUpdateCoordinator(DataUpdateCoordinator[Forecast]):
"""A Open-Meteo Data Update Coordinator."""
config_entry: ConfigEntry
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
"""Initialize the Open-Meteo coordinator."""
super().__init__(
hass,
LOGGER,
config_entry=config_entry,
name=f"{DOMAIN}_{config_entry.data[CONF_ZONE]}",
update_interval=SCAN_INTERVAL,
)
session = async_get_clientsession(hass)
self.open_meteo = OpenMeteo(session=session)
async def _async_update_data(self) -> Forecast:
"""Fetch data from Sensibo."""
if (zone := self.hass.states.get(self.config_entry.data[CONF_ZONE])) is None:
raise UpdateFailed(f"Zone '{self.config_entry.data[CONF_ZONE]}' not found")
try:
return await self.open_meteo.forecast(
latitude=zone.attributes[ATTR_LATITUDE],
longitude=zone.attributes[ATTR_LONGITUDE],
current_weather=True,
daily=[
DailyParameters.PRECIPITATION_SUM,
DailyParameters.TEMPERATURE_2M_MAX,
DailyParameters.TEMPERATURE_2M_MIN,
DailyParameters.WEATHER_CODE,
DailyParameters.WIND_DIRECTION_10M_DOMINANT,
DailyParameters.WIND_SPEED_10M_MAX,
],
hourly=[
HourlyParameters.PRECIPITATION,
HourlyParameters.TEMPERATURE_2M,
HourlyParameters.WEATHER_CODE,
],
precipitation_unit=PrecipitationUnit.MILLIMETERS,
temperature_unit=TemperatureUnit.CELSIUS,
timezone="UTC",
wind_speed_unit=WindSpeedUnit.KILOMETERS_PER_HOUR,
)
except OpenMeteoError as err:
raise UpdateFailed("Open-Meteo API communication error") from err

View File

@ -43,7 +43,7 @@ def mock_open_meteo(request: pytest.FixtureRequest) -> Generator[MagicMock]:
forecast = Forecast.from_json(load_fixture(fixture, DOMAIN))
with patch(
"homeassistant.components.open_meteo.OpenMeteo", autospec=True
"homeassistant.components.open_meteo.coordinator.OpenMeteo", autospec=True
) as open_meteo_mock:
open_meteo = open_meteo_mock.return_value
open_meteo.forecast.return_value = forecast

View File

@ -33,7 +33,7 @@ async def test_load_unload_config_entry(
@patch(
"homeassistant.components.open_meteo.OpenMeteo.forecast",
"homeassistant.components.open_meteo.coordinator.OpenMeteo.forecast",
side_effect=OpenMeteoConnectionError,
)
async def test_config_entry_not_ready(