diff --git a/homeassistant/components/hue/helpers.py b/homeassistant/components/hue/helpers.py new file mode 100644 index 00000000000..388046bb8cb --- /dev/null +++ b/homeassistant/components/hue/helpers.py @@ -0,0 +1,33 @@ +"""Helper functions for Philips Hue.""" +from homeassistant.helpers.entity_registry import async_get_registry as get_ent_reg +from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg + +from .const import DOMAIN + + +async def remove_devices(hass, config_entry, api_ids, current): + """Get items that are removed from api.""" + removed_items = [] + + for item_id in current: + if item_id in api_ids: + continue + + # Device is removed from Hue, so we remove it from Home Assistant + entity = current[item_id] + removed_items.append(item_id) + await entity.async_remove() + ent_registry = await get_ent_reg(hass) + if entity.entity_id in ent_registry.entities: + ent_registry.async_remove(entity.entity_id) + dev_registry = await get_dev_reg(hass) + device = dev_registry.async_get_device( + identifiers={(DOMAIN, entity.device_id)}, connections=set() + ) + if device is not None: + dev_registry.async_update_device( + device.id, remove_config_entry_id=config_entry.entry_id + ) + + for item_id in removed_items: + del current[item_id] diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index 5a3379f71ce..dcae1cf4f5d 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -8,9 +8,6 @@ import random import aiohue import async_timeout -from homeassistant.helpers.entity_registry import async_get_registry as get_ent_reg -from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg - from homeassistant.components import hue from homeassistant.components.light import ( ATTR_BRIGHTNESS, @@ -32,6 +29,7 @@ from homeassistant.components.light import ( Light, ) from homeassistant.util import color +from .helpers import remove_devices SCAN_INTERVAL = timedelta(seconds=5) @@ -226,7 +224,6 @@ async def async_update_items( bridge.available = True new_items = [] - removed_items = [] for item_id in api: if item_id not in current: @@ -238,31 +235,11 @@ async def async_update_items( elif item_id not in progress_waiting: current[item_id].async_schedule_update_ha_state() - for item_id in current: - if item_id in api: - continue - - # Device is removed from Hue, so we remove it from Home Assistant - entity = current[item_id] - removed_items.append(item_id) - await entity.async_remove() - ent_registry = await get_ent_reg(hass) - if entity.entity_id in ent_registry.entities: - ent_registry.async_remove(entity.entity_id) - dev_registry = await get_dev_reg(hass) - device = dev_registry.async_get_device( - identifiers={(hue.DOMAIN, entity.unique_id)}, connections=set() - ) - dev_registry.async_update_device( - device.id, remove_config_entry_id=config_entry.entry_id - ) + await remove_devices(hass, config_entry, api, current) if new_items: async_add_entities(new_items) - for item_id in removed_items: - del current[item_id] - class HueLight(Light): """Representation of a Hue light.""" @@ -300,9 +277,14 @@ class HueLight(Light): @property def unique_id(self): - """Return the ID of this Hue light.""" + """Return the unique ID of this Hue light.""" return self.light.uniqueid + @property + def device_id(self): + """Return the ID of this Hue light.""" + return self.unique_id + @property def name(self): """Return the name of the Hue light.""" @@ -384,7 +366,7 @@ class HueLight(Light): return None return { - "identifiers": {(hue.DOMAIN, self.unique_id)}, + "identifiers": {(hue.DOMAIN, self.device_id)}, "name": self.name, "manufacturer": self.light.manufacturername, # productname added in Hue Bridge API 1.24 diff --git a/homeassistant/components/hue/sensor_base.py b/homeassistant/components/hue/sensor_base.py index 96b9b8bf5d6..3f202d38bc5 100644 --- a/homeassistant/components/hue/sensor_base.py +++ b/homeassistant/components/hue/sensor_base.py @@ -11,6 +11,7 @@ from homeassistant.exceptions import NoEntitySpecifiedError from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.util.dt import utcnow +from .helpers import remove_devices CURRENT_SENSORS = "current_sensors" SENSOR_MANAGER_FORMAT = "{}_sensor_manager" @@ -34,7 +35,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities, binary=False sm_key = SENSOR_MANAGER_FORMAT.format(config_entry.data["host"]) manager = hass.data[hue.DOMAIN].get(sm_key) if manager is None: - manager = SensorManager(hass, bridge) + manager = SensorManager(hass, bridge, config_entry) hass.data[hue.DOMAIN][sm_key] = manager manager.register_component(binary, async_add_entities) @@ -50,7 +51,7 @@ class SensorManager: SCAN_INTERVAL = timedelta(seconds=5) sensor_config_map = {} - def __init__(self, hass, bridge): + def __init__(self, hass, bridge, config_entry): """Initialize the sensor manager.""" import aiohue from .binary_sensor import HuePresence, PRESENCE_NAME_FORMAT @@ -63,6 +64,7 @@ class SensorManager: self.hass = hass self.bridge = bridge + self.config_entry = config_entry self._component_add_entities = {} self._started = False @@ -194,6 +196,13 @@ class SensorManager: else: new_sensors.append(current[api[item_id].uniqueid]) + await remove_devices( + self.hass, + self.config_entry, + [value.uniqueid for value in api.values()], + current, + ) + async_add_sensor_entities = self._component_add_entities.get(False) async_add_binary_entities = self._component_add_entities.get(True) if new_sensors and async_add_sensor_entities: