async def test_loading_race_condition(hass): """Test only one storage load called when concurrent loading occurred .""" with tests.async_mock.patch( "homeassistant.helpers.entity_registry.EntityRegistry.async_load" ) as mock_load: results = await asyncio.gather( entity_registry.async_get_registry(hass), entity_registry.async_get_registry(hass), ) mock_load.assert_called_once_with() assert results[0] == results[1]
async def test_loading_race_condition(hass): """Test only one storage load called when concurrent loading occurred .""" with asynctest.patch( 'homeassistant.helpers.entity_registry.EntityRegistry.async_load', ) as mock_load: results = await asyncio.gather( entity_registry.async_get_registry(hass), entity_registry.async_get_registry(hass), ) mock_load.assert_called_once_with() assert results[0] == results[1]
def light_entities_for_group(group_name): """Find light entity IDs for the Philips Hue zone/room name. All configured Hue bridges are queried for the group. Pyscript must be configured to expose the "hass" global variable and allow all imports so that we can access the bridge configs and entity registry. :param group_name: The Hue zone/room name exactly as it appears in the Hue app (e.g. "Living room"). :return: Set of light entity IDs for the group name or empty set if no matching group or entities are found. """ entity_ids = set() # Load entity registry. entity_registry = er.async_get_registry(hass) # Find Hue bridge config(s). for config_entry in hass.config_entries.async_entries(domain="hue"): host, api_key = config_entry.data["host"], config_entry.data["api_key"] async with HueBridgeV2(host, api_key) as bridge: # Query Hue bridge for light services in the matching group(s), if any. for group in bridge.groups: if not hasattr(group, "metadata") or group.metadata.name != group_name: continue lights_resolver = bridge.groups.room if group.type == ResourceTypes.ROOM else bridge.groups.zone light_ids = {light.id for light in lights_resolver.get_lights(group.id)} group_entity_ids = { id for id, entity in entity_registry.entities.items() if entity.unique_id in light_ids and entity.platform == "hue" } log.debug(f"Found Hue group '{group_name}' on {host}; lights: {group_entity_ids}") entity_ids |= group_entity_ids return entity_ids
async def async_extract_referenced_entity_ids( hass: HomeAssistantType, service_call: ha.ServiceCall, expand_group: bool = True) -> SelectedEntities: """Extract referenced entity IDs from a service call.""" entity_ids = service_call.data.get(ATTR_ENTITY_ID) device_ids = service_call.data.get(ATTR_DEVICE_ID) area_ids = service_call.data.get(ATTR_AREA_ID) selects_entity_ids = entity_ids not in (None, ENTITY_MATCH_NONE) selects_device_ids = device_ids not in (None, ENTITY_MATCH_NONE) selects_area_ids = area_ids not in (None, ENTITY_MATCH_NONE) selected = SelectedEntities() if not selects_entity_ids and not selects_device_ids and not selects_area_ids: return selected if selects_entity_ids: assert entity_ids is not None # Entity ID attr can be a list or a string if isinstance(entity_ids, str): entity_ids = [entity_ids] if expand_group: entity_ids = hass.components.group.expand_entity_ids(entity_ids) selected.referenced.update(entity_ids) if not selects_device_ids and not selects_area_ids: return selected area_reg, dev_reg, ent_reg = cast( Tuple[area_registry.AreaRegistry, device_registry.DeviceRegistry, entity_registry.EntityRegistry, ], await asyncio.gather( area_registry.async_get_registry(hass), device_registry.async_get_registry(hass), entity_registry.async_get_registry(hass), ), ) picked_devices = set() if selects_device_ids: if isinstance(device_ids, str): picked_devices = {device_ids} else: assert isinstance(device_ids, list) picked_devices = set(device_ids) for device_id in picked_devices: if device_id not in dev_reg.devices: selected.missing_devices.add(device_id) if selects_area_ids: assert area_ids is not None if isinstance(area_ids, str): area_lookup = {area_ids} else: area_lookup = set(area_ids) for area_id in area_lookup: if area_id not in area_reg.areas: selected.missing_areas.add(area_id) continue # Find entities tied to an area for entity_entry in ent_reg.entities.values(): if entity_entry.area_id in area_lookup: selected.indirectly_referenced.add(entity_entry.entity_id) # Find devices for this area for device_entry in dev_reg.devices.values(): if device_entry.area_id in area_lookup: picked_devices.add(device_entry.id) if not picked_devices: return selected for entity_entry in ent_reg.entities.values(): if not entity_entry.area_id and entity_entry.device_id in picked_devices: selected.indirectly_referenced.add(entity_entry.entity_id) return selected
def _get_entry_id(self, entity_id: str): """ Resolve ConfigEntry.entry_id for entity_id """ registry = asyncio.run_coroutine_threadsafe( er.async_get_registry(self._hass), self._hass.loop).result() return registry.async_get(entity_id).config_entry_id