Add valid inputs to alexa InputController (#28483)
* Add supported Inputs for Alexa.InputController. * Fixed Test. * Added default parameter for get() per @quthla suggestion. * Added additional tests, assets call data. * Added additional tests, asserts call data. * Accounted for space in input name, added tests to handle space.
This commit is contained in:
parent
f53812f261
commit
970a80216d
4 changed files with 225 additions and 6 deletions
|
@ -35,6 +35,7 @@ from .const import (
|
|||
DATE_FORMAT,
|
||||
PERCENTAGE_FAN_MAP,
|
||||
RANGE_FAN_MAP,
|
||||
Inputs,
|
||||
)
|
||||
from .errors import UnsupportedProperty
|
||||
|
||||
|
@ -115,6 +116,11 @@ class AlexaCapability:
|
|||
"""Return the Configuration object."""
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def inputs():
|
||||
"""Applicable only to media players."""
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def supported_operations():
|
||||
"""Return the supportedOperations object."""
|
||||
|
@ -164,6 +170,10 @@ class AlexaCapability:
|
|||
if supported_operations:
|
||||
result["supportedOperations"] = supported_operations
|
||||
|
||||
inputs = self.inputs()
|
||||
if inputs:
|
||||
result["inputs"] = inputs
|
||||
|
||||
return result
|
||||
|
||||
def serialize_properties(self):
|
||||
|
@ -531,6 +541,23 @@ class AlexaInputController(AlexaCapability):
|
|||
"""Return the Alexa API name of this interface."""
|
||||
return "Alexa.InputController"
|
||||
|
||||
def inputs(self):
|
||||
"""Return the list of valid supported inputs."""
|
||||
source_list = self.entity.attributes.get(
|
||||
media_player.ATTR_INPUT_SOURCE_LIST, []
|
||||
)
|
||||
input_list = []
|
||||
for source in source_list:
|
||||
formatted_source = (
|
||||
source.lower().replace("-", "").replace("_", "").replace(" ", "")
|
||||
)
|
||||
if formatted_source in Inputs.VALID_SOURCE_NAME_MAP.keys():
|
||||
input_list.append(
|
||||
{"name": Inputs.VALID_SOURCE_NAME_MAP[formatted_source]}
|
||||
)
|
||||
|
||||
return input_list
|
||||
|
||||
|
||||
class AlexaTemperatureSensor(AlexaCapability):
|
||||
"""Implements Alexa.TemperatureSensor.
|
||||
|
|
|
@ -272,3 +272,84 @@ class Unit:
|
|||
WEIGHT_OUNCES = "Alexa.Unit.Weight.Ounces"
|
||||
|
||||
WEIGHT_POUNDS = "Alexa.Unit.Weight.Pounds"
|
||||
|
||||
|
||||
class Inputs:
|
||||
"""Valid names for the InputController.
|
||||
|
||||
https://developer.amazon.com/docs/device-apis/alexa-property-schemas.html#input
|
||||
"""
|
||||
|
||||
VALID_SOURCE_NAME_MAP = {
|
||||
"aux": "AUX 1",
|
||||
"aux1": "AUX 1",
|
||||
"aux2": "AUX 2",
|
||||
"aux3": "AUX 3",
|
||||
"aux4": "AUX 4",
|
||||
"aux5": "AUX 5",
|
||||
"aux6": "AUX 6",
|
||||
"aux7": "AUX 7",
|
||||
"bluray": "BLURAY",
|
||||
"cable": "CABLE",
|
||||
"cd": "CD",
|
||||
"coax": "COAX 1",
|
||||
"coax1": "COAX 1",
|
||||
"coax2": "COAX 2",
|
||||
"composite": "COMPOSITE 1",
|
||||
"composite1": "COMPOSITE 1",
|
||||
"dvd": "DVD",
|
||||
"game": "GAME",
|
||||
"gameconsole": "GAME",
|
||||
"hdradio": "HD RADIO",
|
||||
"hdmi": "HDMI 1",
|
||||
"hdmi1": "HDMI 1",
|
||||
"hdmi2": "HDMI 2",
|
||||
"hdmi3": "HDMI 3",
|
||||
"hdmi4": "HDMI 4",
|
||||
"hdmi5": "HDMI 5",
|
||||
"hdmi6": "HDMI 6",
|
||||
"hdmi7": "HDMI 7",
|
||||
"hdmi8": "HDMI 8",
|
||||
"hdmi9": "HDMI 9",
|
||||
"hdmi10": "HDMI 10",
|
||||
"hdmiarc": "HDMI ARC",
|
||||
"input": "INPUT 1",
|
||||
"input1": "INPUT 1",
|
||||
"input2": "INPUT 2",
|
||||
"input3": "INPUT 3",
|
||||
"input4": "INPUT 4",
|
||||
"input5": "INPUT 5",
|
||||
"input6": "INPUT 6",
|
||||
"input7": "INPUT 7",
|
||||
"input8": "INPUT 8",
|
||||
"input9": "INPUT 9",
|
||||
"input10": "INPUT 10",
|
||||
"ipod": "IPOD",
|
||||
"line": "LINE 1",
|
||||
"line1": "LINE 1",
|
||||
"line2": "LINE 2",
|
||||
"line3": "LINE 3",
|
||||
"line4": "LINE 4",
|
||||
"line5": "LINE 5",
|
||||
"line6": "LINE 6",
|
||||
"line7": "LINE 7",
|
||||
"mediaplayer": "MEDIA PLAYER",
|
||||
"optical": "OPTICAL 1",
|
||||
"optical1": "OPTICAL 1",
|
||||
"optical2": "OPTICAL 2",
|
||||
"phono": "PHONO",
|
||||
"playstation": "PLAYSTATION",
|
||||
"playstation3": "PLAYSTATION 3",
|
||||
"playstation4": "PLAYSTATION 4",
|
||||
"satellite": "SATELLITE",
|
||||
"satellitetv": "SATELLITE",
|
||||
"smartcast": "SMARTCAST",
|
||||
"tuner": "TUNER",
|
||||
"tv": "TV",
|
||||
"usbdac": "USB DAC",
|
||||
"video": "VIDEO 1",
|
||||
"video1": "VIDEO 1",
|
||||
"video2": "VIDEO 2",
|
||||
"video3": "VIDEO 3",
|
||||
"xbox": "XBOX",
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ from .const import (
|
|||
API_THERMOSTAT_MODES,
|
||||
API_THERMOSTAT_PRESETS,
|
||||
Cause,
|
||||
Inputs,
|
||||
PERCENTAGE_FAN_MAP,
|
||||
RANGE_FAN_MAP,
|
||||
SPEED_FAN_MAP,
|
||||
|
@ -461,13 +462,20 @@ async def async_api_select_input(hass, config, directive, context):
|
|||
media_input = directive.payload["input"]
|
||||
entity = directive.entity
|
||||
|
||||
# attempt to map the ALL UPPERCASE payload name to a source
|
||||
source_list = entity.attributes[media_player.const.ATTR_INPUT_SOURCE_LIST] or []
|
||||
# Attempt to map the ALL UPPERCASE payload name to a source.
|
||||
# Strips trailing 1 to match single input devices.
|
||||
source_list = entity.attributes.get(media_player.const.ATTR_INPUT_SOURCE_LIST, [])
|
||||
for source in source_list:
|
||||
# response will always be space separated, so format the source in the
|
||||
# most likely way to find a match
|
||||
formatted_source = source.lower().replace("-", " ").replace("_", " ")
|
||||
if formatted_source in media_input.lower():
|
||||
formatted_source = (
|
||||
source.lower().replace("-", "").replace("_", "").replace(" ", "")
|
||||
)
|
||||
media_input = media_input.lower().replace(" ", "")
|
||||
if (
|
||||
formatted_source in Inputs.VALID_SOURCE_NAME_MAP.keys()
|
||||
and formatted_source == media_input
|
||||
) or (
|
||||
media_input.endswith("1") and formatted_source == media_input.rstrip("1")
|
||||
):
|
||||
media_input = source
|
||||
break
|
||||
else:
|
||||
|
|
|
@ -1015,6 +1015,109 @@ async def test_media_player_power(hass):
|
|||
)
|
||||
|
||||
|
||||
async def test_media_player_inputs(hass):
|
||||
"""Test media player discovery with source list inputs."""
|
||||
device = (
|
||||
"media_player.test",
|
||||
"on",
|
||||
{
|
||||
"friendly_name": "Test media player",
|
||||
"supported_features": SUPPORT_SELECT_SOURCE,
|
||||
"volume_level": 0.75,
|
||||
"source_list": [
|
||||
"foo",
|
||||
"foo_2",
|
||||
"hdmi",
|
||||
"hdmi_2",
|
||||
"hdmi-3",
|
||||
"hdmi4",
|
||||
"hdmi 5",
|
||||
"HDMI 6",
|
||||
"hdmi_arc",
|
||||
"aux",
|
||||
"input 1",
|
||||
"tv",
|
||||
],
|
||||
},
|
||||
)
|
||||
appliance = await discovery_test(device, hass)
|
||||
|
||||
assert appliance["endpointId"] == "media_player#test"
|
||||
assert appliance["displayCategories"][0] == "TV"
|
||||
assert appliance["friendlyName"] == "Test media player"
|
||||
|
||||
capabilities = assert_endpoint_capabilities(
|
||||
appliance,
|
||||
"Alexa.InputController",
|
||||
"Alexa.PowerController",
|
||||
"Alexa.EndpointHealth",
|
||||
)
|
||||
|
||||
input_capability = get_capability(capabilities, "Alexa.InputController")
|
||||
assert input_capability is not None
|
||||
assert {"name": "AUX"} not in input_capability["inputs"]
|
||||
assert {"name": "AUX 1"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 1"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 2"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 3"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 4"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 5"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI 6"} in input_capability["inputs"]
|
||||
assert {"name": "HDMI ARC"} in input_capability["inputs"]
|
||||
assert {"name": "FOO 1"} not in input_capability["inputs"]
|
||||
assert {"name": "TV"} in input_capability["inputs"]
|
||||
|
||||
call, _ = await assert_request_calls_service(
|
||||
"Alexa.InputController",
|
||||
"SelectInput",
|
||||
"media_player#test",
|
||||
"media_player.select_source",
|
||||
hass,
|
||||
payload={"input": "HDMI 1"},
|
||||
)
|
||||
assert call.data["source"] == "hdmi"
|
||||
|
||||
call, _ = await assert_request_calls_service(
|
||||
"Alexa.InputController",
|
||||
"SelectInput",
|
||||
"media_player#test",
|
||||
"media_player.select_source",
|
||||
hass,
|
||||
payload={"input": "HDMI 2"},
|
||||
)
|
||||
assert call.data["source"] == "hdmi_2"
|
||||
|
||||
call, _ = await assert_request_calls_service(
|
||||
"Alexa.InputController",
|
||||
"SelectInput",
|
||||
"media_player#test",
|
||||
"media_player.select_source",
|
||||
hass,
|
||||
payload={"input": "HDMI 5"},
|
||||
)
|
||||
assert call.data["source"] == "hdmi 5"
|
||||
|
||||
call, _ = await assert_request_calls_service(
|
||||
"Alexa.InputController",
|
||||
"SelectInput",
|
||||
"media_player#test",
|
||||
"media_player.select_source",
|
||||
hass,
|
||||
payload={"input": "HDMI 6"},
|
||||
)
|
||||
assert call.data["source"] == "HDMI 6"
|
||||
|
||||
call, _ = await assert_request_calls_service(
|
||||
"Alexa.InputController",
|
||||
"SelectInput",
|
||||
"media_player#test",
|
||||
"media_player.select_source",
|
||||
hass,
|
||||
payload={"input": "TV"},
|
||||
)
|
||||
assert call.data["source"] == "tv"
|
||||
|
||||
|
||||
async def test_media_player_speaker(hass):
|
||||
"""Test media player discovery with device class speaker."""
|
||||
device = (
|
||||
|
|
Loading…
Add table
Reference in a new issue