From 66dd3b153d78afeaa76e473434304dc3822b3858 Mon Sep 17 00:00:00 2001 From: Tudor Sandu Date: Wed, 1 Nov 2023 07:46:13 -0700 Subject: [PATCH] Support HassTurnOn/Off intents for lock domain (#93231) * Support HassTurnOn/Off intents for lock domain Fix https://github.com/home-assistant/intents/issues/1347 * Added tests * Linting changes * Linting --- homeassistant/components/intent/__init__.py | 23 ++++++++++++ tests/components/intent/test_init.py | 39 +++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/homeassistant/components/intent/__init__.py b/homeassistant/components/intent/__init__.py index 5d3a2259bed..4d256795f55 100644 --- a/homeassistant/components/intent/__init__.py +++ b/homeassistant/components/intent/__init__.py @@ -10,6 +10,11 @@ from homeassistant.components.cover import ( SERVICE_OPEN_COVER, ) from homeassistant.components.http.data_validator import RequestDataValidator +from homeassistant.components.lock import ( + DOMAIN as LOCK_DOMAIN, + SERVICE_LOCK, + SERVICE_UNLOCK, +) from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TOGGLE, @@ -89,6 +94,24 @@ class OnOffIntentHandler(intent.ServiceIntentHandler): ) return + if state.domain == LOCK_DOMAIN: + # on = lock + # off = unlock + await self._run_then_background( + hass.async_create_task( + hass.services.async_call( + LOCK_DOMAIN, + SERVICE_LOCK + if self.service == SERVICE_TURN_ON + else SERVICE_UNLOCK, + {ATTR_ENTITY_ID: state.entity_id}, + context=intent_obj.context, + blocking=True, + ) + ) + ) + return + if not hass.services.has_service(state.domain, self.service): raise intent.IntentHandleError( f"Service {self.service} does not support entity {state.entity_id}" diff --git a/tests/components/intent/test_init.py b/tests/components/intent/test_init.py index fa8eb9cad61..6e4e00202c8 100644 --- a/tests/components/intent/test_init.py +++ b/tests/components/intent/test_init.py @@ -2,6 +2,7 @@ import pytest from homeassistant.components.cover import SERVICE_OPEN_COVER +from homeassistant.components.lock import SERVICE_LOCK from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_FRIENDLY_NAME, @@ -118,6 +119,44 @@ async def test_turn_on_intent(hass: HomeAssistant) -> None: assert call.data == {"entity_id": ["light.test_light"]} +async def test_translated_turn_on_intent(hass: HomeAssistant) -> None: + """Test HassTurnOn intent on domains which don't have the intent.""" + result = await async_setup_component(hass, "homeassistant", {}) + result = await async_setup_component(hass, "intent", {}) + await hass.async_block_till_done() + assert result + + entity_registry = er.async_get(hass) + + cover = entity_registry.async_get_or_create("cover", "test", "cover_uid") + lock = entity_registry.async_get_or_create("lock", "test", "lock_uid") + + hass.states.async_set(cover.entity_id, "closed") + hass.states.async_set(lock.entity_id, "unlocked") + cover_service_calls = async_mock_service(hass, "cover", SERVICE_OPEN_COVER) + lock_service_calls = async_mock_service(hass, "lock", SERVICE_LOCK) + + await intent.async_handle( + hass, "test", "HassTurnOn", {"name": {"value": cover.entity_id}} + ) + await intent.async_handle( + hass, "test", "HassTurnOn", {"name": {"value": lock.entity_id}} + ) + await hass.async_block_till_done() + + assert len(cover_service_calls) == 1 + call = cover_service_calls[0] + assert call.domain == "cover" + assert call.service == "open_cover" + assert call.data == {"entity_id": cover.entity_id} + + assert len(lock_service_calls) == 1 + call = lock_service_calls[0] + assert call.domain == "lock" + assert call.service == "lock" + assert call.data == {"entity_id": lock.entity_id} + + async def test_turn_off_intent(hass: HomeAssistant) -> None: """Test HassTurnOff intent.""" result = await async_setup_component(hass, "homeassistant", {})