2019-02-13 20:21:14 +00:00
|
|
|
"""Support for alexa Smart Home Skill API."""
|
2024-03-08 18:15:59 +00:00
|
|
|
|
2017-09-16 19:35:28 +00:00
|
|
|
import logging
|
2023-08-08 09:48:50 +00:00
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
from aiohttp import web
|
|
|
|
from yarl import URL
|
2017-09-16 19:35:28 +00:00
|
|
|
|
2023-08-05 19:32:53 +00:00
|
|
|
from homeassistant import core
|
2023-08-08 09:48:50 +00:00
|
|
|
from homeassistant.auth.models import User
|
2024-03-07 17:09:20 +00:00
|
|
|
from homeassistant.components.http import (
|
|
|
|
KEY_HASS,
|
|
|
|
HomeAssistantRequest,
|
|
|
|
HomeAssistantView,
|
|
|
|
)
|
2023-08-05 19:32:53 +00:00
|
|
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
|
|
|
from homeassistant.core import Context, HomeAssistant
|
|
|
|
from homeassistant.helpers import entity_registry as er
|
|
|
|
from homeassistant.helpers.typing import ConfigType
|
2019-01-03 21:28:43 +00:00
|
|
|
|
2023-08-05 19:32:53 +00:00
|
|
|
from .auth import Auth
|
|
|
|
from .config import AbstractConfig
|
|
|
|
from .const import (
|
|
|
|
API_DIRECTIVE,
|
|
|
|
API_HEADER,
|
|
|
|
CONF_ENDPOINT,
|
|
|
|
CONF_ENTITY_CONFIG,
|
|
|
|
CONF_FILTER,
|
|
|
|
CONF_LOCALE,
|
|
|
|
EVENT_ALEXA_SMART_HOME,
|
|
|
|
)
|
2024-01-10 15:20:47 +00:00
|
|
|
from .diagnostics import async_redact_auth_data
|
2019-12-08 13:56:42 +00:00
|
|
|
from .errors import AlexaBridgeUnreachableError, AlexaError
|
2019-06-13 15:43:57 +00:00
|
|
|
from .handlers import HANDLERS
|
2023-08-05 19:32:53 +00:00
|
|
|
from .state_report import AlexaDirective
|
|
|
|
|
2019-06-13 15:43:57 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2023-08-08 09:48:50 +00:00
|
|
|
SMART_HOME_HTTP_ENDPOINT = "/api/alexa/smart_home"
|
2019-01-03 21:28:43 +00:00
|
|
|
|
2017-10-07 20:31:57 +00:00
|
|
|
|
2023-08-05 19:32:53 +00:00
|
|
|
class AlexaConfig(AbstractConfig):
|
|
|
|
"""Alexa config."""
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
_auth: Auth | None
|
|
|
|
|
|
|
|
def __init__(self, hass: HomeAssistant, config: ConfigType) -> None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Initialize Alexa config."""
|
|
|
|
super().__init__(hass)
|
|
|
|
self._config = config
|
|
|
|
|
|
|
|
if config.get(CONF_CLIENT_ID) and config.get(CONF_CLIENT_SECRET):
|
|
|
|
self._auth = Auth(hass, config[CONF_CLIENT_ID], config[CONF_CLIENT_SECRET])
|
|
|
|
else:
|
|
|
|
self._auth = None
|
|
|
|
|
|
|
|
@property
|
2023-08-08 09:48:50 +00:00
|
|
|
def supports_auth(self) -> bool:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Return if config supports auth."""
|
|
|
|
return self._auth is not None
|
|
|
|
|
|
|
|
@property
|
2023-08-08 09:48:50 +00:00
|
|
|
def should_report_state(self) -> bool:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Return if we should proactively report states."""
|
|
|
|
return self._auth is not None and self.authorized
|
|
|
|
|
|
|
|
@property
|
2023-08-08 09:48:50 +00:00
|
|
|
def endpoint(self) -> str | URL | None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Endpoint for report state."""
|
|
|
|
return self._config.get(CONF_ENDPOINT)
|
|
|
|
|
|
|
|
@property
|
2023-08-08 09:48:50 +00:00
|
|
|
def entity_config(self) -> dict[str, Any]:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Return entity config."""
|
|
|
|
return self._config.get(CONF_ENTITY_CONFIG) or {}
|
|
|
|
|
|
|
|
@property
|
2023-08-08 09:48:50 +00:00
|
|
|
def locale(self) -> str | None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Return config locale."""
|
|
|
|
return self._config.get(CONF_LOCALE)
|
|
|
|
|
|
|
|
@core.callback
|
2023-08-08 09:48:50 +00:00
|
|
|
def user_identifier(self) -> str:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Return an identifier for the user that represents this config."""
|
|
|
|
return ""
|
|
|
|
|
|
|
|
@core.callback
|
2023-08-08 09:48:50 +00:00
|
|
|
def should_expose(self, entity_id: str) -> bool:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""If an entity should be exposed."""
|
|
|
|
if not self._config[CONF_FILTER].empty_filter:
|
2023-08-08 15:15:25 +00:00
|
|
|
return bool(self._config[CONF_FILTER](entity_id))
|
2023-08-05 19:32:53 +00:00
|
|
|
|
|
|
|
entity_registry = er.async_get(self.hass)
|
|
|
|
if registry_entry := entity_registry.async_get(entity_id):
|
|
|
|
auxiliary_entity = (
|
|
|
|
registry_entry.entity_category is not None
|
|
|
|
or registry_entry.hidden_by is not None
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
auxiliary_entity = False
|
|
|
|
return not auxiliary_entity
|
|
|
|
|
|
|
|
@core.callback
|
2023-08-08 09:48:50 +00:00
|
|
|
def async_invalidate_access_token(self) -> None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Invalidate access token."""
|
2023-08-08 09:48:50 +00:00
|
|
|
assert self._auth is not None
|
2023-08-05 19:32:53 +00:00
|
|
|
self._auth.async_invalidate_access_token()
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
async def async_get_access_token(self) -> str | None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Get an access token."""
|
2023-08-08 09:48:50 +00:00
|
|
|
assert self._auth is not None
|
2023-08-05 19:32:53 +00:00
|
|
|
return await self._auth.async_get_access_token()
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
async def async_accept_grant(self, code: str) -> str | None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Accept a grant."""
|
2023-08-08 09:48:50 +00:00
|
|
|
assert self._auth is not None
|
2023-08-05 19:32:53 +00:00
|
|
|
return await self._auth.async_do_auth(code)
|
|
|
|
|
|
|
|
|
|
|
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> None:
|
|
|
|
"""Activate Smart Home functionality of Alexa component.
|
|
|
|
|
|
|
|
This is optional, triggered by having a `smart_home:` sub-section in the
|
|
|
|
alexa configuration.
|
|
|
|
|
|
|
|
Even if that's disabled, the functionality in this module may still be used
|
|
|
|
by the cloud component which will call async_handle_message directly.
|
|
|
|
"""
|
|
|
|
smart_home_config = AlexaConfig(hass, config)
|
|
|
|
await smart_home_config.async_initialize()
|
|
|
|
hass.http.register_view(SmartHomeView(smart_home_config))
|
|
|
|
|
|
|
|
if smart_home_config.should_report_state:
|
|
|
|
await smart_home_config.async_enable_proactive_mode()
|
|
|
|
|
|
|
|
|
|
|
|
class SmartHomeView(HomeAssistantView):
|
|
|
|
"""Expose Smart Home v3 payload interface via HTTP POST."""
|
|
|
|
|
|
|
|
url = SMART_HOME_HTTP_ENDPOINT
|
|
|
|
name = "api:alexa:smart_home"
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
def __init__(self, smart_home_config: AlexaConfig) -> None:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Initialize."""
|
|
|
|
self.smart_home_config = smart_home_config
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
async def post(self, request: HomeAssistantRequest) -> web.Response | bytes:
|
2023-08-05 19:32:53 +00:00
|
|
|
"""Handle Alexa Smart Home requests.
|
|
|
|
|
|
|
|
The Smart Home API requires the endpoint to be implemented in AWS
|
|
|
|
Lambda, which will need to forward the requests to here and pass back
|
|
|
|
the response.
|
|
|
|
"""
|
2024-03-07 17:09:20 +00:00
|
|
|
hass = request.app[KEY_HASS]
|
2023-08-08 09:48:50 +00:00
|
|
|
user: User = request["hass_user"]
|
|
|
|
message: dict[str, Any] = await request.json()
|
2023-08-05 19:32:53 +00:00
|
|
|
|
2024-01-10 15:20:47 +00:00
|
|
|
if _LOGGER.isEnabledFor(logging.DEBUG):
|
|
|
|
_LOGGER.debug(
|
|
|
|
"Received Alexa Smart Home request: %s",
|
|
|
|
async_redact_auth_data(message),
|
|
|
|
)
|
2023-08-05 19:32:53 +00:00
|
|
|
|
|
|
|
response = await async_handle_message(
|
|
|
|
hass, self.smart_home_config, message, context=core.Context(user_id=user.id)
|
|
|
|
)
|
2024-01-10 15:20:47 +00:00
|
|
|
if _LOGGER.isEnabledFor(logging.DEBUG):
|
|
|
|
_LOGGER.debug(
|
|
|
|
"Sending Alexa Smart Home response: %s",
|
|
|
|
async_redact_auth_data(response),
|
|
|
|
)
|
|
|
|
|
2023-08-05 19:32:53 +00:00
|
|
|
return b"" if response is None else self.json(response)
|
|
|
|
|
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
async def async_handle_message(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config: AbstractConfig,
|
|
|
|
request: dict[str, Any],
|
|
|
|
context: Context | None = None,
|
|
|
|
enabled: bool = True,
|
|
|
|
) -> dict[str, Any]:
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
"""Handle incoming API messages.
|
|
|
|
|
2022-01-17 13:22:04 +00:00
|
|
|
If enabled is False, the response to all messages will be a
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
BRIDGE_UNREACHABLE error. This can be used if the API has been disabled in
|
|
|
|
configuration.
|
2017-09-16 19:35:28 +00:00
|
|
|
"""
|
2019-07-31 19:25:30 +00:00
|
|
|
assert request[API_DIRECTIVE][API_HEADER]["payloadVersion"] == "3"
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
|
|
|
if context is None:
|
2023-08-05 19:32:53 +00:00
|
|
|
context = Context()
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
2019-06-13 15:43:57 +00:00
|
|
|
directive = AlexaDirective(request)
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
if not enabled:
|
2024-08-12 07:16:33 +00:00
|
|
|
raise AlexaBridgeUnreachableError( # noqa: TRY301
|
2019-07-31 19:25:30 +00:00
|
|
|
"Alexa API not enabled in Home Assistant configuration"
|
|
|
|
)
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
2022-01-17 17:14:26 +00:00
|
|
|
await config.set_authorized(True)
|
2022-01-13 17:47:31 +00:00
|
|
|
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
if directive.has_endpoint:
|
2023-05-03 10:39:22 +00:00
|
|
|
directive.load_entity(hass, config)
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
|
|
|
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(
|
2019-07-31 19:25:30 +00:00
|
|
|
"Unsupported API request %s/%s", directive.namespace, directive.name
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
)
|
|
|
|
response = directive.error()
|
2019-06-13 15:43:57 +00:00
|
|
|
except AlexaError as err:
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
response = directive.error(
|
2023-08-08 09:48:50 +00:00
|
|
|
error_type=str(err.error_type),
|
2022-01-31 23:01:46 +00:00
|
|
|
error_message=err.error_message,
|
|
|
|
payload=err.payload,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2024-05-07 12:00:27 +00:00
|
|
|
except Exception:
|
2022-01-31 23:01:46 +00:00
|
|
|
_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")
|
2018-03-30 06:49:08 +00:00
|
|
|
|
2023-08-08 09:48:50 +00:00
|
|
|
request_info: dict[str, Any] = {
|
|
|
|
"namespace": directive.namespace,
|
|
|
|
"name": directive.name,
|
|
|
|
}
|
2017-09-16 19:35:28 +00:00
|
|
|
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
if directive.has_endpoint:
|
2023-08-08 09:48:50 +00:00
|
|
|
assert directive.entity_id is not None
|
2019-07-31 19:25:30 +00:00
|
|
|
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,
|
|
|
|
)
|
Refactor Alexa API, fix thermostats (#17969)
* Refactor Alexa API to use objects for requests
This introduces _AlexaDirective to stand in for the previous model of passing
basic dict and list data structures to and from handlers. This gives a more
expressive platform for functionality common to most or all handlers.
I had two use cases in mind:
1) Most responses should include current properties. In the case of locks and
thermostats, the response must include the properties or Alexa will give the
user a vague error like "Hmm, $device is not responding." Locks currently work,
but thermostats do not. I wanted a way to automatically include properties in
all responses. This is implemented in a subsequent commit.
2) The previous model had a 1:1 mapping between Alexa endpoints and Home
Assistant entities. This works most of the time, but sometimes it's not so
great. For example, my Z-wave thermostat shows as three devices in Alexa: one
for the temperature sensor, one for the heat, and one for the AC. I'd like to
merge these into one device from Alexa's perspective. I believe this will be
facilitated with the `endpoint` attribute on `_AlexaDirective`.
* Include properties in all Alexa responses
The added _AlexaResponse class provides a richer vocabulary for handlers.
Among that vocabulary is .merge_context_properties(), which is invoked
automatically for any request directed at an endpoint. This adds all supported
properties to the response as recommended by the Alexa API docs, and in some
cases (locks, thermostats at least) the user will get an error "Hmm, $device is
not responding" if properties are not provided in the response.
* Fix setting temperature with Alexa thermostats
Fixes https://github.com/home-assistant/home-assistant/issues/16577
2018-10-30 02:16:35 +00:00
|
|
|
|
|
|
|
return response.serialize()
|