mirror of
https://github.com/home-assistant/core.git
synced 2026-07-06 22:36:33 +01:00
68757996de
Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
108 lines
3.4 KiB
Python
108 lines
3.4 KiB
Python
"""Services for the Google Air Quality integration."""
|
|
|
|
from datetime import timedelta
|
|
from typing import Final, cast
|
|
|
|
from google_air_quality_api.exceptions import GoogleAirQualityApiError
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import ATTR_DEVICE_ID
|
|
from homeassistant.core import (
|
|
HomeAssistant,
|
|
ServiceCall,
|
|
ServiceResponse,
|
|
SupportsResponse,
|
|
callback,
|
|
)
|
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
|
from homeassistant.helpers import device_registry as dr, selector
|
|
|
|
from .const import DOMAIN
|
|
from .coordinator import GoogleAirQualityConfigEntry
|
|
|
|
ATTR_HOURS: Final = "hours"
|
|
|
|
FORECAST_HOURS_MAX: Final = 96
|
|
|
|
SERVICE_GET_FORECAST: Final = "get_forecast"
|
|
|
|
SERVICE_GET_FORECAST_SCHEMA: Final = vol.Schema(
|
|
{
|
|
vol.Required(ATTR_DEVICE_ID): selector.DeviceSelector({"integration": DOMAIN}),
|
|
vol.Required(ATTR_HOURS): vol.All(
|
|
vol.Coerce(int), vol.Range(min=1, max=FORECAST_HOURS_MAX)
|
|
),
|
|
}
|
|
)
|
|
|
|
|
|
def _get_config_entry_and_subentry_id(
|
|
hass: HomeAssistant, device_id: str
|
|
) -> tuple[GoogleAirQualityConfigEntry, str]:
|
|
"""Get the config entry and subentry from a selected location device."""
|
|
device = dr.async_get(hass).async_get(device_id)
|
|
if device is not None:
|
|
for entry_id, subentry_ids in device.config_entries_subentries.items():
|
|
config_entry: ConfigEntry | None = hass.config_entries.async_get_entry(
|
|
entry_id
|
|
)
|
|
if config_entry is None or config_entry.domain != DOMAIN:
|
|
continue
|
|
|
|
gaq_config_entry = cast(GoogleAirQualityConfigEntry, config_entry)
|
|
for subentry_id in subentry_ids:
|
|
if (
|
|
subentry_id is not None
|
|
and subentry_id
|
|
in gaq_config_entry.runtime_data.subentries_runtime_data
|
|
):
|
|
return gaq_config_entry, subentry_id
|
|
|
|
raise ServiceValidationError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="device_not_found",
|
|
)
|
|
|
|
|
|
async def _async_get_forecast(call: ServiceCall) -> ServiceResponse:
|
|
"""Fetch the air quality forecast for a configured location."""
|
|
config_entry, subentry_id = _get_config_entry_and_subentry_id(
|
|
call.hass, call.data[ATTR_DEVICE_ID]
|
|
)
|
|
|
|
coordinator = config_entry.runtime_data.subentries_runtime_data[subentry_id]
|
|
|
|
try:
|
|
forecast = await config_entry.runtime_data.api.async_get_forecast(
|
|
coordinator.lat,
|
|
coordinator.long,
|
|
timedelta(hours=call.data[ATTR_HOURS]),
|
|
)
|
|
except GoogleAirQualityApiError as err:
|
|
raise HomeAssistantError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="unable_to_fetch",
|
|
) from err
|
|
|
|
return cast(
|
|
ServiceResponse,
|
|
{
|
|
"forecast_time": forecast.hourly_forecasts[0].date_time,
|
|
"indexes": forecast.hourly_forecasts[0].indexes,
|
|
"pollutants": forecast.hourly_forecasts[0].pollutants,
|
|
},
|
|
)
|
|
|
|
|
|
@callback
|
|
def async_setup_services(hass: HomeAssistant) -> None:
|
|
"""Set up services."""
|
|
hass.services.async_register(
|
|
DOMAIN,
|
|
SERVICE_GET_FORECAST,
|
|
_async_get_forecast,
|
|
schema=SERVICE_GET_FORECAST_SCHEMA,
|
|
supports_response=SupportsResponse.ONLY,
|
|
)
|