88 lines
2.8 KiB
Python
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)
|