Implement TimeHoldController Interface in Alexa (#30650)

* Implement Alexa.TimeHoldController Interface

* Add test for timer resume directive.
This commit is contained in:
ochlocracy 2020-01-10 17:11:50 -05:00 committed by Paulus Schoutsen
parent e2f591e5bc
commit 74a198e37b
4 changed files with 110 additions and 0 deletions

View file

@ -1665,3 +1665,29 @@ class AlexaEqualizerController(AlexaCapability):
configurations = {"modes": {"supported": supported_sound_modes}}
return configurations
class AlexaTimeHoldController(AlexaCapability):
"""Implements Alexa.TimeHoldController.
https://developer.amazon.com/docs/device-apis/alexa-timeholdcontroller.html
"""
supported_locales = {"en-US"}
def __init__(self, entity, allow_remote_resume=False):
"""Initialize the entity."""
super().__init__(entity)
self._allow_remote_resume = allow_remote_resume
def name(self):
"""Return the Alexa API name of this interface."""
return "Alexa.TimeHoldController"
def configuration(self):
"""Return configuration object.
Set allowRemoteResume to True if Alexa can restart the operation on the device.
When false, Alexa does not send the Resume directive.
"""
return {"allowRemoteResume": self._allow_remote_resume}

View file

@ -19,6 +19,7 @@ from homeassistant.components import (
script,
sensor,
switch,
timer,
)
from homeassistant.components.climate import const as climate
from homeassistant.const import (
@ -61,6 +62,7 @@ from .capabilities import (
AlexaStepSpeaker,
AlexaTemperatureSensor,
AlexaThermostatController,
AlexaTimeHoldController,
AlexaToggleController,
)
from .const import CONF_DESCRIPTION, CONF_DISPLAY_CATEGORIES
@ -708,3 +710,17 @@ class InputNumberCapabilities(AlexaEntity):
)
yield AlexaEndpointHealth(self.hass, self.entity)
yield Alexa(self.hass)
@ENTITY_ADAPTERS.register(timer.DOMAIN)
class TimerCapabilities(AlexaEntity):
"""Class to represent Timer capabilities."""
def default_display_categories(self):
"""Return the display categories for this entity."""
return [DisplayCategory.OTHER]
def interfaces(self):
"""Yield the supported interfaces."""
yield AlexaTimeHoldController(self.entity, allow_remote_resume=True)
yield Alexa(self.entity)

View file

@ -10,6 +10,7 @@ from homeassistant.components import (
input_number,
light,
media_player,
timer,
)
from homeassistant.components.climate import const as climate
from homeassistant.const import (
@ -1396,3 +1397,29 @@ async def async_api_bands_directive(hass, config, directive, context):
# Currently bands directives are not supported.
msg = "Entity does not support directive"
raise AlexaInvalidDirectiveError(msg)
@HANDLERS.register(("Alexa.TimeHoldController", "Hold"))
async def async_api_hold(hass, config, directive, context):
"""Process a TimeHoldController Hold request."""
entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id}
await hass.services.async_call(
entity.domain, timer.SERVICE_PAUSE, data, blocking=False, context=context
)
return directive.response()
@HANDLERS.register(("Alexa.TimeHoldController", "Resume"))
async def async_api_resume(hass, config, directive, context):
"""Process a TimeHoldController Resume request."""
entity = directive.entity
data = {ATTR_ENTITY_ID: entity.entity_id}
await hass.services.async_call(
entity.domain, timer.SERVICE_START, data, blocking=False, context=context
)
return directive.response()

View file

@ -3037,3 +3037,44 @@ async def test_media_player_eq_bands_not_supported(hass):
assert msg["header"]["name"] == "ErrorResponse"
assert msg["header"]["namespace"] == "Alexa"
assert msg["payload"]["type"] == "INVALID_DIRECTIVE"
async def test_timer_hold(hass):
"""Test timer hold."""
device = (
"timer.laundry",
"active",
{"friendly_name": "Laundry", "duration": "00:01:00", "remaining": "00:50:00"},
)
appliance = await discovery_test(device, hass)
assert appliance["endpointId"] == "timer#laundry"
assert appliance["displayCategories"][0] == "OTHER"
assert appliance["friendlyName"] == "Laundry"
capabilities = assert_endpoint_capabilities(
appliance, "Alexa", "Alexa.TimeHoldController"
)
time_hold_capability = get_capability(capabilities, "Alexa.TimeHoldController")
assert time_hold_capability is not None
configuration = time_hold_capability["configuration"]
assert configuration["allowRemoteResume"] is True
await assert_request_calls_service(
"Alexa.TimeHoldController", "Hold", "timer#laundry", "timer.pause", hass
)
async def test_timer_resume(hass):
"""Test timer resume."""
device = (
"timer.laundry",
"paused",
{"friendly_name": "Laundry", "duration": "00:01:00", "remaining": "00:50:00"},
)
await discovery_test(device, hass)
await assert_request_calls_service(
"Alexa.TimeHoldController", "Resume", "timer#laundry", "timer.start", hass
)