diff --git a/homeassistant/components/google_assistant/const.py b/homeassistant/components/google_assistant/const.py index d23560b85c1..269c0aafea1 100644 --- a/homeassistant/components/google_assistant/const.py +++ b/homeassistant/components/google_assistant/const.py @@ -2,6 +2,7 @@ from homeassistant.components import ( alarm_control_panel, binary_sensor, + button, camera, climate, cover, @@ -120,6 +121,7 @@ EVENT_SYNC_RECEIVED = "google_assistant_sync" DOMAIN_TO_GOOGLE_TYPES = { alarm_control_panel.DOMAIN: TYPE_ALARM, + button.DOMAIN: TYPE_SCENE, camera.DOMAIN: TYPE_CAMERA, climate.DOMAIN: TYPE_THERMOSTAT, cover.DOMAIN: TYPE_BLINDS, diff --git a/homeassistant/components/google_assistant/trait.py b/homeassistant/components/google_assistant/trait.py index 66df9315220..5801ae6811b 100644 --- a/homeassistant/components/google_assistant/trait.py +++ b/homeassistant/components/google_assistant/trait.py @@ -6,6 +6,7 @@ import logging from homeassistant.components import ( alarm_control_panel, binary_sensor, + button, camera, cover, fan, @@ -513,11 +514,11 @@ class SceneTrait(_Trait): @staticmethod def supported(domain, features, device_class, _): """Test if state is supported.""" - return domain in (scene.DOMAIN, script.DOMAIN) + return domain in (button.DOMAIN, scene.DOMAIN, script.DOMAIN) def sync_attributes(self): """Return scene attributes for a sync request.""" - # Neither supported domain can support sceneReversible + # None of the supported domains can support sceneReversible return {} def query_attributes(self): @@ -526,12 +527,16 @@ class SceneTrait(_Trait): async def execute(self, command, data, params, challenge): """Execute a scene command.""" - # Don't block for scripts as they can be slow. + service = SERVICE_TURN_ON + if self.state.domain == button.DOMAIN: + service = button.SERVICE_PRESS + + # Don't block for scripts or buttons, as they can be slow. await self.hass.services.async_call( self.state.domain, - SERVICE_TURN_ON, + service, {ATTR_ENTITY_ID: self.state.entity_id}, - blocking=self.state.domain != script.DOMAIN, + blocking=self.state.domain not in (button.DOMAIN, script.DOMAIN), context=data.context, ) diff --git a/script/hassfest/dependencies.py b/script/hassfest/dependencies.py index 9e66e05899c..3f0bd9c1236 100644 --- a/script/hassfest/dependencies.py +++ b/script/hassfest/dependencies.py @@ -94,6 +94,7 @@ ALLOWED_USED_COMPONENTS = { # Internal integrations "alert", "automation", + "button", "conversation", "button", "device_automation", diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index 62a9d7a0120..a396c1bc91d 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -7,6 +7,7 @@ import pytest from homeassistant.components import ( alarm_control_panel, binary_sensor, + button, camera, cover, fan, @@ -767,6 +768,26 @@ async def test_light_modes(hass): } +async def test_scene_button(hass): + """Test Scene trait support for the button domain.""" + assert helpers.get_google_type(button.DOMAIN, None) is not None + assert trait.SceneTrait.supported(button.DOMAIN, 0, None, None) + + trt = trait.SceneTrait(hass, State("button.bla", STATE_UNKNOWN), BASIC_CONFIG) + assert trt.sync_attributes() == {} + assert trt.query_attributes() == {} + assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {}) + + calls = async_mock_service(hass, button.DOMAIN, button.SERVICE_PRESS) + await trt.execute(trait.COMMAND_ACTIVATE_SCENE, BASIC_DATA, {}, {}) + + # We don't wait till button press is done. + await hass.async_block_till_done() + + assert len(calls) == 1 + assert calls[0].data == {ATTR_ENTITY_ID: "button.bla"} + + async def test_scene_scene(hass): """Test Scene trait support for scene domain.""" assert helpers.get_google_type(scene.DOMAIN, None) is not None