mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
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
@ -35,6 +35,7 @@ from .const import (
|
|||||||
DATE_FORMAT,
|
DATE_FORMAT,
|
||||||
PERCENTAGE_FAN_MAP,
|
PERCENTAGE_FAN_MAP,
|
||||||
RANGE_FAN_MAP,
|
RANGE_FAN_MAP,
|
||||||
|
Inputs,
|
||||||
)
|
)
|
||||||
from .errors import UnsupportedProperty
|
from .errors import UnsupportedProperty
|
||||||
|
|
||||||
@ -115,6 +116,11 @@ class AlexaCapability:
|
|||||||
"""Return the Configuration object."""
|
"""Return the Configuration object."""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def inputs():
|
||||||
|
"""Applicable only to media players."""
|
||||||
|
return []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def supported_operations():
|
def supported_operations():
|
||||||
"""Return the supportedOperations object."""
|
"""Return the supportedOperations object."""
|
||||||
@ -164,6 +170,10 @@ class AlexaCapability:
|
|||||||
if supported_operations:
|
if supported_operations:
|
||||||
result["supportedOperations"] = supported_operations
|
result["supportedOperations"] = supported_operations
|
||||||
|
|
||||||
|
inputs = self.inputs()
|
||||||
|
if inputs:
|
||||||
|
result["inputs"] = inputs
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def serialize_properties(self):
|
def serialize_properties(self):
|
||||||
@ -531,6 +541,23 @@ class AlexaInputController(AlexaCapability):
|
|||||||
"""Return the Alexa API name of this interface."""
|
"""Return the Alexa API name of this interface."""
|
||||||
return "Alexa.InputController"
|
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):
|
class AlexaTemperatureSensor(AlexaCapability):
|
||||||
"""Implements Alexa.TemperatureSensor.
|
"""Implements Alexa.TemperatureSensor.
|
||||||
|
@ -272,3 +272,84 @@ class Unit:
|
|||||||
WEIGHT_OUNCES = "Alexa.Unit.Weight.Ounces"
|
WEIGHT_OUNCES = "Alexa.Unit.Weight.Ounces"
|
||||||
|
|
||||||
WEIGHT_POUNDS = "Alexa.Unit.Weight.Pounds"
|
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_MODES,
|
||||||
API_THERMOSTAT_PRESETS,
|
API_THERMOSTAT_PRESETS,
|
||||||
Cause,
|
Cause,
|
||||||
|
Inputs,
|
||||||
PERCENTAGE_FAN_MAP,
|
PERCENTAGE_FAN_MAP,
|
||||||
RANGE_FAN_MAP,
|
RANGE_FAN_MAP,
|
||||||
SPEED_FAN_MAP,
|
SPEED_FAN_MAP,
|
||||||
@ -461,13 +462,20 @@ async def async_api_select_input(hass, config, directive, context):
|
|||||||
media_input = directive.payload["input"]
|
media_input = directive.payload["input"]
|
||||||
entity = directive.entity
|
entity = directive.entity
|
||||||
|
|
||||||
# attempt to map the ALL UPPERCASE payload name to a source
|
# Attempt to map the ALL UPPERCASE payload name to a source.
|
||||||
source_list = entity.attributes[media_player.const.ATTR_INPUT_SOURCE_LIST] or []
|
# 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:
|
for source in source_list:
|
||||||
# response will always be space separated, so format the source in the
|
formatted_source = (
|
||||||
# most likely way to find a match
|
source.lower().replace("-", "").replace("_", "").replace(" ", "")
|
||||||
formatted_source = source.lower().replace("-", " ").replace("_", " ")
|
)
|
||||||
if formatted_source in media_input.lower():
|
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
|
media_input = source
|
||||||
break
|
break
|
||||||
else:
|
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):
|
async def test_media_player_speaker(hass):
|
||||||
"""Test media player discovery with device class speaker."""
|
"""Test media player discovery with device class speaker."""
|
||||||
device = (
|
device = (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user