"""Services for Fritz integration.""" from __future__ import annotations import logging import voluptuous as vol from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.service import async_extract_config_entry_ids from .common import AvmWrapper from .const import ( DOMAIN, FRITZ_SERVICES, SERVICE_CLEANUP, SERVICE_REBOOT, SERVICE_RECONNECT, SERVICE_SET_GUEST_WIFI_PW, ) _LOGGER = logging.getLogger(__name__) SERVICE_SCHEMA_SET_GUEST_WIFI_PW = vol.Schema( { vol.Required("device_id"): str, vol.Optional("password"): vol.Length(min=8, max=63), vol.Optional("length"): vol.Range(min=8, max=63), } ) SERVICE_LIST: list[tuple[str, vol.Schema | None]] = [ (SERVICE_CLEANUP, None), (SERVICE_REBOOT, None), (SERVICE_RECONNECT, None), (SERVICE_SET_GUEST_WIFI_PW, SERVICE_SCHEMA_SET_GUEST_WIFI_PW), ] async def async_setup_services(hass: HomeAssistant) -> None: """Set up services for Fritz integration.""" for service, _ in SERVICE_LIST: if hass.services.has_service(DOMAIN, service): return async def async_call_fritz_service(service_call: ServiceCall) -> None: """Call correct Fritz service.""" if not ( fritzbox_entry_ids := await _async_get_configured_avm_device( hass, service_call ) ): raise HomeAssistantError( f"Failed to call service '{service_call.service}'. Config entry for target not found" ) for entry_id in fritzbox_entry_ids: _LOGGER.debug("Executing service %s", service_call.service) avm_wrapper: AvmWrapper = hass.data[DOMAIN][entry_id] if config_entry := hass.config_entries.async_get_entry(entry_id): await avm_wrapper.service_fritzbox(service_call, config_entry) else: _LOGGER.error( "Executing service %s failed, no config entry found", service_call.service, ) for service, schema in SERVICE_LIST: hass.services.async_register(DOMAIN, service, async_call_fritz_service, schema) async def _async_get_configured_avm_device( hass: HomeAssistant, service_call: ServiceCall ) -> list: """Get FritzBoxTools class from config entry.""" list_entry_id: list = [] for entry_id in await async_extract_config_entry_ids(hass, service_call): config_entry = hass.config_entries.async_get_entry(entry_id) if ( config_entry and config_entry.domain == DOMAIN and config_entry.state == ConfigEntryState.LOADED ): list_entry_id.append(entry_id) return list_entry_id async def async_unload_services(hass: HomeAssistant) -> None: """Unload services for Fritz integration.""" if not hass.data.get(FRITZ_SERVICES): return hass.data[FRITZ_SERVICES] = False for service, _ in SERVICE_LIST: hass.services.async_remove(DOMAIN, service)