core/homeassistant/components/intent/__init__.py

88 lines
2.8 KiB
Python

"""The Intent integration."""
import asyncio
import logging
import voluptuous as vol
from homeassistant.core import HomeAssistant
from homeassistant.const import EVENT_COMPONENT_LOADED
from homeassistant.setup import ATTR_COMPONENT
from homeassistant.components import http
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.helpers import config_validation as cv, intent
from homeassistant.loader import async_get_integration, IntegrationNotFound
from .const import DOMAIN
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Intent component."""
hass.http.register_view(IntentHandleView())
tasks = [_async_process_intent(hass, comp) for comp in hass.config.components]
async def async_component_loaded(event):
"""Handle a new component loaded."""
await _async_process_intent(hass, event.data[ATTR_COMPONENT])
hass.bus.async_listen(EVENT_COMPONENT_LOADED, async_component_loaded)
if tasks:
await asyncio.gather(*tasks)
return True
async def _async_process_intent(hass: HomeAssistant, component_name: str):
"""Process the intents of a component."""
try:
integration = await async_get_integration(hass, component_name)
platform = integration.get_platform(DOMAIN)
except (IntegrationNotFound, ImportError):
return
try:
await platform.async_setup_intents(hass)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error setting up intents for %s", component_name)
class IntentHandleView(http.HomeAssistantView):
"""View to handle intents from JSON."""
url = "/api/intent/handle"
name = "api:intent:handle"
@RequestDataValidator(
vol.Schema(
{
vol.Required("name"): cv.string,
vol.Optional("data"): vol.Schema({cv.string: object}),
}
)
)
async def post(self, request, data):
"""Handle intent with name/data."""
hass = request.app["hass"]
try:
intent_name = data["name"]
slots = {
key: {"value": value} for key, value in data.get("data", {}).items()
}
intent_result = await intent.async_handle(
hass, DOMAIN, intent_name, slots, "", self.context(request)
)
except intent.IntentHandleError as err:
intent_result = intent.IntentResponse()
intent_result.async_set_speech(str(err))
if intent_result is None:
intent_result = intent.IntentResponse()
intent_result.async_set_speech("Sorry, I couldn't handle that")
return self.json(intent_result)