From 02ad93db5338b68172869474e07718c96f9ef339 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 26 Jun 2023 18:14:23 +0200 Subject: [PATCH] Use entity registry id in cover device conditions (#95253) --- .../components/cover/device_condition.py | 14 +- .../components/cover/test_device_condition.py | 130 +++++++++++++++--- 2 files changed, 119 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/cover/device_condition.py b/homeassistant/components/cover/device_condition.py index 6144bdb6dbf..2aa0a1dd2fb 100644 --- a/homeassistant/components/cover/device_condition.py +++ b/homeassistant/components/cover/device_condition.py @@ -4,7 +4,6 @@ from __future__ import annotations import voluptuous as vol from homeassistant.const import ( - ATTR_ENTITY_ID, CONF_ABOVE, CONF_BELOW, CONF_CONDITION, @@ -43,7 +42,7 @@ STATE_CONDITION_TYPES = {"is_open", "is_closed", "is_opening", "is_closing"} POSITION_CONDITION_SCHEMA = vol.All( DEVICE_CONDITION_BASE_SCHEMA.extend( { - vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid, vol.Required(CONF_TYPE): vol.In(POSITION_CONDITION_TYPES), vol.Optional(CONF_ABOVE): vol.All( vol.Coerce(int), vol.Range(min=0, max=100) @@ -58,7 +57,7 @@ POSITION_CONDITION_SCHEMA = vol.All( STATE_CONDITION_SCHEMA = DEVICE_CONDITION_BASE_SCHEMA.extend( { - vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid, vol.Required(CONF_TYPE): vol.In(STATE_CONDITION_TYPES), } ) @@ -86,7 +85,7 @@ async def async_get_conditions( CONF_CONDITION: "device", CONF_DEVICE_ID: device_id, CONF_DOMAIN: DOMAIN, - CONF_ENTITY_ID: entry.entity_id, + CONF_ENTITY_ID: entry.id, } if supports_open_close: @@ -127,6 +126,9 @@ def async_condition_from_config( hass: HomeAssistant, config: ConfigType ) -> condition.ConditionCheckerType: """Create a function to test a device condition.""" + registry = er.async_get(hass) + entity_id = er.async_resolve_entity_id(registry, config[CONF_ENTITY_ID]) + if config[CONF_TYPE] in STATE_CONDITION_TYPES: if config[CONF_TYPE] == "is_open": state = STATE_OPEN @@ -139,7 +141,7 @@ def async_condition_from_config( def test_is_state(hass: HomeAssistant, variables: TemplateVarsType) -> bool: """Test if an entity is a certain state.""" - return condition.state(hass, config[ATTR_ENTITY_ID], state) + return condition.state(hass, entity_id, state) return test_is_state @@ -156,7 +158,7 @@ def async_condition_from_config( ) -> bool: """Return whether the criteria are met.""" return condition.async_numeric_state( - hass, config[ATTR_ENTITY_ID], max_pos, min_pos, attribute=position_attr + hass, entity_id, max_pos, min_pos, attribute=position_attr ) return check_numeric_state diff --git a/tests/components/cover/test_device_condition.py b/tests/components/cover/test_device_condition.py index 534c2b027a1..bfde3a0b514 100644 --- a/tests/components/cover/test_device_condition.py +++ b/tests/components/cover/test_device_condition.py @@ -89,7 +89,7 @@ async def test_get_conditions( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) - entity_registry.async_get_or_create( + entity_entry = entity_registry.async_get_or_create( DOMAIN, "test", "5678", @@ -109,7 +109,7 @@ async def test_get_conditions( "domain": DOMAIN, "type": condition, "device_id": device_entry.id, - "entity_id": f"{DOMAIN}.test_5678", + "entity_id": entity_entry.id, "metadata": {"secondary": False}, } for condition in expected_condition_types @@ -143,7 +143,7 @@ async def test_get_conditions_hidden_auxiliary( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) - entity_registry.async_get_or_create( + entity_entry = entity_registry.async_get_or_create( DOMAIN, "test", "5678", @@ -158,7 +158,7 @@ async def test_get_conditions_hidden_auxiliary( "domain": DOMAIN, "type": condition, "device_id": device_entry.id, - "entity_id": f"{DOMAIN}.test_5678", + "entity_id": entity_entry.id, "metadata": {"secondary": True}, } for condition in ["is_open", "is_closed", "is_opening", "is_closing"] @@ -203,6 +203,43 @@ async def test_get_condition_capabilities( assert capabilities == {"extra_fields": []} +async def test_get_condition_capabilities_legacy( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + entity_registry: er.EntityRegistry, + enable_custom_integrations: None, +) -> None: + """Test we get the expected capabilities from a cover condition.""" + platform = getattr(hass.components, f"test.{DOMAIN}") + platform.init() + ent = platform.ENTITIES[0] + assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}}) + await hass.async_block_till_done() + + config_entry = MockConfigEntry(domain="test", data={}) + config_entry.add_to_hass(hass) + device_entry = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, + ) + entity_registry.async_get_or_create( + DOMAIN, "test", ent.unique_id, device_id=device_entry.id + ) + + conditions = await async_get_device_automations( + hass, DeviceAutomationType.CONDITION, device_entry.id + ) + assert len(conditions) == 4 + for condition in conditions: + condition["entity_id"] = entity_registry.async_get( + condition["entity_id"] + ).entity_id + capabilities = await async_get_device_automation_capabilities( + hass, DeviceAutomationType.CONDITION, condition + ) + assert capabilities == {"extra_fields": []} + + async def test_get_condition_capabilities_set_pos( hass: HomeAssistant, device_registry: dr.DeviceRegistry, @@ -317,9 +354,13 @@ async def test_get_condition_capabilities_set_tilt_pos( assert capabilities == {"extra_fields": []} -async def test_if_state(hass: HomeAssistant, calls) -> None: +async def test_if_state( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: """Test for turn_on and turn_off conditions.""" - hass.states.async_set("cover.entity", STATE_OPEN) + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_OPEN) assert await async_setup_component( hass, @@ -333,7 +374,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": "cover.entity", + "entity_id": entry.id, "type": "is_open", } ], @@ -355,7 +396,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": "cover.entity", + "entity_id": entry.id, "type": "is_closed", } ], @@ -377,7 +418,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": "cover.entity", + "entity_id": entry.id, "type": "is_opening", } ], @@ -399,7 +440,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": "cover.entity", + "entity_id": entry.id, "type": "is_closing", } ], @@ -423,21 +464,21 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: assert len(calls) == 1 assert calls[0].data["some"] == "is_open - event - test_event1" - hass.states.async_set("cover.entity", STATE_CLOSED) + hass.states.async_set(entry.entity_id, STATE_CLOSED) hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event2") await hass.async_block_till_done() assert len(calls) == 2 assert calls[1].data["some"] == "is_closed - event - test_event2" - hass.states.async_set("cover.entity", STATE_OPENING) + hass.states.async_set(entry.entity_id, STATE_OPENING) hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event3") await hass.async_block_till_done() assert len(calls) == 3 assert calls[2].data["some"] == "is_opening - event - test_event3" - hass.states.async_set("cover.entity", STATE_CLOSING) + hass.states.async_set(entry.entity_id, STATE_CLOSING) hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event4") await hass.async_block_till_done() @@ -445,8 +486,54 @@ async def test_if_state(hass: HomeAssistant, calls) -> None: assert calls[3].data["some"] == "is_closing - event - test_event4" +async def test_if_state_legacy( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: + """Test for turn_on and turn_off conditions.""" + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_OPEN) + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": {"platform": "event", "event_type": "test_event1"}, + "condition": [ + { + "condition": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": entry.entity_id, + "type": "is_open", + } + ], + "action": { + "service": "test.automation", + "data_template": { + "some": ( + "is_open " + "- {{ trigger.platform }} " + "- {{ trigger.event.event_type }}" + ) + }, + }, + }, + ] + }, + ) + hass.bus.async_fire("test_event1") + hass.bus.async_fire("test_event2") + await hass.async_block_till_done() + assert len(calls) == 1 + assert calls[0].data["some"] == "is_open - event - test_event1" + + async def test_if_position( hass: HomeAssistant, + entity_registry: er.EntityRegistry, calls, caplog: pytest.LogCaptureFixture, enable_custom_integrations: None, @@ -458,6 +545,8 @@ async def test_if_position( assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}}) await hass.async_block_till_done() + entry = entity_registry.async_get(ent.entity_id) + assert await async_setup_component( hass, automation.DOMAIN, @@ -471,7 +560,7 @@ async def test_if_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_position", "above": 45, }, @@ -505,7 +594,7 @@ async def test_if_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_position", "below": 90, } @@ -528,7 +617,7 @@ async def test_if_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_position", "above": 45, "below": 90, @@ -597,6 +686,7 @@ async def test_if_position( async def test_if_tilt_position( hass: HomeAssistant, + entity_registry: er.EntityRegistry, calls, caplog: pytest.LogCaptureFixture, enable_custom_integrations: None, @@ -608,6 +698,8 @@ async def test_if_tilt_position( assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}}) await hass.async_block_till_done() + entry = entity_registry.async_get(ent.entity_id) + assert await async_setup_component( hass, automation.DOMAIN, @@ -621,7 +713,7 @@ async def test_if_tilt_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_tilt_position", "above": 45, }, @@ -655,7 +747,7 @@ async def test_if_tilt_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_tilt_position", "below": 90, } @@ -678,7 +770,7 @@ async def test_if_tilt_position( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": ent.entity_id, + "entity_id": entry.id, "type": "is_tilt_position", "above": 45, "below": 90,