mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Implement google_assistant ModesTrait for input_select (#36313)
This commit is contained in:
parent
a333417ddf
commit
47706dac1a
@ -8,6 +8,7 @@ from homeassistant.components import (
|
|||||||
fan,
|
fan,
|
||||||
group,
|
group,
|
||||||
input_boolean,
|
input_boolean,
|
||||||
|
input_select,
|
||||||
light,
|
light,
|
||||||
lock,
|
lock,
|
||||||
media_player,
|
media_player,
|
||||||
@ -44,6 +45,7 @@ DEFAULT_EXPOSED_DOMAINS = [
|
|||||||
"fan",
|
"fan",
|
||||||
"group",
|
"group",
|
||||||
"input_boolean",
|
"input_boolean",
|
||||||
|
"input_select",
|
||||||
"light",
|
"light",
|
||||||
"media_player",
|
"media_player",
|
||||||
"scene",
|
"scene",
|
||||||
@ -113,6 +115,7 @@ DOMAIN_TO_GOOGLE_TYPES = {
|
|||||||
fan.DOMAIN: TYPE_FAN,
|
fan.DOMAIN: TYPE_FAN,
|
||||||
group.DOMAIN: TYPE_SWITCH,
|
group.DOMAIN: TYPE_SWITCH,
|
||||||
input_boolean.DOMAIN: TYPE_SWITCH,
|
input_boolean.DOMAIN: TYPE_SWITCH,
|
||||||
|
input_select.DOMAIN: TYPE_SENSOR,
|
||||||
light.DOMAIN: TYPE_LIGHT,
|
light.DOMAIN: TYPE_LIGHT,
|
||||||
lock.DOMAIN: TYPE_LOCK,
|
lock.DOMAIN: TYPE_LOCK,
|
||||||
media_player.DOMAIN: TYPE_SETTOP,
|
media_player.DOMAIN: TYPE_SETTOP,
|
||||||
|
@ -9,6 +9,7 @@ from homeassistant.components import (
|
|||||||
fan,
|
fan,
|
||||||
group,
|
group,
|
||||||
input_boolean,
|
input_boolean,
|
||||||
|
input_select,
|
||||||
light,
|
light,
|
||||||
lock,
|
lock,
|
||||||
media_player,
|
media_player,
|
||||||
@ -1131,11 +1132,15 @@ class ModesTrait(_Trait):
|
|||||||
SYNONYMS = {
|
SYNONYMS = {
|
||||||
"input source": ["input source", "input", "source"],
|
"input source": ["input source", "input", "source"],
|
||||||
"sound mode": ["sound mode", "effects"],
|
"sound mode": ["sound mode", "effects"],
|
||||||
|
"option": ["option", "setting", "mode", "value"],
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def supported(domain, features, device_class):
|
def supported(domain, features, device_class):
|
||||||
"""Test if state is supported."""
|
"""Test if state is supported."""
|
||||||
|
if domain == input_select.DOMAIN:
|
||||||
|
return True
|
||||||
|
|
||||||
if domain != media_player.DOMAIN:
|
if domain != media_player.DOMAIN:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -1174,15 +1179,20 @@ class ModesTrait(_Trait):
|
|||||||
|
|
||||||
attrs = self.state.attributes
|
attrs = self.state.attributes
|
||||||
modes = []
|
modes = []
|
||||||
|
if self.state.domain == media_player.DOMAIN:
|
||||||
if media_player.ATTR_INPUT_SOURCE_LIST in attrs:
|
if media_player.ATTR_INPUT_SOURCE_LIST in attrs:
|
||||||
modes.append(
|
modes.append(
|
||||||
_generate("input source", attrs[media_player.ATTR_INPUT_SOURCE_LIST])
|
_generate(
|
||||||
|
"input source", attrs[media_player.ATTR_INPUT_SOURCE_LIST]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if media_player.ATTR_SOUND_MODE_LIST in attrs:
|
if media_player.ATTR_SOUND_MODE_LIST in attrs:
|
||||||
modes.append(
|
modes.append(
|
||||||
_generate("sound mode", attrs[media_player.ATTR_SOUND_MODE_LIST])
|
_generate("sound mode", attrs[media_player.ATTR_SOUND_MODE_LIST])
|
||||||
)
|
)
|
||||||
|
elif self.state.domain == input_select.DOMAIN:
|
||||||
|
modes.append(_generate("option", attrs[input_select.ATTR_OPTIONS]))
|
||||||
|
|
||||||
payload = {"availableModes": modes}
|
payload = {"availableModes": modes}
|
||||||
|
|
||||||
@ -1194,11 +1204,16 @@ class ModesTrait(_Trait):
|
|||||||
response = {}
|
response = {}
|
||||||
mode_settings = {}
|
mode_settings = {}
|
||||||
|
|
||||||
|
if self.state.domain == media_player.DOMAIN:
|
||||||
if media_player.ATTR_INPUT_SOURCE_LIST in attrs:
|
if media_player.ATTR_INPUT_SOURCE_LIST in attrs:
|
||||||
mode_settings["input source"] = attrs.get(media_player.ATTR_INPUT_SOURCE)
|
mode_settings["input source"] = attrs.get(
|
||||||
|
media_player.ATTR_INPUT_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
if media_player.ATTR_SOUND_MODE_LIST in attrs:
|
if media_player.ATTR_SOUND_MODE_LIST in attrs:
|
||||||
mode_settings["sound mode"] = attrs.get(media_player.ATTR_SOUND_MODE)
|
mode_settings["sound mode"] = attrs.get(media_player.ATTR_SOUND_MODE)
|
||||||
|
elif self.state.domain == input_select.DOMAIN:
|
||||||
|
mode_settings["option"] = self.state.state
|
||||||
|
|
||||||
if mode_settings:
|
if mode_settings:
|
||||||
response["on"] = self.state.state != STATE_OFF
|
response["on"] = self.state.state != STATE_OFF
|
||||||
@ -1210,6 +1225,28 @@ class ModesTrait(_Trait):
|
|||||||
async def execute(self, command, data, params, challenge):
|
async def execute(self, command, data, params, challenge):
|
||||||
"""Execute an SetModes command."""
|
"""Execute an SetModes command."""
|
||||||
settings = params.get("updateModeSettings")
|
settings = params.get("updateModeSettings")
|
||||||
|
|
||||||
|
if self.state.domain == input_select.DOMAIN:
|
||||||
|
option = params["updateModeSettings"]["option"]
|
||||||
|
await self.hass.services.async_call(
|
||||||
|
input_select.DOMAIN,
|
||||||
|
input_select.SERVICE_SELECT_OPTION,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: self.state.entity_id,
|
||||||
|
input_select.ATTR_OPTION: option,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
context=data.context,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
if self.state.domain != media_player.DOMAIN:
|
||||||
|
_LOGGER.info(
|
||||||
|
"Received an Options command for unrecognised domain %s",
|
||||||
|
self.state.domain,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
requested_source = settings.get("input source")
|
requested_source = settings.get("input source")
|
||||||
sound_mode = settings.get("sound mode")
|
sound_mode = settings.get("sound mode")
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ from homeassistant.components import (
|
|||||||
fan,
|
fan,
|
||||||
group,
|
group,
|
||||||
input_boolean,
|
input_boolean,
|
||||||
|
input_select,
|
||||||
light,
|
light,
|
||||||
lock,
|
lock,
|
||||||
media_player,
|
media_player,
|
||||||
@ -1267,8 +1268,8 @@ async def test_fan_speed(hass):
|
|||||||
assert calls[0].data == {"entity_id": "fan.living_room_fan", "speed": "medium"}
|
assert calls[0].data == {"entity_id": "fan.living_room_fan", "speed": "medium"}
|
||||||
|
|
||||||
|
|
||||||
async def test_modes(hass):
|
async def test_modes_media_player(hass):
|
||||||
"""Test Mode trait."""
|
"""Test Media Player Mode trait."""
|
||||||
assert helpers.get_google_type(media_player.DOMAIN, None) is not None
|
assert helpers.get_google_type(media_player.DOMAIN, None) is not None
|
||||||
assert trait.ModesTrait.supported(
|
assert trait.ModesTrait.supported(
|
||||||
media_player.DOMAIN, media_player.SUPPORT_SELECT_SOURCE, None
|
media_player.DOMAIN, media_player.SUPPORT_SELECT_SOURCE, None
|
||||||
@ -1351,6 +1352,72 @@ async def test_modes(hass):
|
|||||||
assert calls[0].data == {"entity_id": "media_player.living_room", "source": "media"}
|
assert calls[0].data == {"entity_id": "media_player.living_room", "source": "media"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_modes_input_select(hass):
|
||||||
|
"""Test Input Select Mode trait."""
|
||||||
|
assert helpers.get_google_type(input_select.DOMAIN, None) is not None
|
||||||
|
assert trait.ModesTrait.supported(input_select.DOMAIN, None, None)
|
||||||
|
|
||||||
|
trt = trait.ModesTrait(
|
||||||
|
hass,
|
||||||
|
State(
|
||||||
|
"input_select.bla",
|
||||||
|
"abc",
|
||||||
|
attributes={input_select.ATTR_OPTIONS: ["abc", "123", "xyz"]},
|
||||||
|
),
|
||||||
|
BASIC_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
attribs = trt.sync_attributes()
|
||||||
|
assert attribs == {
|
||||||
|
"availableModes": [
|
||||||
|
{
|
||||||
|
"name": "option",
|
||||||
|
"name_values": [
|
||||||
|
{
|
||||||
|
"name_synonym": ["option", "setting", "mode", "value"],
|
||||||
|
"lang": "en",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"setting_name": "abc",
|
||||||
|
"setting_values": [{"setting_synonym": ["abc"], "lang": "en"}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"setting_name": "123",
|
||||||
|
"setting_values": [{"setting_synonym": ["123"], "lang": "en"}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"setting_name": "xyz",
|
||||||
|
"setting_values": [{"setting_synonym": ["xyz"], "lang": "en"}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"ordered": False,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert trt.query_attributes() == {
|
||||||
|
"currentModeSettings": {"option": "abc"},
|
||||||
|
"on": True,
|
||||||
|
"online": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert trt.can_execute(
|
||||||
|
trait.COMMAND_MODES, params={"updateModeSettings": {"option": "xyz"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
calls = async_mock_service(
|
||||||
|
hass, input_select.DOMAIN, input_select.SERVICE_SELECT_OPTION
|
||||||
|
)
|
||||||
|
await trt.execute(
|
||||||
|
trait.COMMAND_MODES, BASIC_DATA, {"updateModeSettings": {"option": "xyz"}}, {},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0].data == {"entity_id": "input_select.bla", "option": "xyz"}
|
||||||
|
|
||||||
|
|
||||||
async def test_sound_modes(hass):
|
async def test_sound_modes(hass):
|
||||||
"""Test Mode trait."""
|
"""Test Mode trait."""
|
||||||
assert helpers.get_google_type(media_player.DOMAIN, None) is not None
|
assert helpers.get_google_type(media_player.DOMAIN, None) is not None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user