mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add Select entity support to Google Assistant (#51997)
This commit is contained in:
parent
0ca199d8d0
commit
655f797f67
@ -15,6 +15,7 @@ from homeassistant.components import (
|
|||||||
media_player,
|
media_player,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
select,
|
||||||
sensor,
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
@ -39,6 +40,8 @@ CONF_PRIVATE_KEY = "private_key"
|
|||||||
|
|
||||||
DEFAULT_EXPOSE_BY_DEFAULT = True
|
DEFAULT_EXPOSE_BY_DEFAULT = True
|
||||||
DEFAULT_EXPOSED_DOMAINS = [
|
DEFAULT_EXPOSED_DOMAINS = [
|
||||||
|
"alarm_control_panel",
|
||||||
|
"binary_sensor",
|
||||||
"climate",
|
"climate",
|
||||||
"cover",
|
"cover",
|
||||||
"fan",
|
"fan",
|
||||||
@ -47,15 +50,14 @@ DEFAULT_EXPOSED_DOMAINS = [
|
|||||||
"input_boolean",
|
"input_boolean",
|
||||||
"input_select",
|
"input_select",
|
||||||
"light",
|
"light",
|
||||||
|
"lock",
|
||||||
"media_player",
|
"media_player",
|
||||||
"scene",
|
"scene",
|
||||||
"script",
|
"script",
|
||||||
|
"select",
|
||||||
|
"sensor",
|
||||||
"switch",
|
"switch",
|
||||||
"vacuum",
|
"vacuum",
|
||||||
"lock",
|
|
||||||
"binary_sensor",
|
|
||||||
"sensor",
|
|
||||||
"alarm_control_panel",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
PREFIX_TYPES = "action.devices.types."
|
PREFIX_TYPES = "action.devices.types."
|
||||||
@ -117,6 +119,7 @@ EVENT_QUERY_RECEIVED = "google_assistant_query"
|
|||||||
EVENT_SYNC_RECEIVED = "google_assistant_sync"
|
EVENT_SYNC_RECEIVED = "google_assistant_sync"
|
||||||
|
|
||||||
DOMAIN_TO_GOOGLE_TYPES = {
|
DOMAIN_TO_GOOGLE_TYPES = {
|
||||||
|
alarm_control_panel.DOMAIN: TYPE_ALARM,
|
||||||
camera.DOMAIN: TYPE_CAMERA,
|
camera.DOMAIN: TYPE_CAMERA,
|
||||||
climate.DOMAIN: TYPE_THERMOSTAT,
|
climate.DOMAIN: TYPE_THERMOSTAT,
|
||||||
cover.DOMAIN: TYPE_BLINDS,
|
cover.DOMAIN: TYPE_BLINDS,
|
||||||
@ -130,9 +133,9 @@ DOMAIN_TO_GOOGLE_TYPES = {
|
|||||||
media_player.DOMAIN: TYPE_SETTOP,
|
media_player.DOMAIN: TYPE_SETTOP,
|
||||||
scene.DOMAIN: TYPE_SCENE,
|
scene.DOMAIN: TYPE_SCENE,
|
||||||
script.DOMAIN: TYPE_SCENE,
|
script.DOMAIN: TYPE_SCENE,
|
||||||
|
select.DOMAIN: TYPE_SENSOR,
|
||||||
switch.DOMAIN: TYPE_SWITCH,
|
switch.DOMAIN: TYPE_SWITCH,
|
||||||
vacuum.DOMAIN: TYPE_VACUUM,
|
vacuum.DOMAIN: TYPE_VACUUM,
|
||||||
alarm_control_panel.DOMAIN: TYPE_ALARM,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_CLASS_TO_GOOGLE_TYPES = {
|
DEVICE_CLASS_TO_GOOGLE_TYPES = {
|
||||||
|
@ -17,6 +17,7 @@ from homeassistant.components import (
|
|||||||
media_player,
|
media_player,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
select,
|
||||||
sensor,
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
@ -1384,6 +1385,9 @@ class ModesTrait(_Trait):
|
|||||||
if domain == input_select.DOMAIN:
|
if domain == input_select.DOMAIN:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if domain == select.DOMAIN:
|
||||||
|
return True
|
||||||
|
|
||||||
if domain == humidifier.DOMAIN and features & humidifier.SUPPORT_MODES:
|
if domain == humidifier.DOMAIN and features & humidifier.SUPPORT_MODES:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -1427,6 +1431,7 @@ class ModesTrait(_Trait):
|
|||||||
(fan.DOMAIN, fan.ATTR_PRESET_MODES, "preset mode"),
|
(fan.DOMAIN, fan.ATTR_PRESET_MODES, "preset mode"),
|
||||||
(media_player.DOMAIN, media_player.ATTR_SOUND_MODE_LIST, "sound mode"),
|
(media_player.DOMAIN, media_player.ATTR_SOUND_MODE_LIST, "sound mode"),
|
||||||
(input_select.DOMAIN, input_select.ATTR_OPTIONS, "option"),
|
(input_select.DOMAIN, input_select.ATTR_OPTIONS, "option"),
|
||||||
|
(select.DOMAIN, select.ATTR_OPTIONS, "option"),
|
||||||
(humidifier.DOMAIN, humidifier.ATTR_AVAILABLE_MODES, "mode"),
|
(humidifier.DOMAIN, humidifier.ATTR_AVAILABLE_MODES, "mode"),
|
||||||
(light.DOMAIN, light.ATTR_EFFECT_LIST, "effect"),
|
(light.DOMAIN, light.ATTR_EFFECT_LIST, "effect"),
|
||||||
):
|
):
|
||||||
@ -1459,6 +1464,8 @@ class ModesTrait(_Trait):
|
|||||||
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:
|
elif self.state.domain == input_select.DOMAIN:
|
||||||
mode_settings["option"] = self.state.state
|
mode_settings["option"] = self.state.state
|
||||||
|
elif self.state.domain == select.DOMAIN:
|
||||||
|
mode_settings["option"] = self.state.state
|
||||||
elif self.state.domain == humidifier.DOMAIN:
|
elif self.state.domain == humidifier.DOMAIN:
|
||||||
if ATTR_MODE in attrs:
|
if ATTR_MODE in attrs:
|
||||||
mode_settings["mode"] = attrs.get(ATTR_MODE)
|
mode_settings["mode"] = attrs.get(ATTR_MODE)
|
||||||
@ -1503,6 +1510,20 @@ class ModesTrait(_Trait):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.state.domain == select.DOMAIN:
|
||||||
|
option = settings["option"]
|
||||||
|
await self.hass.services.async_call(
|
||||||
|
select.DOMAIN,
|
||||||
|
select.SERVICE_SELECT_OPTION,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: self.state.entity_id,
|
||||||
|
select.ATTR_OPTION: option,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
context=data.context,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
if self.state.domain == humidifier.DOMAIN:
|
if self.state.domain == humidifier.DOMAIN:
|
||||||
requested_mode = settings["mode"]
|
requested_mode = settings["mode"]
|
||||||
await self.hass.services.async_call(
|
await self.hass.services.async_call(
|
||||||
|
@ -41,6 +41,7 @@ BASE_PLATFORMS = {
|
|||||||
"notify",
|
"notify",
|
||||||
"remote",
|
"remote",
|
||||||
"scene",
|
"scene",
|
||||||
|
"select",
|
||||||
"sensor",
|
"sensor",
|
||||||
"switch",
|
"switch",
|
||||||
"tts",
|
"tts",
|
||||||
|
@ -18,6 +18,7 @@ from homeassistant.components import (
|
|||||||
media_player,
|
media_player,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
select,
|
||||||
sensor,
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
@ -1799,6 +1800,80 @@ async def test_modes_input_select(hass):
|
|||||||
assert calls[0].data == {"entity_id": "input_select.bla", "option": "xyz"}
|
assert calls[0].data == {"entity_id": "input_select.bla", "option": "xyz"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_modes_select(hass):
|
||||||
|
"""Test Select Mode trait."""
|
||||||
|
assert helpers.get_google_type(select.DOMAIN, None) is not None
|
||||||
|
assert trait.ModesTrait.supported(select.DOMAIN, None, None, None)
|
||||||
|
|
||||||
|
trt = trait.ModesTrait(
|
||||||
|
hass,
|
||||||
|
State("select.bla", "unavailable"),
|
||||||
|
BASIC_CONFIG,
|
||||||
|
)
|
||||||
|
assert trt.sync_attributes() == {"availableModes": []}
|
||||||
|
|
||||||
|
trt = trait.ModesTrait(
|
||||||
|
hass,
|
||||||
|
State(
|
||||||
|
"select.bla",
|
||||||
|
"abc",
|
||||||
|
attributes={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,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert trt.can_execute(
|
||||||
|
trait.COMMAND_MODES,
|
||||||
|
params={"updateModeSettings": {"option": "xyz"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
calls = async_mock_service(hass, select.DOMAIN, 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": "select.bla", "option": "xyz"}
|
||||||
|
|
||||||
|
|
||||||
async def test_modes_humidifier(hass):
|
async def test_modes_humidifier(hass):
|
||||||
"""Test Humidifier Mode trait."""
|
"""Test Humidifier Mode trait."""
|
||||||
assert helpers.get_google_type(humidifier.DOMAIN, None) is not None
|
assert helpers.get_google_type(humidifier.DOMAIN, None) is not None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user