mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Alexa typing part 2 (#97911)
* Alexa typing part 2 * Update homeassistant/components/alexa/intent.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Missed type hints * precision * Follow up comment * value * revert abstract class changes * raise NotImplementedError() --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
c8256d1d3d
commit
5657cfa052
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Generator, Iterable
|
from collections.abc import Generator, Iterable
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from homeassistant.components import (
|
from homeassistant.components import (
|
||||||
alarm_control_panel,
|
alarm_control_panel,
|
||||||
@ -274,22 +274,22 @@ class AlexaEntity:
|
|||||||
self.entity_conf = config.entity_config.get(entity.entity_id, {})
|
self.entity_conf = config.entity_config.get(entity.entity_id, {})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entity_id(self):
|
def entity_id(self) -> str:
|
||||||
"""Return the Entity ID."""
|
"""Return the Entity ID."""
|
||||||
return self.entity.entity_id
|
return self.entity.entity_id
|
||||||
|
|
||||||
def friendly_name(self):
|
def friendly_name(self) -> str:
|
||||||
"""Return the Alexa API friendly name."""
|
"""Return the Alexa API friendly name."""
|
||||||
return self.entity_conf.get(CONF_NAME, self.entity.name).translate(
|
return self.entity_conf.get(CONF_NAME, self.entity.name).translate(
|
||||||
TRANSLATION_TABLE
|
TRANSLATION_TABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
def description(self):
|
def description(self) -> str:
|
||||||
"""Return the Alexa API description."""
|
"""Return the Alexa API description."""
|
||||||
description = self.entity_conf.get(CONF_DESCRIPTION) or self.entity_id
|
description = self.entity_conf.get(CONF_DESCRIPTION) or self.entity_id
|
||||||
return f"{description} via Home Assistant".translate(TRANSLATION_TABLE)
|
return f"{description} via Home Assistant".translate(TRANSLATION_TABLE)
|
||||||
|
|
||||||
def alexa_id(self):
|
def alexa_id(self) -> str:
|
||||||
"""Return the Alexa API entity id."""
|
"""Return the Alexa API entity id."""
|
||||||
return generate_alexa_id(self.entity.entity_id)
|
return generate_alexa_id(self.entity.entity_id)
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ class AlexaEntity:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def serialize_properties(self):
|
def serialize_properties(self) -> Generator[dict[str, Any], None, None]:
|
||||||
"""Yield each supported property in API format."""
|
"""Yield each supported property in API format."""
|
||||||
for interface in self.interfaces():
|
for interface in self.interfaces():
|
||||||
if not interface.properties_proactively_reported():
|
if not interface.properties_proactively_reported():
|
||||||
@ -325,9 +325,9 @@ class AlexaEntity:
|
|||||||
|
|
||||||
yield from interface.serialize_properties()
|
yield from interface.serialize_properties()
|
||||||
|
|
||||||
def serialize_discovery(self):
|
def serialize_discovery(self) -> dict[str, Any]:
|
||||||
"""Serialize the entity for discovery."""
|
"""Serialize the entity for discovery."""
|
||||||
result = {
|
result: dict[str, Any] = {
|
||||||
"displayCategories": self.display_categories(),
|
"displayCategories": self.display_categories(),
|
||||||
"cookie": {},
|
"cookie": {},
|
||||||
"endpointId": self.alexa_id(),
|
"endpointId": self.alexa_id(),
|
||||||
@ -366,7 +366,7 @@ def async_get_entities(
|
|||||||
hass: HomeAssistant, config: AbstractConfig
|
hass: HomeAssistant, config: AbstractConfig
|
||||||
) -> list[AlexaEntity]:
|
) -> list[AlexaEntity]:
|
||||||
"""Return all entities that are supported by Alexa."""
|
"""Return all entities that are supported by Alexa."""
|
||||||
entities = []
|
entities: list[AlexaEntity] = []
|
||||||
for state in hass.states.async_all():
|
for state in hass.states.async_all():
|
||||||
if state.entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
if state.entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||||
continue
|
continue
|
||||||
|
@ -3,8 +3,10 @@ import enum
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from aiohttp.web import Response
|
||||||
|
|
||||||
from homeassistant.components import http
|
from homeassistant.components import http
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import intent
|
from homeassistant.helpers import intent
|
||||||
from homeassistant.util.decorator import Registry
|
from homeassistant.util.decorator import Registry
|
||||||
@ -18,7 +20,7 @@ HANDLERS = Registry() # type: ignore[var-annotated]
|
|||||||
INTENTS_API_ENDPOINT = "/api/alexa"
|
INTENTS_API_ENDPOINT = "/api/alexa"
|
||||||
|
|
||||||
|
|
||||||
class SpeechType(enum.Enum):
|
class SpeechType(enum.StrEnum):
|
||||||
"""The Alexa speech types."""
|
"""The Alexa speech types."""
|
||||||
|
|
||||||
plaintext = "PlainText"
|
plaintext = "PlainText"
|
||||||
@ -28,7 +30,7 @@ class SpeechType(enum.Enum):
|
|||||||
SPEECH_MAPPINGS = {"plain": SpeechType.plaintext, "ssml": SpeechType.ssml}
|
SPEECH_MAPPINGS = {"plain": SpeechType.plaintext, "ssml": SpeechType.ssml}
|
||||||
|
|
||||||
|
|
||||||
class CardType(enum.Enum):
|
class CardType(enum.StrEnum):
|
||||||
"""The Alexa card types."""
|
"""The Alexa card types."""
|
||||||
|
|
||||||
simple = "Simple"
|
simple = "Simple"
|
||||||
@ -36,12 +38,12 @@ class CardType(enum.Enum):
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_setup(hass):
|
def async_setup(hass: HomeAssistant) -> None:
|
||||||
"""Activate Alexa component."""
|
"""Activate Alexa component."""
|
||||||
hass.http.register_view(AlexaIntentsView)
|
hass.http.register_view(AlexaIntentsView)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_intents(hass):
|
async def async_setup_intents(hass: HomeAssistant) -> None:
|
||||||
"""Do intents setup.
|
"""Do intents setup.
|
||||||
|
|
||||||
Right now this module does not expose any, but the intent component breaks
|
Right now this module does not expose any, but the intent component breaks
|
||||||
@ -60,15 +62,15 @@ class AlexaIntentsView(http.HomeAssistantView):
|
|||||||
url = INTENTS_API_ENDPOINT
|
url = INTENTS_API_ENDPOINT
|
||||||
name = "api:alexa"
|
name = "api:alexa"
|
||||||
|
|
||||||
async def post(self, request):
|
async def post(self, request: http.HomeAssistantRequest) -> Response | bytes:
|
||||||
"""Handle Alexa."""
|
"""Handle Alexa."""
|
||||||
hass = request.app["hass"]
|
hass: HomeAssistant = request.app["hass"]
|
||||||
message = await request.json()
|
message: dict[str, Any] = await request.json()
|
||||||
|
|
||||||
_LOGGER.debug("Received Alexa request: %s", message)
|
_LOGGER.debug("Received Alexa request: %s", message)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await async_handle_message(hass, message)
|
response: dict[str, Any] = await async_handle_message(hass, message)
|
||||||
return b"" if response is None else self.json(response)
|
return b"" if response is None else self.json(response)
|
||||||
except UnknownRequest as err:
|
except UnknownRequest as err:
|
||||||
_LOGGER.warning(str(err))
|
_LOGGER.warning(str(err))
|
||||||
@ -99,15 +101,19 @@ class AlexaIntentsView(http.HomeAssistantView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def intent_error_response(hass, message, error):
|
def intent_error_response(
|
||||||
|
hass: HomeAssistant, message: dict[str, Any], error: str
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Return an Alexa response that will speak the error message."""
|
"""Return an Alexa response that will speak the error message."""
|
||||||
alexa_intent_info = message.get("request").get("intent")
|
alexa_intent_info = message["request"].get("intent")
|
||||||
alexa_response = AlexaResponse(hass, alexa_intent_info)
|
alexa_response = AlexaIntentResponse(hass, alexa_intent_info)
|
||||||
alexa_response.add_speech(SpeechType.plaintext, error)
|
alexa_response.add_speech(SpeechType.plaintext, error)
|
||||||
return alexa_response.as_dict()
|
return alexa_response.as_dict()
|
||||||
|
|
||||||
|
|
||||||
async def async_handle_message(hass, message):
|
async def async_handle_message(
|
||||||
|
hass: HomeAssistant, message: dict[str, Any]
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Handle an Alexa intent.
|
"""Handle an Alexa intent.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@ -117,7 +123,7 @@ async def async_handle_message(hass, message):
|
|||||||
- intent.IntentError
|
- intent.IntentError
|
||||||
|
|
||||||
"""
|
"""
|
||||||
req = message.get("request")
|
req = message["request"]
|
||||||
req_type = req["type"]
|
req_type = req["type"]
|
||||||
|
|
||||||
if not (handler := HANDLERS.get(req_type)):
|
if not (handler := HANDLERS.get(req_type)):
|
||||||
@ -129,7 +135,9 @@ async def async_handle_message(hass, message):
|
|||||||
@HANDLERS.register("SessionEndedRequest")
|
@HANDLERS.register("SessionEndedRequest")
|
||||||
@HANDLERS.register("IntentRequest")
|
@HANDLERS.register("IntentRequest")
|
||||||
@HANDLERS.register("LaunchRequest")
|
@HANDLERS.register("LaunchRequest")
|
||||||
async def async_handle_intent(hass, message):
|
async def async_handle_intent(
|
||||||
|
hass: HomeAssistant, message: dict[str, Any]
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Handle an intent request.
|
"""Handle an intent request.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@ -138,9 +146,9 @@ async def async_handle_intent(hass, message):
|
|||||||
- intent.IntentError
|
- intent.IntentError
|
||||||
|
|
||||||
"""
|
"""
|
||||||
req = message.get("request")
|
req = message["request"]
|
||||||
alexa_intent_info = req.get("intent")
|
alexa_intent_info = req.get("intent")
|
||||||
alexa_response = AlexaResponse(hass, alexa_intent_info)
|
alexa_response = AlexaIntentResponse(hass, alexa_intent_info)
|
||||||
|
|
||||||
if req["type"] == "LaunchRequest":
|
if req["type"] == "LaunchRequest":
|
||||||
intent_name = (
|
intent_name = (
|
||||||
@ -187,7 +195,7 @@ def resolve_slot_data(key: str, request: dict[str, Any]) -> dict[str, str]:
|
|||||||
# passes the id and name of the nearest possible slot resolution. For
|
# passes the id and name of the nearest possible slot resolution. For
|
||||||
# reference to the request object structure, see the Alexa docs:
|
# reference to the request object structure, see the Alexa docs:
|
||||||
# https://tinyurl.com/ybvm7jhs
|
# https://tinyurl.com/ybvm7jhs
|
||||||
resolved_data = {}
|
resolved_data: dict[str, Any] = {}
|
||||||
resolved_data["value"] = request["value"]
|
resolved_data["value"] = request["value"]
|
||||||
resolved_data["id"] = ""
|
resolved_data["id"] = ""
|
||||||
|
|
||||||
@ -226,18 +234,18 @@ def resolve_slot_data(key: str, request: dict[str, Any]) -> dict[str, str]:
|
|||||||
return resolved_data
|
return resolved_data
|
||||||
|
|
||||||
|
|
||||||
class AlexaResponse:
|
class AlexaIntentResponse:
|
||||||
"""Help generating the response for Alexa."""
|
"""Help generating the response for Alexa."""
|
||||||
|
|
||||||
def __init__(self, hass, intent_info):
|
def __init__(self, hass: HomeAssistant, intent_info: dict[str, Any] | None) -> None:
|
||||||
"""Initialize the response."""
|
"""Initialize the response."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.speech = None
|
self.speech: dict[str, Any] | None = None
|
||||||
self.card = None
|
self.card: dict[str, Any] | None = None
|
||||||
self.reprompt = None
|
self.reprompt: dict[str, Any] | None = None
|
||||||
self.session_attributes = {}
|
self.session_attributes: dict[str, Any] = {}
|
||||||
self.should_end_session = True
|
self.should_end_session = True
|
||||||
self.variables = {}
|
self.variables: dict[str, Any] = {}
|
||||||
|
|
||||||
# Intent is None if request was a LaunchRequest or SessionEndedRequest
|
# Intent is None if request was a LaunchRequest or SessionEndedRequest
|
||||||
if intent_info is not None:
|
if intent_info is not None:
|
||||||
@ -252,7 +260,7 @@ class AlexaResponse:
|
|||||||
self.variables[_key] = _slot_data["value"]
|
self.variables[_key] = _slot_data["value"]
|
||||||
self.variables[_key + "_Id"] = _slot_data["id"]
|
self.variables[_key + "_Id"] = _slot_data["id"]
|
||||||
|
|
||||||
def add_card(self, card_type, title, content):
|
def add_card(self, card_type: CardType, title: str, content: str) -> None:
|
||||||
"""Add a card to the response."""
|
"""Add a card to the response."""
|
||||||
assert self.card is None
|
assert self.card is None
|
||||||
|
|
||||||
@ -266,7 +274,7 @@ class AlexaResponse:
|
|||||||
card["content"] = content
|
card["content"] = content
|
||||||
self.card = card
|
self.card = card
|
||||||
|
|
||||||
def add_speech(self, speech_type, text):
|
def add_speech(self, speech_type: SpeechType, text: str) -> None:
|
||||||
"""Add speech to the response."""
|
"""Add speech to the response."""
|
||||||
assert self.speech is None
|
assert self.speech is None
|
||||||
|
|
||||||
@ -274,7 +282,7 @@ class AlexaResponse:
|
|||||||
|
|
||||||
self.speech = {"type": speech_type.value, key: text}
|
self.speech = {"type": speech_type.value, key: text}
|
||||||
|
|
||||||
def add_reprompt(self, speech_type, text):
|
def add_reprompt(self, speech_type: SpeechType, text) -> None:
|
||||||
"""Add reprompt if user does not answer."""
|
"""Add reprompt if user does not answer."""
|
||||||
assert self.reprompt is None
|
assert self.reprompt is None
|
||||||
|
|
||||||
@ -284,9 +292,9 @@ class AlexaResponse:
|
|||||||
|
|
||||||
self.reprompt = {"type": speech_type.value, key: text}
|
self.reprompt = {"type": speech_type.value, key: text}
|
||||||
|
|
||||||
def as_dict(self):
|
def as_dict(self) -> dict[str, Any]:
|
||||||
"""Return response in an Alexa valid dict."""
|
"""Return response in an Alexa valid dict."""
|
||||||
response = {"shouldEndSession": self.should_end_session}
|
response: dict[str, Any] = {"shouldEndSession": self.should_end_session}
|
||||||
|
|
||||||
if self.card is not None:
|
if self.card is not None:
|
||||||
response["card"] = self.card
|
response["card"] = self.card
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
"""Alexa Resources and Assets."""
|
"""Alexa Resources and Assets."""
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
class AlexaGlobalCatalog:
|
class AlexaGlobalCatalog:
|
||||||
"""The Global Alexa catalog.
|
"""The Global Alexa catalog.
|
||||||
|
|
||||||
@ -207,36 +210,40 @@ class AlexaCapabilityResource:
|
|||||||
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#capability-resources
|
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#capability-resources
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, labels):
|
def __init__(self, labels: list[str]) -> None:
|
||||||
"""Initialize an Alexa resource."""
|
"""Initialize an Alexa resource."""
|
||||||
self._resource_labels = []
|
self._resource_labels = []
|
||||||
for label in labels:
|
for label in labels:
|
||||||
self._resource_labels.append(label)
|
self._resource_labels.append(label)
|
||||||
|
|
||||||
def serialize_capability_resources(self):
|
def serialize_capability_resources(self) -> dict[str, list[dict[str, Any]]]:
|
||||||
"""Return capabilityResources object serialized for an API response."""
|
"""Return capabilityResources object serialized for an API response."""
|
||||||
return self.serialize_labels(self._resource_labels)
|
return self.serialize_labels(self._resource_labels)
|
||||||
|
|
||||||
def serialize_configuration(self):
|
def serialize_configuration(self) -> dict[str, Any]:
|
||||||
"""Return serialized configuration for an API response.
|
"""Return serialized configuration for an API response.
|
||||||
|
|
||||||
Return ModeResources, PresetResources friendlyNames serialized.
|
Return ModeResources, PresetResources friendlyNames serialized.
|
||||||
"""
|
"""
|
||||||
return []
|
raise NotImplementedError()
|
||||||
|
|
||||||
def serialize_labels(self, resources):
|
def serialize_labels(self, resources: list[str]) -> dict[str, list[dict[str, Any]]]:
|
||||||
"""Return serialized labels for an API response.
|
"""Return serialized labels for an API response.
|
||||||
|
|
||||||
Returns resource label objects for friendlyNames serialized.
|
Returns resource label objects for friendlyNames serialized.
|
||||||
"""
|
"""
|
||||||
labels = []
|
labels: list[dict[str, Any]] = []
|
||||||
|
label_dict: dict[str, Any]
|
||||||
for label in resources:
|
for label in resources:
|
||||||
if label in AlexaGlobalCatalog.__dict__.values():
|
if label in AlexaGlobalCatalog.__dict__.values():
|
||||||
label = {"@type": "asset", "value": {"assetId": label}}
|
label_dict = {"@type": "asset", "value": {"assetId": label}}
|
||||||
else:
|
else:
|
||||||
label = {"@type": "text", "value": {"text": label, "locale": "en-US"}}
|
label_dict = {
|
||||||
|
"@type": "text",
|
||||||
|
"value": {"text": label, "locale": "en-US"},
|
||||||
|
}
|
||||||
|
|
||||||
labels.append(label)
|
labels.append(label_dict)
|
||||||
|
|
||||||
return {"friendlyNames": labels}
|
return {"friendlyNames": labels}
|
||||||
|
|
||||||
@ -247,22 +254,22 @@ class AlexaModeResource(AlexaCapabilityResource):
|
|||||||
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#capability-resources
|
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#capability-resources
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, labels, ordered=False):
|
def __init__(self, labels: list[str], ordered: bool = False) -> None:
|
||||||
"""Initialize an Alexa modeResource."""
|
"""Initialize an Alexa modeResource."""
|
||||||
super().__init__(labels)
|
super().__init__(labels)
|
||||||
self._supported_modes = []
|
self._supported_modes: list[dict[str, Any]] = []
|
||||||
self._mode_ordered = ordered
|
self._mode_ordered: bool = ordered
|
||||||
|
|
||||||
def add_mode(self, value, labels):
|
def add_mode(self, value: str, labels: list[str]) -> None:
|
||||||
"""Add mode to the supportedModes object."""
|
"""Add mode to the supportedModes object."""
|
||||||
self._supported_modes.append({"value": value, "labels": labels})
|
self._supported_modes.append({"value": value, "labels": labels})
|
||||||
|
|
||||||
def serialize_configuration(self):
|
def serialize_configuration(self) -> dict[str, Any]:
|
||||||
"""Return serialized configuration for an API response.
|
"""Return serialized configuration for an API response.
|
||||||
|
|
||||||
Returns configuration for ModeResources friendlyNames serialized.
|
Returns configuration for ModeResources friendlyNames serialized.
|
||||||
"""
|
"""
|
||||||
mode_resources = []
|
mode_resources: list[dict[str, Any]] = []
|
||||||
for mode in self._supported_modes:
|
for mode in self._supported_modes:
|
||||||
result = {
|
result = {
|
||||||
"value": mode["value"],
|
"value": mode["value"],
|
||||||
@ -282,10 +289,17 @@ class AlexaPresetResource(AlexaCapabilityResource):
|
|||||||
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#presetresources
|
https://developer.amazon.com/docs/device-apis/resources-and-assets.html#presetresources
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, labels, min_value, max_value, precision, unit=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
labels: list[str],
|
||||||
|
min_value: int | float,
|
||||||
|
max_value: int | float,
|
||||||
|
precision: int | float,
|
||||||
|
unit: str | None = None,
|
||||||
|
) -> None:
|
||||||
"""Initialize an Alexa presetResource."""
|
"""Initialize an Alexa presetResource."""
|
||||||
super().__init__(labels)
|
super().__init__(labels)
|
||||||
self._presets = []
|
self._presets: list[dict[str, Any]] = []
|
||||||
self._minimum_value = min_value
|
self._minimum_value = min_value
|
||||||
self._maximum_value = max_value
|
self._maximum_value = max_value
|
||||||
self._precision = precision
|
self._precision = precision
|
||||||
@ -293,16 +307,16 @@ class AlexaPresetResource(AlexaCapabilityResource):
|
|||||||
if unit in AlexaGlobalCatalog.__dict__.values():
|
if unit in AlexaGlobalCatalog.__dict__.values():
|
||||||
self._unit_of_measure = unit
|
self._unit_of_measure = unit
|
||||||
|
|
||||||
def add_preset(self, value, labels):
|
def add_preset(self, value: int | float, labels: list[str]) -> None:
|
||||||
"""Add preset to configuration presets array."""
|
"""Add preset to configuration presets array."""
|
||||||
self._presets.append({"value": value, "labels": labels})
|
self._presets.append({"value": value, "labels": labels})
|
||||||
|
|
||||||
def serialize_configuration(self):
|
def serialize_configuration(self) -> dict[str, Any]:
|
||||||
"""Return serialized configuration for an API response.
|
"""Return serialized configuration for an API response.
|
||||||
|
|
||||||
Returns configuration for PresetResources friendlyNames serialized.
|
Returns configuration for PresetResources friendlyNames serialized.
|
||||||
"""
|
"""
|
||||||
configuration = {
|
configuration: dict[str, Any] = {
|
||||||
"supportedRange": {
|
"supportedRange": {
|
||||||
"minimumValue": self._minimum_value,
|
"minimumValue": self._minimum_value,
|
||||||
"maximumValue": self._maximum_value,
|
"maximumValue": self._maximum_value,
|
||||||
@ -372,26 +386,28 @@ class AlexaSemantics:
|
|||||||
DIRECTIVE_MODE_SET_MODE = "SetMode"
|
DIRECTIVE_MODE_SET_MODE = "SetMode"
|
||||||
DIRECTIVE_MODE_ADJUST_MODE = "AdjustMode"
|
DIRECTIVE_MODE_ADJUST_MODE = "AdjustMode"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
"""Initialize an Alexa modeResource."""
|
"""Initialize an Alexa modeResource."""
|
||||||
self._action_mappings = []
|
self._action_mappings: list[dict[str, Any]] = []
|
||||||
self._state_mappings = []
|
self._state_mappings: list[dict[str, Any]] = []
|
||||||
|
|
||||||
def _add_action_mapping(self, semantics):
|
def _add_action_mapping(self, semantics: dict[str, Any]) -> None:
|
||||||
"""Add action mapping between actions and interface directives."""
|
"""Add action mapping between actions and interface directives."""
|
||||||
self._action_mappings.append(semantics)
|
self._action_mappings.append(semantics)
|
||||||
|
|
||||||
def _add_state_mapping(self, semantics):
|
def _add_state_mapping(self, semantics: dict[str, Any]) -> None:
|
||||||
"""Add state mapping between states and interface directives."""
|
"""Add state mapping between states and interface directives."""
|
||||||
self._state_mappings.append(semantics)
|
self._state_mappings.append(semantics)
|
||||||
|
|
||||||
def add_states_to_value(self, states, value):
|
def add_states_to_value(self, states: list[str], value: int | float) -> None:
|
||||||
"""Add StatesToValue stateMappings."""
|
"""Add StatesToValue stateMappings."""
|
||||||
self._add_state_mapping(
|
self._add_state_mapping(
|
||||||
{"@type": self.STATES_TO_VALUE, "states": states, "value": value}
|
{"@type": self.STATES_TO_VALUE, "states": states, "value": value}
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_states_to_range(self, states, min_value, max_value):
|
def add_states_to_range(
|
||||||
|
self, states: list[str], min_value: int | float, max_value: int | float
|
||||||
|
) -> None:
|
||||||
"""Add StatesToRange stateMappings."""
|
"""Add StatesToRange stateMappings."""
|
||||||
self._add_state_mapping(
|
self._add_state_mapping(
|
||||||
{
|
{
|
||||||
@ -401,7 +417,9 @@ class AlexaSemantics:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_action_to_directive(self, actions, directive, payload):
|
def add_action_to_directive(
|
||||||
|
self, actions: list[str], directive: str, payload: dict[str, Any]
|
||||||
|
) -> None:
|
||||||
"""Add ActionsToDirective actionMappings."""
|
"""Add ActionsToDirective actionMappings."""
|
||||||
self._add_action_mapping(
|
self._add_action_mapping(
|
||||||
{
|
{
|
||||||
@ -411,9 +429,9 @@ class AlexaSemantics:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def serialize_semantics(self):
|
def serialize_semantics(self) -> dict[str, Any]:
|
||||||
"""Return semantics object serialized for an API response."""
|
"""Return semantics object serialized for an API response."""
|
||||||
semantics = {}
|
semantics: dict[str, Any] = {}
|
||||||
if self._action_mappings:
|
if self._action_mappings:
|
||||||
semantics[self.MAPPINGS_ACTION] = self._action_mappings
|
semantics[self.MAPPINGS_ACTION] = self._action_mappings
|
||||||
if self._state_mappings:
|
if self._state_mappings:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user