Improve Registry typing in Alexa handlers (#75921)

This commit is contained in:
epenet 2022-08-01 00:39:38 +02:00 committed by GitHub
parent 0167875789
commit 89729b2c49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,10 @@
"""Alexa message handlers.""" """Alexa message handlers."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
import logging import logging
import math import math
from typing import Any
from homeassistant import core as ha from homeassistant import core as ha
from homeassistant.components import ( from homeassistant.components import (
@ -51,6 +55,7 @@ from homeassistant.util.decorator import Registry
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.util.temperature import convert as convert_temperature from homeassistant.util.temperature import convert as convert_temperature
from .config import AbstractConfig
from .const import ( from .const import (
API_TEMP_UNITS, API_TEMP_UNITS,
API_THERMOSTAT_MODES, API_THERMOSTAT_MODES,
@ -70,14 +75,27 @@ from .errors import (
AlexaUnsupportedThermostatModeError, AlexaUnsupportedThermostatModeError,
AlexaVideoActionNotPermittedForContentError, AlexaVideoActionNotPermittedForContentError,
) )
from .messages import AlexaDirective, AlexaResponse
from .state_report import async_enable_proactive_mode from .state_report import async_enable_proactive_mode
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
HANDLERS = Registry() # type: ignore[var-annotated] DIRECTIVE_NOT_SUPPORTED = "Entity does not support directive"
HANDLERS: Registry[
tuple[str, str],
Callable[
[ha.HomeAssistant, AbstractConfig, AlexaDirective, ha.Context],
Coroutine[Any, Any, AlexaResponse],
],
] = Registry()
@HANDLERS.register(("Alexa.Discovery", "Discover")) @HANDLERS.register(("Alexa.Discovery", "Discover"))
async def async_api_discovery(hass, config, directive, context): async def async_api_discovery(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Create a API formatted discovery response. """Create a API formatted discovery response.
Async friendly. Async friendly.
@ -96,7 +114,12 @@ async def async_api_discovery(hass, config, directive, context):
@HANDLERS.register(("Alexa.Authorization", "AcceptGrant")) @HANDLERS.register(("Alexa.Authorization", "AcceptGrant"))
async def async_api_accept_grant(hass, config, directive, context): async def async_api_accept_grant(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Create a API formatted AcceptGrant response. """Create a API formatted AcceptGrant response.
Async friendly. Async friendly.
@ -116,7 +139,12 @@ async def async_api_accept_grant(hass, config, directive, context):
@HANDLERS.register(("Alexa.PowerController", "TurnOn")) @HANDLERS.register(("Alexa.PowerController", "TurnOn"))
async def async_api_turn_on(hass, config, directive, context): async def async_api_turn_on(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a turn on request.""" """Process a turn on request."""
entity = directive.entity entity = directive.entity
if (domain := entity.domain) == group.DOMAIN: if (domain := entity.domain) == group.DOMAIN:
@ -157,7 +185,12 @@ async def async_api_turn_on(hass, config, directive, context):
@HANDLERS.register(("Alexa.PowerController", "TurnOff")) @HANDLERS.register(("Alexa.PowerController", "TurnOff"))
async def async_api_turn_off(hass, config, directive, context): async def async_api_turn_off(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a turn off request.""" """Process a turn off request."""
entity = directive.entity entity = directive.entity
domain = entity.domain domain = entity.domain
@ -199,7 +232,12 @@ async def async_api_turn_off(hass, config, directive, context):
@HANDLERS.register(("Alexa.BrightnessController", "SetBrightness")) @HANDLERS.register(("Alexa.BrightnessController", "SetBrightness"))
async def async_api_set_brightness(hass, config, directive, context): async def async_api_set_brightness(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set brightness request.""" """Process a set brightness request."""
entity = directive.entity entity = directive.entity
brightness = int(directive.payload["brightness"]) brightness = int(directive.payload["brightness"])
@ -216,7 +254,12 @@ async def async_api_set_brightness(hass, config, directive, context):
@HANDLERS.register(("Alexa.BrightnessController", "AdjustBrightness")) @HANDLERS.register(("Alexa.BrightnessController", "AdjustBrightness"))
async def async_api_adjust_brightness(hass, config, directive, context): async def async_api_adjust_brightness(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an adjust brightness request.""" """Process an adjust brightness request."""
entity = directive.entity entity = directive.entity
brightness_delta = int(directive.payload["brightnessDelta"]) brightness_delta = int(directive.payload["brightnessDelta"])
@ -237,7 +280,12 @@ async def async_api_adjust_brightness(hass, config, directive, context):
@HANDLERS.register(("Alexa.ColorController", "SetColor")) @HANDLERS.register(("Alexa.ColorController", "SetColor"))
async def async_api_set_color(hass, config, directive, context): async def async_api_set_color(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set color request.""" """Process a set color request."""
entity = directive.entity entity = directive.entity
rgb = color_util.color_hsb_to_RGB( rgb = color_util.color_hsb_to_RGB(
@ -258,7 +306,12 @@ async def async_api_set_color(hass, config, directive, context):
@HANDLERS.register(("Alexa.ColorTemperatureController", "SetColorTemperature")) @HANDLERS.register(("Alexa.ColorTemperatureController", "SetColorTemperature"))
async def async_api_set_color_temperature(hass, config, directive, context): async def async_api_set_color_temperature(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set color temperature request.""" """Process a set color temperature request."""
entity = directive.entity entity = directive.entity
kelvin = int(directive.payload["colorTemperatureInKelvin"]) kelvin = int(directive.payload["colorTemperatureInKelvin"])
@ -275,7 +328,12 @@ async def async_api_set_color_temperature(hass, config, directive, context):
@HANDLERS.register(("Alexa.ColorTemperatureController", "DecreaseColorTemperature")) @HANDLERS.register(("Alexa.ColorTemperatureController", "DecreaseColorTemperature"))
async def async_api_decrease_color_temp(hass, config, directive, context): async def async_api_decrease_color_temp(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a decrease color temperature request.""" """Process a decrease color temperature request."""
entity = directive.entity entity = directive.entity
current = int(entity.attributes.get(light.ATTR_COLOR_TEMP)) current = int(entity.attributes.get(light.ATTR_COLOR_TEMP))
@ -294,7 +352,12 @@ async def async_api_decrease_color_temp(hass, config, directive, context):
@HANDLERS.register(("Alexa.ColorTemperatureController", "IncreaseColorTemperature")) @HANDLERS.register(("Alexa.ColorTemperatureController", "IncreaseColorTemperature"))
async def async_api_increase_color_temp(hass, config, directive, context): async def async_api_increase_color_temp(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an increase color temperature request.""" """Process an increase color temperature request."""
entity = directive.entity entity = directive.entity
current = int(entity.attributes.get(light.ATTR_COLOR_TEMP)) current = int(entity.attributes.get(light.ATTR_COLOR_TEMP))
@ -313,7 +376,12 @@ async def async_api_increase_color_temp(hass, config, directive, context):
@HANDLERS.register(("Alexa.SceneController", "Activate")) @HANDLERS.register(("Alexa.SceneController", "Activate"))
async def async_api_activate(hass, config, directive, context): async def async_api_activate(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an activate request.""" """Process an activate request."""
entity = directive.entity entity = directive.entity
domain = entity.domain domain = entity.domain
@ -343,7 +411,12 @@ async def async_api_activate(hass, config, directive, context):
@HANDLERS.register(("Alexa.SceneController", "Deactivate")) @HANDLERS.register(("Alexa.SceneController", "Deactivate"))
async def async_api_deactivate(hass, config, directive, context): async def async_api_deactivate(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a deactivate request.""" """Process a deactivate request."""
entity = directive.entity entity = directive.entity
domain = entity.domain domain = entity.domain
@ -367,16 +440,24 @@ async def async_api_deactivate(hass, config, directive, context):
@HANDLERS.register(("Alexa.PercentageController", "SetPercentage")) @HANDLERS.register(("Alexa.PercentageController", "SetPercentage"))
async def async_api_set_percentage(hass, config, directive, context): async def async_api_set_percentage(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set percentage request.""" """Process a set percentage request."""
entity = directive.entity entity = directive.entity
service = None
data = {ATTR_ENTITY_ID: entity.entity_id}
if entity.domain == fan.DOMAIN: if entity.domain != fan.DOMAIN:
service = fan.SERVICE_SET_PERCENTAGE raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
percentage = int(directive.payload["percentage"])
data[fan.ATTR_PERCENTAGE] = percentage percentage = int(directive.payload["percentage"])
service = fan.SERVICE_SET_PERCENTAGE
data = {
ATTR_ENTITY_ID: entity.entity_id,
fan.ATTR_PERCENTAGE: percentage,
}
await hass.services.async_call( await hass.services.async_call(
entity.domain, service, data, blocking=False, context=context entity.domain, service, data, blocking=False, context=context
@ -386,20 +467,27 @@ async def async_api_set_percentage(hass, config, directive, context):
@HANDLERS.register(("Alexa.PercentageController", "AdjustPercentage")) @HANDLERS.register(("Alexa.PercentageController", "AdjustPercentage"))
async def async_api_adjust_percentage(hass, config, directive, context): async def async_api_adjust_percentage(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an adjust percentage request.""" """Process an adjust percentage request."""
entity = directive.entity entity = directive.entity
if entity.domain != fan.DOMAIN:
raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
percentage_delta = int(directive.payload["percentageDelta"]) percentage_delta = int(directive.payload["percentageDelta"])
service = None current = entity.attributes.get(fan.ATTR_PERCENTAGE) or 0
data = {ATTR_ENTITY_ID: entity.entity_id} # set percentage
percentage = min(100, max(0, percentage_delta + current))
if entity.domain == fan.DOMAIN: service = fan.SERVICE_SET_PERCENTAGE
service = fan.SERVICE_SET_PERCENTAGE data = {
current = entity.attributes.get(fan.ATTR_PERCENTAGE) or 0 ATTR_ENTITY_ID: entity.entity_id,
fan.ATTR_PERCENTAGE: percentage,
# set percentage }
percentage = min(100, max(0, percentage_delta + current))
data[fan.ATTR_PERCENTAGE] = percentage
await hass.services.async_call( await hass.services.async_call(
entity.domain, service, data, blocking=False, context=context entity.domain, service, data, blocking=False, context=context
@ -409,7 +497,12 @@ async def async_api_adjust_percentage(hass, config, directive, context):
@HANDLERS.register(("Alexa.LockController", "Lock")) @HANDLERS.register(("Alexa.LockController", "Lock"))
async def async_api_lock(hass, config, directive, context): async def async_api_lock(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a lock request.""" """Process a lock request."""
entity = directive.entity entity = directive.entity
await hass.services.async_call( await hass.services.async_call(
@ -428,7 +521,12 @@ async def async_api_lock(hass, config, directive, context):
@HANDLERS.register(("Alexa.LockController", "Unlock")) @HANDLERS.register(("Alexa.LockController", "Unlock"))
async def async_api_unlock(hass, config, directive, context): async def async_api_unlock(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an unlock request.""" """Process an unlock request."""
if config.locale not in {"de-DE", "en-US", "ja-JP"}: if config.locale not in {"de-DE", "en-US", "ja-JP"}:
msg = f"The unlock directive is not supported for the following locales: {config.locale}" msg = f"The unlock directive is not supported for the following locales: {config.locale}"
@ -452,7 +550,12 @@ async def async_api_unlock(hass, config, directive, context):
@HANDLERS.register(("Alexa.Speaker", "SetVolume")) @HANDLERS.register(("Alexa.Speaker", "SetVolume"))
async def async_api_set_volume(hass, config, directive, context): async def async_api_set_volume(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set volume request.""" """Process a set volume request."""
volume = round(float(directive.payload["volume"] / 100), 2) volume = round(float(directive.payload["volume"] / 100), 2)
entity = directive.entity entity = directive.entity
@ -470,7 +573,12 @@ async def async_api_set_volume(hass, config, directive, context):
@HANDLERS.register(("Alexa.InputController", "SelectInput")) @HANDLERS.register(("Alexa.InputController", "SelectInput"))
async def async_api_select_input(hass, config, directive, context): async def async_api_select_input(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set input request.""" """Process a set input request."""
media_input = directive.payload["input"] media_input = directive.payload["input"]
entity = directive.entity entity = directive.entity
@ -514,7 +622,12 @@ async def async_api_select_input(hass, config, directive, context):
@HANDLERS.register(("Alexa.Speaker", "AdjustVolume")) @HANDLERS.register(("Alexa.Speaker", "AdjustVolume"))
async def async_api_adjust_volume(hass, config, directive, context): async def async_api_adjust_volume(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an adjust volume request.""" """Process an adjust volume request."""
volume_delta = int(directive.payload["volume"]) volume_delta = int(directive.payload["volume"])
@ -542,7 +655,12 @@ async def async_api_adjust_volume(hass, config, directive, context):
@HANDLERS.register(("Alexa.StepSpeaker", "AdjustVolume")) @HANDLERS.register(("Alexa.StepSpeaker", "AdjustVolume"))
async def async_api_adjust_volume_step(hass, config, directive, context): async def async_api_adjust_volume_step(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an adjust volume step request.""" """Process an adjust volume step request."""
# media_player volume up/down service does not support specifying steps # media_player volume up/down service does not support specifying steps
# each component handles it differently e.g. via config. # each component handles it differently e.g. via config.
@ -575,7 +693,12 @@ async def async_api_adjust_volume_step(hass, config, directive, context):
@HANDLERS.register(("Alexa.StepSpeaker", "SetMute")) @HANDLERS.register(("Alexa.StepSpeaker", "SetMute"))
@HANDLERS.register(("Alexa.Speaker", "SetMute")) @HANDLERS.register(("Alexa.Speaker", "SetMute"))
async def async_api_set_mute(hass, config, directive, context): async def async_api_set_mute(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set mute request.""" """Process a set mute request."""
mute = bool(directive.payload["mute"]) mute = bool(directive.payload["mute"])
entity = directive.entity entity = directive.entity
@ -592,7 +715,12 @@ async def async_api_set_mute(hass, config, directive, context):
@HANDLERS.register(("Alexa.PlaybackController", "Play")) @HANDLERS.register(("Alexa.PlaybackController", "Play"))
async def async_api_play(hass, config, directive, context): async def async_api_play(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a play request.""" """Process a play request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -605,7 +733,12 @@ async def async_api_play(hass, config, directive, context):
@HANDLERS.register(("Alexa.PlaybackController", "Pause")) @HANDLERS.register(("Alexa.PlaybackController", "Pause"))
async def async_api_pause(hass, config, directive, context): async def async_api_pause(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a pause request.""" """Process a pause request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -618,7 +751,12 @@ async def async_api_pause(hass, config, directive, context):
@HANDLERS.register(("Alexa.PlaybackController", "Stop")) @HANDLERS.register(("Alexa.PlaybackController", "Stop"))
async def async_api_stop(hass, config, directive, context): async def async_api_stop(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a stop request.""" """Process a stop request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -631,7 +769,12 @@ async def async_api_stop(hass, config, directive, context):
@HANDLERS.register(("Alexa.PlaybackController", "Next")) @HANDLERS.register(("Alexa.PlaybackController", "Next"))
async def async_api_next(hass, config, directive, context): async def async_api_next(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a next request.""" """Process a next request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -644,7 +787,12 @@ async def async_api_next(hass, config, directive, context):
@HANDLERS.register(("Alexa.PlaybackController", "Previous")) @HANDLERS.register(("Alexa.PlaybackController", "Previous"))
async def async_api_previous(hass, config, directive, context): async def async_api_previous(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a previous request.""" """Process a previous request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -676,7 +824,12 @@ def temperature_from_object(hass, temp_obj, interval=False):
@HANDLERS.register(("Alexa.ThermostatController", "SetTargetTemperature")) @HANDLERS.register(("Alexa.ThermostatController", "SetTargetTemperature"))
async def async_api_set_target_temp(hass, config, directive, context): async def async_api_set_target_temp(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set target temperature request.""" """Process a set target temperature request."""
entity = directive.entity entity = directive.entity
min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP)
@ -736,7 +889,12 @@ async def async_api_set_target_temp(hass, config, directive, context):
@HANDLERS.register(("Alexa.ThermostatController", "AdjustTargetTemperature")) @HANDLERS.register(("Alexa.ThermostatController", "AdjustTargetTemperature"))
async def async_api_adjust_target_temp(hass, config, directive, context): async def async_api_adjust_target_temp(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process an adjust target temperature request.""" """Process an adjust target temperature request."""
entity = directive.entity entity = directive.entity
min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP)
@ -773,7 +931,12 @@ async def async_api_adjust_target_temp(hass, config, directive, context):
@HANDLERS.register(("Alexa.ThermostatController", "SetThermostatMode")) @HANDLERS.register(("Alexa.ThermostatController", "SetThermostatMode"))
async def async_api_set_thermostat_mode(hass, config, directive, context): async def async_api_set_thermostat_mode(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a set thermostat mode request.""" """Process a set thermostat mode request."""
entity = directive.entity entity = directive.entity
mode = directive.payload["thermostatMode"] mode = directive.payload["thermostatMode"]
@ -836,13 +999,23 @@ async def async_api_set_thermostat_mode(hass, config, directive, context):
@HANDLERS.register(("Alexa", "ReportState")) @HANDLERS.register(("Alexa", "ReportState"))
async def async_api_reportstate(hass, config, directive, context): async def async_api_reportstate(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a ReportState request.""" """Process a ReportState request."""
return directive.response(name="StateReport") return directive.response(name="StateReport")
@HANDLERS.register(("Alexa.SecurityPanelController", "Arm")) @HANDLERS.register(("Alexa.SecurityPanelController", "Arm"))
async def async_api_arm(hass, config, directive, context): async def async_api_arm(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a Security Panel Arm request.""" """Process a Security Panel Arm request."""
entity = directive.entity entity = directive.entity
service = None service = None
@ -859,6 +1032,8 @@ async def async_api_arm(hass, config, directive, context):
service = SERVICE_ALARM_ARM_NIGHT service = SERVICE_ALARM_ARM_NIGHT
elif arm_state == "ARMED_STAY": elif arm_state == "ARMED_STAY":
service = SERVICE_ALARM_ARM_HOME service = SERVICE_ALARM_ARM_HOME
else:
raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
await hass.services.async_call( await hass.services.async_call(
entity.domain, service, data, blocking=False, context=context entity.domain, service, data, blocking=False, context=context
@ -883,7 +1058,12 @@ async def async_api_arm(hass, config, directive, context):
@HANDLERS.register(("Alexa.SecurityPanelController", "Disarm")) @HANDLERS.register(("Alexa.SecurityPanelController", "Disarm"))
async def async_api_disarm(hass, config, directive, context): async def async_api_disarm(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a Security Panel Disarm request.""" """Process a Security Panel Disarm request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -916,7 +1096,12 @@ async def async_api_disarm(hass, config, directive, context):
@HANDLERS.register(("Alexa.ModeController", "SetMode")) @HANDLERS.register(("Alexa.ModeController", "SetMode"))
async def async_api_set_mode(hass, config, directive, context): async def async_api_set_mode(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a SetMode directive.""" """Process a SetMode directive."""
entity = directive.entity entity = directive.entity
instance = directive.instance instance = directive.instance
@ -955,9 +1140,8 @@ async def async_api_set_mode(hass, config, directive, context):
elif position == "custom": elif position == "custom":
service = cover.SERVICE_STOP_COVER service = cover.SERVICE_STOP_COVER
else: if not service:
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
await hass.services.async_call( await hass.services.async_call(
domain, service, data, blocking=False, context=context domain, service, data, blocking=False, context=context
@ -977,7 +1161,12 @@ async def async_api_set_mode(hass, config, directive, context):
@HANDLERS.register(("Alexa.ModeController", "AdjustMode")) @HANDLERS.register(("Alexa.ModeController", "AdjustMode"))
async def async_api_adjust_mode(hass, config, directive, context): async def async_api_adjust_mode(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a AdjustMode request. """Process a AdjustMode request.
Requires capabilityResources supportedModes to be ordered. Requires capabilityResources supportedModes to be ordered.
@ -985,26 +1174,30 @@ async def async_api_adjust_mode(hass, config, directive, context):
""" """
# Currently no supportedModes are configured with ordered=True to support this request. # Currently no supportedModes are configured with ordered=True to support this request.
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
@HANDLERS.register(("Alexa.ToggleController", "TurnOn")) @HANDLERS.register(("Alexa.ToggleController", "TurnOn"))
async def async_api_toggle_on(hass, config, directive, context): async def async_api_toggle_on(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a toggle on request.""" """Process a toggle on request."""
entity = directive.entity entity = directive.entity
instance = directive.instance instance = directive.instance
domain = entity.domain domain = entity.domain
service = None
data = {ATTR_ENTITY_ID: entity.entity_id}
# Fan Oscillating # Fan Oscillating
if instance == f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}": if instance != f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}":
service = fan.SERVICE_OSCILLATE raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
data[fan.ATTR_OSCILLATING] = True
else: service = fan.SERVICE_OSCILLATE
msg = "Entity does not support directive" data = {
raise AlexaInvalidDirectiveError(msg) ATTR_ENTITY_ID: entity.entity_id,
fan.ATTR_OSCILLATING: True,
}
await hass.services.async_call( await hass.services.async_call(
domain, service, data, blocking=False, context=context domain, service, data, blocking=False, context=context
@ -1024,21 +1217,26 @@ async def async_api_toggle_on(hass, config, directive, context):
@HANDLERS.register(("Alexa.ToggleController", "TurnOff")) @HANDLERS.register(("Alexa.ToggleController", "TurnOff"))
async def async_api_toggle_off(hass, config, directive, context): async def async_api_toggle_off(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a toggle off request.""" """Process a toggle off request."""
entity = directive.entity entity = directive.entity
instance = directive.instance instance = directive.instance
domain = entity.domain domain = entity.domain
service = None
data = {ATTR_ENTITY_ID: entity.entity_id}
# Fan Oscillating # Fan Oscillating
if instance == f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}": if instance != f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}":
service = fan.SERVICE_OSCILLATE raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
data[fan.ATTR_OSCILLATING] = False
else: service = fan.SERVICE_OSCILLATE
msg = "Entity does not support directive" data = {
raise AlexaInvalidDirectiveError(msg) ATTR_ENTITY_ID: entity.entity_id,
fan.ATTR_OSCILLATING: False,
}
await hass.services.async_call( await hass.services.async_call(
domain, service, data, blocking=False, context=context domain, service, data, blocking=False, context=context
@ -1058,7 +1256,12 @@ async def async_api_toggle_off(hass, config, directive, context):
@HANDLERS.register(("Alexa.RangeController", "SetRangeValue")) @HANDLERS.register(("Alexa.RangeController", "SetRangeValue"))
async def async_api_set_range(hass, config, directive, context): async def async_api_set_range(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a next request.""" """Process a next request."""
entity = directive.entity entity = directive.entity
instance = directive.instance instance = directive.instance
@ -1125,8 +1328,7 @@ async def async_api_set_range(hass, config, directive, context):
data[vacuum.ATTR_FAN_SPEED] = speed data[vacuum.ATTR_FAN_SPEED] = speed
else: else:
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
await hass.services.async_call( await hass.services.async_call(
domain, service, data, blocking=False, context=context domain, service, data, blocking=False, context=context
@ -1146,16 +1348,21 @@ async def async_api_set_range(hass, config, directive, context):
@HANDLERS.register(("Alexa.RangeController", "AdjustRangeValue")) @HANDLERS.register(("Alexa.RangeController", "AdjustRangeValue"))
async def async_api_adjust_range(hass, config, directive, context): async def async_api_adjust_range(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a next request.""" """Process a next request."""
entity = directive.entity entity = directive.entity
instance = directive.instance instance = directive.instance
domain = entity.domain domain = entity.domain
service = None service = None
data = {ATTR_ENTITY_ID: entity.entity_id} data: dict[str, Any] = {ATTR_ENTITY_ID: entity.entity_id}
range_delta = directive.payload["rangeValueDelta"] range_delta = directive.payload["rangeValueDelta"]
range_delta_default = bool(directive.payload["rangeValueDeltaDefault"]) range_delta_default = bool(directive.payload["rangeValueDeltaDefault"])
response_value = 0 response_value: int | None = 0
# Cover Position # Cover Position
if instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}": if instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
@ -1232,12 +1439,10 @@ async def async_api_adjust_range(hass, config, directive, context):
speed = next( speed = next(
(v for i, v in enumerate(speed_list) if i == new_speed_index), None (v for i, v in enumerate(speed_list) if i == new_speed_index), None
) )
data[vacuum.ATTR_FAN_SPEED] = response_value = speed data[vacuum.ATTR_FAN_SPEED] = response_value = speed
else: else:
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
await hass.services.async_call( await hass.services.async_call(
domain, service, data, blocking=False, context=context domain, service, data, blocking=False, context=context
@ -1257,7 +1462,12 @@ async def async_api_adjust_range(hass, config, directive, context):
@HANDLERS.register(("Alexa.ChannelController", "ChangeChannel")) @HANDLERS.register(("Alexa.ChannelController", "ChangeChannel"))
async def async_api_changechannel(hass, config, directive, context): async def async_api_changechannel(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a change channel request.""" """Process a change channel request."""
channel = "0" channel = "0"
entity = directive.entity entity = directive.entity
@ -1309,7 +1519,12 @@ async def async_api_changechannel(hass, config, directive, context):
@HANDLERS.register(("Alexa.ChannelController", "SkipChannels")) @HANDLERS.register(("Alexa.ChannelController", "SkipChannels"))
async def async_api_skipchannel(hass, config, directive, context): async def async_api_skipchannel(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a skipchannel request.""" """Process a skipchannel request."""
channel = int(directive.payload["channelCount"]) channel = int(directive.payload["channelCount"])
entity = directive.entity entity = directive.entity
@ -1340,7 +1555,12 @@ async def async_api_skipchannel(hass, config, directive, context):
@HANDLERS.register(("Alexa.SeekController", "AdjustSeekPosition")) @HANDLERS.register(("Alexa.SeekController", "AdjustSeekPosition"))
async def async_api_seek(hass, config, directive, context): async def async_api_seek(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a seek request.""" """Process a seek request."""
entity = directive.entity entity = directive.entity
position_delta = int(directive.payload["deltaPositionMilliseconds"]) position_delta = int(directive.payload["deltaPositionMilliseconds"])
@ -1379,7 +1599,12 @@ async def async_api_seek(hass, config, directive, context):
@HANDLERS.register(("Alexa.EqualizerController", "SetMode")) @HANDLERS.register(("Alexa.EqualizerController", "SetMode"))
async def async_api_set_eq_mode(hass, config, directive, context): async def async_api_set_eq_mode(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a SetMode request for EqualizerController.""" """Process a SetMode request for EqualizerController."""
mode = directive.payload["mode"] mode = directive.payload["mode"]
entity = directive.entity entity = directive.entity
@ -1406,18 +1631,27 @@ async def async_api_set_eq_mode(hass, config, directive, context):
@HANDLERS.register(("Alexa.EqualizerController", "AdjustBands")) @HANDLERS.register(("Alexa.EqualizerController", "AdjustBands"))
@HANDLERS.register(("Alexa.EqualizerController", "ResetBands")) @HANDLERS.register(("Alexa.EqualizerController", "ResetBands"))
@HANDLERS.register(("Alexa.EqualizerController", "SetBands")) @HANDLERS.register(("Alexa.EqualizerController", "SetBands"))
async def async_api_bands_directive(hass, config, directive, context): async def async_api_bands_directive(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Handle an AdjustBands, ResetBands, SetBands request. """Handle an AdjustBands, ResetBands, SetBands request.
Only mode directives are currently supported for the EqualizerController. Only mode directives are currently supported for the EqualizerController.
""" """
# Currently bands directives are not supported. # Currently bands directives are not supported.
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
@HANDLERS.register(("Alexa.TimeHoldController", "Hold")) @HANDLERS.register(("Alexa.TimeHoldController", "Hold"))
async def async_api_hold(hass, config, directive, context): async def async_api_hold(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a TimeHoldController Hold request.""" """Process a TimeHoldController Hold request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -1429,8 +1663,7 @@ async def async_api_hold(hass, config, directive, context):
service = vacuum.SERVICE_START_PAUSE service = vacuum.SERVICE_START_PAUSE
else: else:
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
await hass.services.async_call( await hass.services.async_call(
entity.domain, service, data, blocking=False, context=context entity.domain, service, data, blocking=False, context=context
@ -1440,7 +1673,12 @@ async def async_api_hold(hass, config, directive, context):
@HANDLERS.register(("Alexa.TimeHoldController", "Resume")) @HANDLERS.register(("Alexa.TimeHoldController", "Resume"))
async def async_api_resume(hass, config, directive, context): async def async_api_resume(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a TimeHoldController Resume request.""" """Process a TimeHoldController Resume request."""
entity = directive.entity entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id} data = {ATTR_ENTITY_ID: entity.entity_id}
@ -1452,8 +1690,7 @@ async def async_api_resume(hass, config, directive, context):
service = vacuum.SERVICE_START_PAUSE service = vacuum.SERVICE_START_PAUSE
else: else:
msg = "Entity does not support directive" raise AlexaInvalidDirectiveError(DIRECTIVE_NOT_SUPPORTED)
raise AlexaInvalidDirectiveError(msg)
await hass.services.async_call( await hass.services.async_call(
entity.domain, service, data, blocking=False, context=context entity.domain, service, data, blocking=False, context=context
@ -1463,11 +1700,18 @@ async def async_api_resume(hass, config, directive, context):
@HANDLERS.register(("Alexa.CameraStreamController", "InitializeCameraStreams")) @HANDLERS.register(("Alexa.CameraStreamController", "InitializeCameraStreams"))
async def async_api_initialize_camera_stream(hass, config, directive, context): async def async_api_initialize_camera_stream(
hass: ha.HomeAssistant,
config: AbstractConfig,
directive: AlexaDirective,
context: ha.Context,
) -> AlexaResponse:
"""Process a InitializeCameraStreams request.""" """Process a InitializeCameraStreams request."""
entity = directive.entity entity = directive.entity
stream_source = await camera.async_request_stream(hass, entity.entity_id, fmt="hls") stream_source = await camera.async_request_stream(hass, entity.entity_id, fmt="hls")
camera_image = hass.states.get(entity.entity_id).attributes[ATTR_ENTITY_PICTURE] state = hass.states.get(entity.entity_id)
assert state
camera_image = state.attributes[ATTR_ENTITY_PICTURE]
try: try:
external_url = network.get_url( external_url = network.get_url(