Add support for Google Assistant's LocatorTrait for vacuum cleaners (#55015)
* Support for LocatorTrait for vacuum cleaners * Handle Locator request with `silence: True` * Update homeassistant/components/google_assistant/trait.py Co-authored-by: Joakim Plate <elupus@ecce.se> * Black Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io> Co-authored-by: Joakim Plate <elupus@ecce.se> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>pull/55133/head
parent
ff14a11254
commit
4d7de0fd4c
|
@ -74,6 +74,7 @@ from .const import (
|
||||||
ERR_ALREADY_DISARMED,
|
ERR_ALREADY_DISARMED,
|
||||||
ERR_ALREADY_STOPPED,
|
ERR_ALREADY_STOPPED,
|
||||||
ERR_CHALLENGE_NOT_SETUP,
|
ERR_CHALLENGE_NOT_SETUP,
|
||||||
|
ERR_FUNCTION_NOT_SUPPORTED,
|
||||||
ERR_NO_AVAILABLE_CHANNEL,
|
ERR_NO_AVAILABLE_CHANNEL,
|
||||||
ERR_NOT_SUPPORTED,
|
ERR_NOT_SUPPORTED,
|
||||||
ERR_UNSUPPORTED_INPUT,
|
ERR_UNSUPPORTED_INPUT,
|
||||||
|
@ -104,6 +105,7 @@ TRAIT_HUMIDITY_SETTING = f"{PREFIX_TRAITS}HumiditySetting"
|
||||||
TRAIT_TRANSPORT_CONTROL = f"{PREFIX_TRAITS}TransportControl"
|
TRAIT_TRANSPORT_CONTROL = f"{PREFIX_TRAITS}TransportControl"
|
||||||
TRAIT_MEDIA_STATE = f"{PREFIX_TRAITS}MediaState"
|
TRAIT_MEDIA_STATE = f"{PREFIX_TRAITS}MediaState"
|
||||||
TRAIT_CHANNEL = f"{PREFIX_TRAITS}Channel"
|
TRAIT_CHANNEL = f"{PREFIX_TRAITS}Channel"
|
||||||
|
TRAIT_LOCATOR = f"{PREFIX_TRAITS}Locator"
|
||||||
|
|
||||||
PREFIX_COMMANDS = "action.devices.commands."
|
PREFIX_COMMANDS = "action.devices.commands."
|
||||||
COMMAND_ONOFF = f"{PREFIX_COMMANDS}OnOff"
|
COMMAND_ONOFF = f"{PREFIX_COMMANDS}OnOff"
|
||||||
|
@ -145,6 +147,7 @@ COMMAND_MEDIA_STOP = f"{PREFIX_COMMANDS}mediaStop"
|
||||||
COMMAND_REVERSE = f"{PREFIX_COMMANDS}Reverse"
|
COMMAND_REVERSE = f"{PREFIX_COMMANDS}Reverse"
|
||||||
COMMAND_SET_HUMIDITY = f"{PREFIX_COMMANDS}SetHumidity"
|
COMMAND_SET_HUMIDITY = f"{PREFIX_COMMANDS}SetHumidity"
|
||||||
COMMAND_SELECT_CHANNEL = f"{PREFIX_COMMANDS}selectChannel"
|
COMMAND_SELECT_CHANNEL = f"{PREFIX_COMMANDS}selectChannel"
|
||||||
|
COMMAND_LOCATE = f"{PREFIX_COMMANDS}Locate"
|
||||||
|
|
||||||
TRAITS = []
|
TRAITS = []
|
||||||
|
|
||||||
|
@ -566,6 +569,46 @@ class DockTrait(_Trait):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register_trait
|
||||||
|
class LocatorTrait(_Trait):
|
||||||
|
"""Trait to offer locate functionality.
|
||||||
|
|
||||||
|
https://developers.google.com/actions/smarthome/traits/locator
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = TRAIT_LOCATOR
|
||||||
|
commands = [COMMAND_LOCATE]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def supported(domain, features, device_class, _):
|
||||||
|
"""Test if state is supported."""
|
||||||
|
return domain == vacuum.DOMAIN and features & vacuum.SUPPORT_LOCATE
|
||||||
|
|
||||||
|
def sync_attributes(self):
|
||||||
|
"""Return locator attributes for a sync request."""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def query_attributes(self):
|
||||||
|
"""Return locator query attributes."""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
async def execute(self, command, data, params, challenge):
|
||||||
|
"""Execute a locate command."""
|
||||||
|
if params.get("silence", False):
|
||||||
|
raise SmartHomeError(
|
||||||
|
ERR_FUNCTION_NOT_SUPPORTED,
|
||||||
|
"Silencing a Locate request is not yet supported",
|
||||||
|
)
|
||||||
|
|
||||||
|
await self.hass.services.async_call(
|
||||||
|
self.state.domain,
|
||||||
|
vacuum.SERVICE_LOCATE,
|
||||||
|
{ATTR_ENTITY_ID: self.state.entity_id},
|
||||||
|
blocking=True,
|
||||||
|
context=data.context,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@register_trait
|
@register_trait
|
||||||
class StartStopTrait(_Trait):
|
class StartStopTrait(_Trait):
|
||||||
"""Trait to offer StartStop functionality.
|
"""Trait to offer StartStop functionality.
|
||||||
|
|
|
@ -356,6 +356,37 @@ async def test_dock_vacuum(hass):
|
||||||
assert calls[0].data == {ATTR_ENTITY_ID: "vacuum.bla"}
|
assert calls[0].data == {ATTR_ENTITY_ID: "vacuum.bla"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_locate_vacuum(hass):
|
||||||
|
"""Test locate trait support for vacuum domain."""
|
||||||
|
assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
|
||||||
|
assert trait.LocatorTrait.supported(
|
||||||
|
vacuum.DOMAIN, vacuum.SUPPORT_LOCATE, None, None
|
||||||
|
)
|
||||||
|
|
||||||
|
trt = trait.LocatorTrait(
|
||||||
|
hass,
|
||||||
|
State(
|
||||||
|
"vacuum.bla",
|
||||||
|
vacuum.STATE_IDLE,
|
||||||
|
{ATTR_SUPPORTED_FEATURES: vacuum.SUPPORT_LOCATE},
|
||||||
|
),
|
||||||
|
BASIC_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert trt.sync_attributes() == {}
|
||||||
|
|
||||||
|
assert trt.query_attributes() == {}
|
||||||
|
|
||||||
|
calls = async_mock_service(hass, vacuum.DOMAIN, vacuum.SERVICE_LOCATE)
|
||||||
|
await trt.execute(trait.COMMAND_LOCATE, BASIC_DATA, {"silence": False}, {})
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0].data == {ATTR_ENTITY_ID: "vacuum.bla"}
|
||||||
|
|
||||||
|
with pytest.raises(helpers.SmartHomeError) as err:
|
||||||
|
await trt.execute(trait.COMMAND_LOCATE, BASIC_DATA, {"silence": True}, {})
|
||||||
|
assert err.value.code == const.ERR_FUNCTION_NOT_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
async def test_startstop_vacuum(hass):
|
async def test_startstop_vacuum(hass):
|
||||||
"""Test startStop trait support for vacuum domain."""
|
"""Test startStop trait support for vacuum domain."""
|
||||||
assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
|
assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
|
||||||
|
|
Loading…
Reference in New Issue