1 """Implement the services discovery feature from Hass.io for Add-ons."""
3 from __future__
import annotations
10 from aiohasupervisor
import SupervisorError
11 from aiohasupervisor.models
import Discovery
12 from aiohttp
import web
13 from aiohttp.web_exceptions
import HTTPServiceUnavailable
15 from homeassistant
import config_entries
23 from .const
import ATTR_ADDON, ATTR_UUID, DOMAIN
24 from .handler
import HassIO, get_supervisor_client
26 _LOGGER = logging.getLogger(__name__)
31 """Discovery setup."""
34 hass.http.register_view(hassio_discovery)
37 async
def _async_discovery_start_handler(event: Event) ->
None:
38 """Process all exists discovery on startup."""
40 data = await supervisor_client.discovery.list()
41 except SupervisorError
as err:
42 _LOGGER.error(
"Can't read discover info: %s", err)
46 asyncio.create_task(hassio_discovery.async_process_new(discovery))
50 await asyncio.wait(jobs)
52 hass.bus.async_listen_once(
53 EVENT_HOMEASSISTANT_START, _async_discovery_start_handler
56 async
def _handle_config_entry_removed(
57 entry: config_entries.ConfigEntry,
59 """Handle config entry changes."""
60 for disc_key
in entry.discovery_keys[DOMAIN]:
61 if disc_key.version != 1
or not isinstance(key := disc_key.key, str):
64 _LOGGER.debug(
"Rediscover addon %s", uuid)
65 await hassio_discovery.async_rediscover(uuid)
69 config_entries.signal_discovered_config_entry_removed(DOMAIN),
70 _handle_config_entry_removed,
75 """Hass.io view to handle base part."""
77 name =
"api:hassio_push:discovery"
78 url =
"/api/hassio_push/discovery/{uuid}"
80 def __init__(self, hass: HomeAssistant, hassio: HassIO) ->
None:
81 """Initialize WebView."""
86 async
def post(self, request: web.Request, uuid: str) -> web.Response:
87 """Handle new discovery requests."""
91 except SupervisorError
as err:
92 _LOGGER.error(
"Can't read discovery data: %s", err)
93 raise HTTPServiceUnavailable
from None
98 async
def delete(self, request: web.Request, uuid: str) -> web.Response:
99 """Handle remove discovery requests."""
100 data: dict[str, Any] = await request.json()
103 return web.Response()
106 """Rediscover add-on when config entry is removed."""
109 except SupervisorError
as err:
110 _LOGGER.debug(
"Can't read discovery data: %s", err)
115 """Process add discovery entry."""
118 addon_info = await self.
_supervisor_client_supervisor_client.addons.addon_info(data.addon)
119 except SupervisorError
as err:
120 _LOGGER.error(
"Can't read add-on info: %s", err)
123 data.config[ATTR_ADDON] = addon_info.name
126 discovery_flow.async_create_flow(
129 context={
"source": config_entries.SOURCE_HASSIO},
132 name=addon_info.name,
136 discovery_key=discovery_flow.DiscoveryKey(
144 """Process remove discovery entry."""
145 service: str = data[ATTR_SERVICE]
146 uuid: str = data[ATTR_UUID]
151 except SupervisorError:
154 _LOGGER.warning(
"Retrieve wrong unload for %s", service)
158 for entry
in self.
hasshass.config_entries.async_entries(service):
159 if entry.source != config_entries.SOURCE_HASSIO
or entry.unique_id != uuid:
161 await self.
hasshass.config_entries.async_remove(entry.entry_id)
None async_process_del(self, dict[str, Any] data)
web.Response delete(self, web.Request request, str uuid)
None async_process_new(self, Discovery data)
None __init__(self, HomeAssistant hass, HassIO hassio)
web.Response post(self, web.Request request, str uuid)
None async_rediscover(self, str uuid)
None async_setup_discovery_view(HomeAssistant hass, HassIO hassio)
SupervisorClient get_supervisor_client(HomeAssistant hass)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)