From 22b56906078c4f17bacb6b07c9f24e26e842edd4 Mon Sep 17 00:00:00 2001 From: Thomas Hollstegge Date: Mon, 9 Mar 2020 16:58:47 +0100 Subject: [PATCH] Alexa: Support vacuums without turn_on/turn_off feature (#32570) * Alexa: Support vacuums without turn_on/turn_off feature --- .../components/alexa/capabilities.py | 2 + homeassistant/components/alexa/entities.py | 7 +- homeassistant/components/alexa/handlers.py | 11 ++ tests/components/alexa/test_smart_home.py | 102 ++++++++++++++++++ 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alexa/capabilities.py b/homeassistant/components/alexa/capabilities.py index 8b38fe4d298..4f675fa8375 100644 --- a/homeassistant/components/alexa/capabilities.py +++ b/homeassistant/components/alexa/capabilities.py @@ -364,6 +364,8 @@ class AlexaPowerController(AlexaCapability): if self.entity.domain == climate.DOMAIN: is_on = self.entity.state != climate.HVAC_MODE_OFF + elif self.entity.domain == vacuum.DOMAIN: + is_on = self.entity.state == vacuum.STATE_CLEANING else: is_on = self.entity.state != STATE_OFF diff --git a/homeassistant/components/alexa/entities.py b/homeassistant/components/alexa/entities.py index f7b9af4c8fe..df3be7ee85e 100644 --- a/homeassistant/components/alexa/entities.py +++ b/homeassistant/components/alexa/entities.py @@ -741,8 +741,11 @@ class VacuumCapabilities(AlexaEntity): def interfaces(self): """Yield the supported interfaces.""" supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) - if (supported & vacuum.SUPPORT_TURN_ON) and ( - supported & vacuum.SUPPORT_TURN_OFF + if ( + (supported & vacuum.SUPPORT_TURN_ON) or (supported & vacuum.SUPPORT_START) + ) and ( + (supported & vacuum.SUPPORT_TURN_OFF) + or (supported & vacuum.SUPPORT_RETURN_HOME) ): yield AlexaPowerController(self.entity) diff --git a/homeassistant/components/alexa/handlers.py b/homeassistant/components/alexa/handlers.py index b771a8fc50c..a77051cb03b 100644 --- a/homeassistant/components/alexa/handlers.py +++ b/homeassistant/components/alexa/handlers.py @@ -121,6 +121,10 @@ async def async_api_turn_on(hass, config, directive, context): service = SERVICE_TURN_ON if domain == cover.DOMAIN: service = cover.SERVICE_OPEN_COVER + elif domain == vacuum.DOMAIN: + supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + if not supported & vacuum.SUPPORT_TURN_ON and supported & vacuum.SUPPORT_START: + service = vacuum.SERVICE_START elif domain == media_player.DOMAIN: supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) power_features = media_player.SUPPORT_TURN_ON | media_player.SUPPORT_TURN_OFF @@ -149,6 +153,13 @@ async def async_api_turn_off(hass, config, directive, context): service = SERVICE_TURN_OFF if entity.domain == cover.DOMAIN: service = cover.SERVICE_CLOSE_COVER + elif domain == vacuum.DOMAIN: + supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + if ( + not supported & vacuum.SUPPORT_TURN_OFF + and supported & vacuum.SUPPORT_RETURN_HOME + ): + service = vacuum.SERVICE_RETURN_TO_BASE elif domain == media_player.DOMAIN: supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) power_features = media_player.SUPPORT_TURN_ON | media_player.SUPPORT_TURN_OFF diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index 6190403f20e..f723832938a 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -3386,6 +3386,7 @@ async def test_vacuum_discovery(hass): | vacuum.SUPPORT_TURN_OFF | vacuum.SUPPORT_START | vacuum.SUPPORT_STOP + | vacuum.SUPPORT_RETURN_HOME | vacuum.SUPPORT_PAUSE, }, ) @@ -3403,6 +3404,17 @@ async def test_vacuum_discovery(hass): "Alexa", ) + properties = await reported_properties(hass, "vacuum#test_1") + properties.assert_equal("Alexa.PowerController", "powerState", "OFF") + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOn", "vacuum#test_1", "vacuum.turn_on", hass, + ) + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOff", "vacuum#test_1", "vacuum.turn_off", hass, + ) + async def test_vacuum_fan_speed(hass): """Test vacuum fan speed with rangeController.""" @@ -3597,3 +3609,93 @@ async def test_vacuum_resume(hass): "vacuum.start_pause", hass, ) + + +async def test_vacuum_discovery_no_turn_on(hass): + """Test vacuum discovery for vacuums without turn_on.""" + device = ( + "vacuum.test_5", + "cleaning", + { + "friendly_name": "Test vacuum 5", + "supported_features": vacuum.SUPPORT_TURN_OFF + | vacuum.SUPPORT_START + | vacuum.SUPPORT_RETURN_HOME, + }, + ) + appliance = await discovery_test(device, hass) + + assert_endpoint_capabilities( + appliance, "Alexa.PowerController", "Alexa.EndpointHealth", "Alexa", + ) + + properties = await reported_properties(hass, "vacuum#test_5") + properties.assert_equal("Alexa.PowerController", "powerState", "ON") + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOn", "vacuum#test_5", "vacuum.start", hass, + ) + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOff", "vacuum#test_5", "vacuum.turn_off", hass, + ) + + +async def test_vacuum_discovery_no_turn_off(hass): + """Test vacuum discovery for vacuums without turn_off.""" + device = ( + "vacuum.test_6", + "cleaning", + { + "friendly_name": "Test vacuum 6", + "supported_features": vacuum.SUPPORT_TURN_ON + | vacuum.SUPPORT_START + | vacuum.SUPPORT_RETURN_HOME, + }, + ) + appliance = await discovery_test(device, hass) + + assert_endpoint_capabilities( + appliance, "Alexa.PowerController", "Alexa.EndpointHealth", "Alexa", + ) + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOn", "vacuum#test_6", "vacuum.turn_on", hass, + ) + + await assert_request_calls_service( + "Alexa.PowerController", + "TurnOff", + "vacuum#test_6", + "vacuum.return_to_base", + hass, + ) + + +async def test_vacuum_discovery_no_turn_on_or_off(hass): + """Test vacuum discovery vacuums without on or off.""" + device = ( + "vacuum.test_7", + "cleaning", + { + "friendly_name": "Test vacuum 7", + "supported_features": vacuum.SUPPORT_START | vacuum.SUPPORT_RETURN_HOME, + }, + ) + appliance = await discovery_test(device, hass) + + assert_endpoint_capabilities( + appliance, "Alexa.PowerController", "Alexa.EndpointHealth", "Alexa", + ) + + await assert_request_calls_service( + "Alexa.PowerController", "TurnOn", "vacuum#test_7", "vacuum.start", hass, + ) + + await assert_request_calls_service( + "Alexa.PowerController", + "TurnOff", + "vacuum#test_7", + "vacuum.return_to_base", + hass, + )