async def test_loading_race_condition(hass): """Test only one storage load called when concurrent loading occurred .""" with asynctest.patch( "homeassistant.helpers.device_registry.DeviceRegistry.async_load" ) as mock_load: results = await asyncio.gather( device_registry.async_get_registry(hass), device_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.device_registry.DeviceRegistry.async_load', ) as mock_load: results = await asyncio.gather( device_registry.async_get_registry(hass), device_registry.async_get_registry(hass), ) mock_load.assert_called_once_with() assert results[0] == results[1]
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
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Meross IoT local LAN from a config entry.""" LOGGER.debug("async_setup_entry entry_id = %s", entry.entry_id) api = hass.data.get(DOMAIN) if api == None: try: api = MerossApi(hass) hass.data[DOMAIN] = api await api.async_mqtt_register() except: return False device_id = entry.data.get(CONF_DEVICE_ID) if device_id == None: # this is the MQTT Hub entry api.key = entry.data.get( CONF_KEY ) # could be 'None' : if so defaults to "" but allows key reply trick api.unsub_entry_update_listener = entry.add_update_listener( api.entry_update_listener) else: #device related entry LOGGER.debug("async_setup_entry device_id = %s", device_id) device = MerossDevice(api, device_id, entry) api.devices[device_id] = device p_system = entry.data.get(CONF_DISCOVERY_PAYLOAD, {}).get("all", {}).get("system", {}) p_hardware = p_system.get("hardware", {}) p_firmware = p_system.get("firmware", {}) p_hardware_type = p_hardware.get("type", MANUFACTURER) try: #use newer api device_registry.async_get(hass).async_get_or_create( config_entry_id=entry.entry_id, connections={(device_registry.CONNECTION_NETWORK_MAC, p_hardware.get("macAddress"))}, identifiers={(DOMAIN, device_id)}, manufacturer=MANUFACTURER, name=p_hardware_type + " " + device_id, model=p_hardware_type + " " + p_hardware.get("version", ""), sw_version=p_firmware.get("version"), ) except: #fallback: as of 27-03-2021 this is still working device_registry.async_get_registry(hass).async_get_or_create( config_entry_id=entry.entry_id, connections={(device_registry.CONNECTION_NETWORK_MAC, p_hardware.get("macAddress"))}, identifiers={(DOMAIN, device_id)}, manufacturer=MANUFACTURER, name=p_hardware_type + " " + device_id, model=p_hardware_type + " " + p_hardware.get("version", ""), sw_version=p_firmware.get("version"), ) if device.has_switches: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "switch")) if device.has_lights: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "light")) if device.has_sensors: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "sensor")) device.unsub_entry_update_listener = entry.add_update_listener( device_entry_update_listener) device.unsub_updatecoordinator_listener = api.coordinator.async_add_listener( device.updatecoordinator_listener) return True