"""Support for alexa Smart Home Skill API.""" import logging import homeassistant.core as ha from .const import API_DIRECTIVE, API_HEADER, EVENT_ALEXA_SMART_HOME from .errors import AlexaBridgeUnreachableError, AlexaError from .handlers import HANDLERS from .messages import AlexaDirective _LOGGER = logging.getLogger(__name__) async def async_handle_message(hass, config, request, context=None, enabled=True): """Handle incoming API messages. If enabled is False, the response to all messages will be a BRIDGE_UNREACHABLE error. This can be used if the API has been disabled in configuration. """ assert request[API_DIRECTIVE][API_HEADER]["payloadVersion"] == "3" if context is None: context = ha.Context() directive = AlexaDirective(request) try: if not enabled: raise AlexaBridgeUnreachableError( "Alexa API not enabled in Home Assistant configuration" ) await config.set_authorized(True) if directive.has_endpoint: directive.load_entity(hass, config) funct_ref = HANDLERS.get((directive.namespace, directive.name)) if funct_ref: response = await funct_ref(hass, config, directive, context) if directive.has_endpoint: response.merge_context_properties(directive.endpoint) else: _LOGGER.warning( "Unsupported API request %s/%s", directive.namespace, directive.name ) response = directive.error() except AlexaError as err: response = directive.error( error_type=err.error_type, error_message=err.error_message, payload=err.payload, ) except Exception: # pylint: disable=broad-except _LOGGER.exception( "Uncaught exception processing Alexa %s/%s request (%s)", directive.namespace, directive.name, directive.entity_id or "-", ) response = directive.error(error_message="Unknown error") request_info = {"namespace": directive.namespace, "name": directive.name} if directive.has_endpoint: request_info["entity_id"] = directive.entity_id hass.bus.async_fire( EVENT_ALEXA_SMART_HOME, { "request": request_info, "response": {"namespace": response.namespace, "name": response.name}, }, context=context, ) return response.serialize()