diff --git a/homeassistant/components/homeassistant/__init__.py b/homeassistant/components/homeassistant/__init__.py index 2314d2b0c1b..8c31859b8e0 100644 --- a/homeassistant/components/homeassistant/__init__.py +++ b/homeassistant/components/homeassistant/__init__.py @@ -61,7 +61,7 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no async def async_handle_turn_service(service): """Handle calls to homeassistant.turn_on/off.""" - referenced = await async_extract_referenced_entity_ids(hass, service) + referenced = async_extract_referenced_entity_ids(hass, service) all_referenced = referenced.referenced | referenced.indirectly_referenced # Generic turn on/off method requires entity id diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 8fc68ca641c..9ebc29a683f 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -396,7 +396,7 @@ def _async_register_events_and_services(hass: HomeAssistant): async def async_handle_homekit_unpair(service): """Handle unpair HomeKit service call.""" - referenced = await async_extract_referenced_entity_ids(hass, service) + referenced = async_extract_referenced_entity_ids(hass, service) dev_reg = device_registry.async_get(hass) for device_id in referenced.referenced_devices: dev_reg_ent = dev_reg.async_get(device_id) diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 002d6447441..800d494fdbb 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -20,6 +20,8 @@ from homeassistant.const import ( CONF_SERVICE_DATA, CONF_SERVICE_TEMPLATE, CONF_TARGET, + ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, ENTITY_MATCH_ALL, ENTITY_MATCH_NONE, ) @@ -279,9 +281,7 @@ async def async_extract_entities( if data_ent_id == ENTITY_MATCH_ALL: return [entity for entity in entities if entity.available] - referenced = await async_extract_referenced_entity_ids( - hass, service_call, expand_group - ) + referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group) combined = referenced.referenced | referenced.indirectly_referenced found = [] @@ -310,9 +310,7 @@ async def async_extract_entity_ids( Will convert group entity ids to the entity ids it represents. """ - referenced = await async_extract_referenced_entity_ids( - hass, service_call, expand_group - ) + referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group) return referenced.referenced | referenced.indirectly_referenced @@ -322,7 +320,7 @@ def _has_match(ids: str | list | None) -> bool: @bind_hass -async def async_extract_referenced_entity_ids( +def async_extract_referenced_entity_ids( hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True ) -> SelectedEntities: """Extract referenced entity IDs from a service call.""" @@ -363,6 +361,13 @@ async def async_extract_referenced_entity_ids( return selected for ent_entry in ent_reg.entities.values(): + # Do not add config or diagnostic entities referenced by areas or devices + if ent_entry.entity_category in ( + ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, + ): + continue + if ( # when area matches the target area ent_entry.area_id in selector.area_ids @@ -384,9 +389,7 @@ async def async_extract_config_entry_ids( hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True ) -> set: """Extract referenced config entry ids from a service call.""" - referenced = await async_extract_referenced_entity_ids( - hass, service_call, expand_group - ) + referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group) ent_reg = entity_registry.async_get(hass) dev_reg = device_registry.async_get(hass) config_entry_ids: set[str] = set() @@ -545,7 +548,7 @@ async def entity_service_call( all_referenced: set[str] | None = None else: # A set of entities we're trying to target. - referenced = await async_extract_referenced_entity_ids(hass, call, True) + referenced = async_extract_referenced_entity_ids(hass, call, True) all_referenced = referenced.referenced | referenced.indirectly_referenced # If the service function is a string, we'll pass it the service call data diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index 7e18547145b..16f7ad4825a 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -113,12 +113,26 @@ def area_mock(hass): platform="test", area_id="own-area", ) + config_entity_in_own_area = ent_reg.RegistryEntry( + entity_id="light.config_in_own_area", + unique_id="config-in-own-area-id", + platform="test", + area_id="own-area", + entity_category="config", + ) entity_in_area = ent_reg.RegistryEntry( entity_id="light.in_area", unique_id="in-area-id", platform="test", device_id=device_in_area.id, ) + config_entity_in_area = ent_reg.RegistryEntry( + entity_id="light.config_in_area", + unique_id="config-in-area-id", + platform="test", + device_id=device_in_area.id, + entity_category="config", + ) entity_in_other_area = ent_reg.RegistryEntry( entity_id="light.in_other_area", unique_id="in-area-a-id", @@ -139,6 +153,13 @@ def area_mock(hass): platform="test", device_id=device_no_area.id, ) + config_entity_no_area = ent_reg.RegistryEntry( + entity_id="light.config_no_area", + unique_id="config-no-area-id", + platform="test", + device_id=device_no_area.id, + entity_category="config", + ) entity_diff_area = ent_reg.RegistryEntry( entity_id="light.diff_area", unique_id="diff-area-id", @@ -163,10 +184,13 @@ def area_mock(hass): hass, { entity_in_own_area.entity_id: entity_in_own_area, + config_entity_in_own_area.entity_id: config_entity_in_own_area, entity_in_area.entity_id: entity_in_area, + config_entity_in_area.entity_id: config_entity_in_area, entity_in_other_area.entity_id: entity_in_other_area, entity_assigned_to_area.entity_id: entity_assigned_to_area, entity_no_area.entity_id: entity_no_area, + config_entity_no_area.entity_id: config_entity_no_area, entity_diff_area.entity_id: entity_diff_area, entity_in_area_a.entity_id: entity_in_area_a, entity_in_area_b.entity_id: entity_in_area_b,