101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
"""Handle intents with scripts."""
|
|
import asyncio
|
|
import copy
|
|
import logging
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.helpers import (
|
|
intent, template, script, config_validation as cv)
|
|
|
|
DOMAIN = 'intent_script'
|
|
|
|
CONF_INTENTS = 'intents'
|
|
CONF_SPEECH = 'speech'
|
|
|
|
CONF_ACTION = 'action'
|
|
CONF_CARD = 'card'
|
|
CONF_TYPE = 'type'
|
|
CONF_TITLE = 'title'
|
|
CONF_CONTENT = 'content'
|
|
CONF_TEXT = 'text'
|
|
CONF_ASYNC_ACTION = 'async_action'
|
|
|
|
DEFAULT_CONF_ASYNC_ACTION = False
|
|
|
|
CONFIG_SCHEMA = vol.Schema({
|
|
DOMAIN: {
|
|
cv.string: {
|
|
vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA,
|
|
vol.Optional(CONF_ASYNC_ACTION,
|
|
default=DEFAULT_CONF_ASYNC_ACTION): cv.boolean,
|
|
vol.Optional(CONF_CARD): {
|
|
vol.Optional(CONF_TYPE, default='simple'): cv.string,
|
|
vol.Required(CONF_TITLE): cv.template,
|
|
vol.Required(CONF_CONTENT): cv.template,
|
|
},
|
|
vol.Optional(CONF_SPEECH): {
|
|
vol.Optional(CONF_TYPE, default='plain'): cv.string,
|
|
vol.Required(CONF_TEXT): cv.template,
|
|
}
|
|
}
|
|
}
|
|
}, extra=vol.ALLOW_EXTRA)
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def async_setup(hass, config):
|
|
"""Activate Alexa component."""
|
|
intents = copy.deepcopy(config[DOMAIN])
|
|
template.attach(hass, intents)
|
|
|
|
for intent_type, conf in intents.items():
|
|
if CONF_ACTION in conf:
|
|
conf[CONF_ACTION] = script.Script(
|
|
hass, conf[CONF_ACTION],
|
|
"Intent Script {}".format(intent_type))
|
|
intent.async_register(hass, ScriptIntentHandler(intent_type, conf))
|
|
|
|
return True
|
|
|
|
|
|
class ScriptIntentHandler(intent.IntentHandler):
|
|
"""Respond to an intent with a script."""
|
|
|
|
def __init__(self, intent_type, config):
|
|
"""Initialize the script intent handler."""
|
|
self.intent_type = intent_type
|
|
self.config = config
|
|
|
|
@asyncio.coroutine
|
|
def async_handle(self, intent_obj):
|
|
"""Handle the intent."""
|
|
speech = self.config.get(CONF_SPEECH)
|
|
card = self.config.get(CONF_CARD)
|
|
action = self.config.get(CONF_ACTION)
|
|
is_async_action = self.config.get(CONF_ASYNC_ACTION)
|
|
slots = {key: value['value'] for key, value
|
|
in intent_obj.slots.items()}
|
|
|
|
if action is not None:
|
|
if is_async_action:
|
|
intent_obj.hass.async_add_job(action.async_run(slots))
|
|
else:
|
|
yield from action.async_run(slots)
|
|
|
|
response = intent_obj.create_response()
|
|
|
|
if speech is not None:
|
|
response.async_set_speech(speech[CONF_TEXT].async_render(slots),
|
|
speech[CONF_TYPE])
|
|
|
|
if card is not None:
|
|
response.async_set_card(
|
|
card[CONF_TITLE].async_render(slots),
|
|
card[CONF_CONTENT].async_render(slots),
|
|
card[CONF_TYPE])
|
|
|
|
return response
|