From b974607d55d0b0d3299a18237fe0b72190e5b253 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Mon, 22 Jan 2018 22:22:40 +0100 Subject: [PATCH 01/15] Improve service by allowing to reference entity id instead of deconz id --- .../components/binary_sensor/deconz.py | 12 +++++++++- homeassistant/components/deconz/__init__.py | 24 ++++++++++++++++--- homeassistant/components/deconz/services.yaml | 7 ++++-- homeassistant/components/light/deconz.py | 14 ++++++++--- homeassistant/components/scene/deconz.py | 12 +++++++++- homeassistant/components/sensor/deconz.py | 20 +++++++++++++++- 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index 0d7c3e086bb869..be07d254d014e1 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -7,7 +7,8 @@ import asyncio from homeassistant.components.binary_sensor import BinarySensorDevice -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) from homeassistant.const import ATTR_BATTERY_LEVEL from homeassistant.core import callback @@ -29,6 +30,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if sensor and sensor.type in DECONZ_BINARY_SENSOR: entities.append(DeconzBinarySensor(sensor)) async_add_devices(entities, True) + hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzBinarySensor(BinarySensorDevice): @@ -100,3 +102,11 @@ def device_state_attributes(self): if self._sensor.type == PRESENCE: attr['dark'] = self._sensor.dark return attr + + @property + def deconz_id(self): + """Return the deconz id of the sensor. + + E.g. /sensor/1. + """ + return self._sensor._deconz_id diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 9d7d253c328e09..ef30bdf7d49147 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -4,6 +4,8 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/deconz/ """ + +import ast import asyncio import logging @@ -22,6 +24,7 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = 'deconz' +DECONZ_ENTITIES = 'deconz_entities' CONFIG_FILE = 'deconz.conf' @@ -34,13 +37,16 @@ }, extra=vol.ALLOW_EXTRA) SERVICE_FIELD = 'field' +SERVICE_ENTITY = 'entity' SERVICE_DATA = 'data' SERVICE_SCHEMA = vol.Schema({ - vol.Required(SERVICE_FIELD): cv.string, + vol.Exclusive(SERVICE_FIELD, 'deconz_id'): cv.string, + vol.Exclusive(SERVICE_ENTITY, 'deconz_id'): cv.entity_id, vol.Required(SERVICE_DATA): dict, }) + CONFIG_INSTRUCTIONS = """ Unlock your deCONZ gateway to register with Home Assistant. @@ -100,6 +106,7 @@ def async_setup_deconz(hass, config, deconz_config): return False hass.data[DOMAIN] = deconz + hass.data[DECONZ_ENTITIES] = [] for component in ['binary_sensor', 'light', 'scene', 'sensor']: hass.async_add_job(discovery.async_load_platform( @@ -112,6 +119,7 @@ def async_configure(call): Field is a string representing a specific device in deCONZ e.g. field='/lights/1/state'. + Entity_id can be used to retrieve the proper field. Data is a json object with what data you want to alter e.g. data={'on': true}. { @@ -122,9 +130,19 @@ def async_configure(call): http://dresden-elektronik.github.io/deconz-rest-doc/rest/ """ deconz = hass.data[DOMAIN] + entities = hass.data[DECONZ_ENTITIES] field = call.data.get(SERVICE_FIELD) - data = call.data.get(SERVICE_DATA) - yield from deconz.async_put_state(field, data) + entity_id = call.data.get(SERVICE_ENTITY) + data_string = call.data.get(SERVICE_DATA) + data = ast.literal_eval(data_string) # String to dict + for entity in entities: + if entity_id == entity.entity_id: + field = entity.deconz_id + break + if field: + yield from deconz.async_put_state(field, data) + elif entity_id: + _LOGGER.error('Could\'nt find the entity %s', entity_id) hass.services.async_register( DOMAIN, 'configure', async_configure, schema=SERVICE_SCHEMA) diff --git a/homeassistant/components/deconz/services.yaml b/homeassistant/components/deconz/services.yaml index 2e6593c6ea0238..78bf7041a93297 100644 --- a/homeassistant/components/deconz/services.yaml +++ b/homeassistant/components/deconz/services.yaml @@ -1,10 +1,13 @@ configure: - description: Set attribute of device in Deconz. See Dresden Elektroniks REST API documentation for details http://dresden-elektronik.github.io/deconz-rest-doc/rest/ + description: Set attribute of device in deCONZ. See https://home-assistant.io/components/deconz/#device-services for details. fields: field: - description: Field is a string representing a specific device in Deconz. + description: Field is a string representing a specific device in deCONZ. example: '/lights/1/state' + entity: + description: Entity id representing a specific device in deCONZ. + example: 'light.rgb_light' data: description: Data is a json object with what data you want to alter. example: '{"on": true}' diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index 529917c36e2571..422dda8227a738 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, @@ -17,8 +18,6 @@ DEPENDENCIES = ['deconz'] -ATTR_LIGHT_GROUP = 'LightGroup' - @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): @@ -37,6 +36,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if group.lights: # Don't create entity for group not containing light entities.append(DeconzLight(group)) async_add_devices(entities, True) + hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzLight(Light): @@ -177,3 +177,11 @@ def async_turn_off(self, **kwargs): del data['on'] yield from self._light.async_set_state(data) + + @property + def deconz_id(self): + """Return the deconz id of the light. + + E.g. /lights/1. + """ + return self._light._deconz_id diff --git a/homeassistant/components/scene/deconz.py b/homeassistant/components/scene/deconz.py index b3400c306afca5..b0aebc7ca0f287 100644 --- a/homeassistant/components/scene/deconz.py +++ b/homeassistant/components/scene/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) from homeassistant.components.scene import Scene DEPENDENCIES = ['deconz'] @@ -24,6 +25,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): for scene in scenes.values(): entities.append(DeconzScene(scene)) async_add_devices(entities) + hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzScene(Scene): @@ -42,3 +44,11 @@ def async_activate(self): def name(self): """Return the name of the scene.""" return self._scene.full_name + + @property + def deconz_id(self): + """Return the deconz id of the scene. + + E.g. /groups/1/scenes/1. + """ + return self._scene._deconz_id diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index b3adaa412ff2be..2fdc90f237f7a9 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) from homeassistant.const import ATTR_BATTERY_LEVEL, CONF_EVENT, CONF_ID from homeassistant.core import EventOrigin, callback from homeassistant.helpers.entity import Entity @@ -38,6 +39,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): else: entities.append(DeconzSensor(sensor)) async_add_devices(entities, True) + hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzSensor(Entity): @@ -112,6 +114,14 @@ def device_state_attributes(self): } return attr + @property + def deconz_id(self): + """Return the deconz id of the sensor. + + E.g. /sensor/1. + """ + return self._sensor._deconz_id + class DeconzBattery(Entity): """Battery class for when a device is only represented as an event.""" @@ -177,6 +187,14 @@ def device_state_attributes(self): } return attr + @property + def deconz_id(self): + """Return the deconz id of the battery sensor. + + E.g. /sensor/1. + """ + return self._device._deconz_id + class DeconzEvent(object): """When you want signals instead of entities. From 5685ec1ed0358561ce121ccff696267a133383cb Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Tue, 23 Jan 2018 19:13:27 +0100 Subject: [PATCH 02/15] Change from having access to full entities to only store entity id together with deconz id --- .../components/binary_sensor/deconz.py | 16 ++++--------- homeassistant/components/deconz/__init__.py | 9 +++---- homeassistant/components/light/deconz.py | 18 +++++--------- homeassistant/components/scene/deconz.py | 20 +++++++--------- homeassistant/components/sensor/deconz.py | 24 ++++--------------- 5 files changed, 28 insertions(+), 59 deletions(-) diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index be07d254d014e1..5019d36076bd1c 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -23,27 +23,29 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): from pydeconz.sensor import DECONZ_BINARY_SENSOR sensors = hass.data[DECONZ_DATA].sensors + entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for key in sorted(sensors.keys(), key=int): sensor = sensors[key] if sensor and sensor.type in DECONZ_BINARY_SENSOR: - entities.append(DeconzBinarySensor(sensor)) + entities.append(DeconzBinarySensor(sensor, entity_registry)) async_add_devices(entities, True) - hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzBinarySensor(BinarySensorDevice): """Representation of a binary sensor.""" - def __init__(self, sensor): + def __init__(self, sensor, registry): """Set up sensor and add update callback to get data from websocket.""" self._sensor = sensor + self._registry = registry @asyncio.coroutine def async_added_to_hass(self): """Subscribe sensors events.""" self._sensor.register_async_callback(self.async_update_callback) + self._registry[self.entity_id] = self._sensor._deconz_id @callback def async_update_callback(self, reason): @@ -102,11 +104,3 @@ def device_state_attributes(self): if self._sensor.type == PRESENCE: attr['dark'] = self._sensor.dark return attr - - @property - def deconz_id(self): - """Return the deconz id of the sensor. - - E.g. /sensor/1. - """ - return self._sensor._deconz_id diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index ef30bdf7d49147..94983994ff9f10 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -106,7 +106,7 @@ def async_setup_deconz(hass, config, deconz_config): return False hass.data[DOMAIN] = deconz - hass.data[DECONZ_ENTITIES] = [] + hass.data[DECONZ_ENTITIES] = {} for component in ['binary_sensor', 'light', 'scene', 'sensor']: hass.async_add_job(discovery.async_load_platform( @@ -130,15 +130,12 @@ def async_configure(call): http://dresden-elektronik.github.io/deconz-rest-doc/rest/ """ deconz = hass.data[DOMAIN] - entities = hass.data[DECONZ_ENTITIES] + entity_registry = hass.data[DECONZ_ENTITIES] field = call.data.get(SERVICE_FIELD) entity_id = call.data.get(SERVICE_ENTITY) data_string = call.data.get(SERVICE_DATA) data = ast.literal_eval(data_string) # String to dict - for entity in entities: - if entity_id == entity.entity_id: - field = entity.deconz_id - break + field = entity_registry.get(entity_id, field) if field: yield from deconz.async_put_state(field, data) elif entity_id: diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index 422dda8227a738..8668c57ec30a57 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -27,24 +27,25 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): lights = hass.data[DECONZ_DATA].lights groups = hass.data[DECONZ_DATA].groups + entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for light in lights.values(): - entities.append(DeconzLight(light)) + entities.append(DeconzLight(light, entity_registry)) for group in groups.values(): if group.lights: # Don't create entity for group not containing light - entities.append(DeconzLight(group)) + entities.append(DeconzLight(group, entity_registry)) async_add_devices(entities, True) - hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzLight(Light): """Representation of a deCONZ light.""" - def __init__(self, light): + def __init__(self, light, registry): """Set up light and add update callback to get data from websocket.""" self._light = light + self._registry = registry self._features = SUPPORT_BRIGHTNESS self._features |= SUPPORT_FLASH @@ -64,6 +65,7 @@ def __init__(self, light): def async_added_to_hass(self): """Subscribe to lights events.""" self._light.register_async_callback(self.async_update_callback) + self._registry[self.entity_id] = self._light._deconz_id @callback def async_update_callback(self, reason): @@ -177,11 +179,3 @@ def async_turn_off(self, **kwargs): del data['on'] yield from self._light.async_set_state(data) - - @property - def deconz_id(self): - """Return the deconz id of the light. - - E.g. /lights/1. - """ - return self._light._deconz_id diff --git a/homeassistant/components/scene/deconz.py b/homeassistant/components/scene/deconz.py index b0aebc7ca0f287..e3f78940e4b429 100644 --- a/homeassistant/components/scene/deconz.py +++ b/homeassistant/components/scene/deconz.py @@ -20,20 +20,26 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return scenes = hass.data[DECONZ_DATA].scenes + entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for scene in scenes.values(): - entities.append(DeconzScene(scene)) + entities.append(DeconzScene(scene, entity_registry)) async_add_devices(entities) - hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzScene(Scene): """Representation of a deCONZ scene.""" - def __init__(self, scene): + def __init__(self, scene, registry): """Set up a scene.""" self._scene = scene + self._registry = registry + + @asyncio.coroutine + def async_added_to_hass(self): + """Add scene entity id and deconz id to entity registry.""" + self._registry[self.entity_id] = self._scene._deconz_id @asyncio.coroutine def async_activate(self): @@ -44,11 +50,3 @@ def async_activate(self): def name(self): """Return the name of the scene.""" return self._scene.full_name - - @property - def deconz_id(self): - """Return the deconz id of the scene. - - E.g. /groups/1/scenes/1. - """ - return self._scene._deconz_id diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index 2fdc90f237f7a9..11d99b060dc5f2 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -27,6 +27,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE sensors = hass.data[DECONZ_DATA].sensors + entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for key in sorted(sensors.keys(), key=int): @@ -37,22 +38,23 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if sensor.battery: entities.append(DeconzBattery(sensor)) else: - entities.append(DeconzSensor(sensor)) + entities.append(DeconzSensor(sensor, entity_registry)) async_add_devices(entities, True) - hass.data[DECONZ_ENTITIES] = hass.data[DECONZ_ENTITIES] + entities class DeconzSensor(Entity): """Representation of a sensor.""" - def __init__(self, sensor): + def __init__(self, sensor, registry): """Set up sensor and add update callback to get data from websocket.""" self._sensor = sensor + self._registry = registry @asyncio.coroutine def async_added_to_hass(self): """Subscribe to sensors events.""" self._sensor.register_async_callback(self.async_update_callback) + self._registry[self.entity_id] = self._sensor._deconz_id @callback def async_update_callback(self, reason): @@ -114,14 +116,6 @@ def device_state_attributes(self): } return attr - @property - def deconz_id(self): - """Return the deconz id of the sensor. - - E.g. /sensor/1. - """ - return self._sensor._deconz_id - class DeconzBattery(Entity): """Battery class for when a device is only represented as an event.""" @@ -187,14 +181,6 @@ def device_state_attributes(self): } return attr - @property - def deconz_id(self): - """Return the deconz id of the battery sensor. - - E.g. /sensor/1. - """ - return self._device._deconz_id - class DeconzEvent(object): """When you want signals instead of entities. From e89d70ea2e27d6dc7104b43572886a46b5b646c8 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Wed, 24 Jan 2018 17:52:18 +0100 Subject: [PATCH 03/15] Don't use eval, there is a dict type for voluptuous --- homeassistant/components/deconz/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 94983994ff9f10..21d19461812702 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -5,7 +5,6 @@ https://home-assistant.io/components/deconz/ """ -import ast import asyncio import logging @@ -133,8 +132,7 @@ def async_configure(call): entity_registry = hass.data[DECONZ_ENTITIES] field = call.data.get(SERVICE_FIELD) entity_id = call.data.get(SERVICE_ENTITY) - data_string = call.data.get(SERVICE_DATA) - data = ast.literal_eval(data_string) # String to dict + data = call.data.get(SERVICE_DATA) field = entity_registry.get(entity_id, field) if field: yield from deconz.async_put_state(field, data) From 45627014cfd75167b597d523eda624074db03da9 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Wed, 31 Jan 2018 21:56:23 +0100 Subject: [PATCH 04/15] Use entity registry instead of keeping a local registry over entity ids --- .../components/binary_sensor/deconz.py | 10 +++------- homeassistant/components/deconz/__init__.py | 20 ++++++++++++++----- homeassistant/components/light/deconz.py | 12 ++++------- homeassistant/components/scene/deconz.py | 14 +++---------- homeassistant/components/sensor/deconz.py | 12 +++++------ homeassistant/helpers/entity_registry.py | 5 +++++ 6 files changed, 35 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index 5019d36076bd1c..0d7c3e086bb869 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -7,8 +7,7 @@ import asyncio from homeassistant.components.binary_sensor import BinarySensorDevice -from homeassistant.components.deconz import ( - DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) +from homeassistant.components.deconz import DOMAIN as DECONZ_DATA from homeassistant.const import ATTR_BATTERY_LEVEL from homeassistant.core import callback @@ -23,29 +22,26 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): from pydeconz.sensor import DECONZ_BINARY_SENSOR sensors = hass.data[DECONZ_DATA].sensors - entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for key in sorted(sensors.keys(), key=int): sensor = sensors[key] if sensor and sensor.type in DECONZ_BINARY_SENSOR: - entities.append(DeconzBinarySensor(sensor, entity_registry)) + entities.append(DeconzBinarySensor(sensor)) async_add_devices(entities, True) class DeconzBinarySensor(BinarySensorDevice): """Representation of a binary sensor.""" - def __init__(self, sensor, registry): + def __init__(self, sensor): """Set up sensor and add update callback to get data from websocket.""" self._sensor = sensor - self._registry = registry @asyncio.coroutine def async_added_to_hass(self): """Subscribe sensors events.""" self._sensor.register_async_callback(self.async_update_callback) - self._registry[self.entity_id] = self._sensor._deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 21d19461812702..ce5655bd9f7302 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -16,6 +16,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.entity_component import DATA_REGISTRY from homeassistant.util.json import load_json, save_json REQUIREMENTS = ['pydeconz==27'] @@ -23,7 +24,6 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = 'deconz' -DECONZ_ENTITIES = 'deconz_entities' CONFIG_FILE = 'deconz.conf' @@ -105,7 +105,6 @@ def async_setup_deconz(hass, config, deconz_config): return False hass.data[DOMAIN] = deconz - hass.data[DECONZ_ENTITIES] = {} for component in ['binary_sensor', 'light', 'scene', 'sensor']: hass.async_add_job(discovery.async_load_platform( @@ -128,12 +127,23 @@ def async_configure(call): See Dresden Elektroniks REST API documentation for details: http://dresden-elektronik.github.io/deconz-rest-doc/rest/ """ - deconz = hass.data[DOMAIN] - entity_registry = hass.data[DECONZ_ENTITIES] field = call.data.get(SERVICE_FIELD) entity_id = call.data.get(SERVICE_ENTITY) data = call.data.get(SERVICE_DATA) - field = entity_registry.get(entity_id, field) + deconz = hass.data[DOMAIN] + + registry = hass.data.get(DATA_REGISTRY) + if registry.async_is_registered(entity_id): + entity = registry.async_get_entry(entity_id) + groups = list(deconz.groups.values()) + lights = list(deconz.lights.values()) + sensors = list(deconz.sensors.values()) + devices = groups + lights + sensors + for device in devices: + if device.uniqueid == entity.unique_id: + field = device._deconz_id + break + if field: yield from deconz.async_put_state(field, data) elif entity_id: diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index 8668c57ec30a57..4b42a7574dd252 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -6,8 +6,7 @@ """ import asyncio -from homeassistant.components.deconz import ( - DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) +from homeassistant.components.deconz import DOMAIN as DECONZ_DATA from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, @@ -27,25 +26,23 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): lights = hass.data[DECONZ_DATA].lights groups = hass.data[DECONZ_DATA].groups - entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for light in lights.values(): - entities.append(DeconzLight(light, entity_registry)) + entities.append(DeconzLight(light)) for group in groups.values(): if group.lights: # Don't create entity for group not containing light - entities.append(DeconzLight(group, entity_registry)) + entities.append(DeconzLight(group)) async_add_devices(entities, True) class DeconzLight(Light): """Representation of a deCONZ light.""" - def __init__(self, light, registry): + def __init__(self, light): """Set up light and add update callback to get data from websocket.""" self._light = light - self._registry = registry self._features = SUPPORT_BRIGHTNESS self._features |= SUPPORT_FLASH @@ -65,7 +62,6 @@ def __init__(self, light, registry): def async_added_to_hass(self): """Subscribe to lights events.""" self._light.register_async_callback(self.async_update_callback) - self._registry[self.entity_id] = self._light._deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/components/scene/deconz.py b/homeassistant/components/scene/deconz.py index e3f78940e4b429..b3400c306afca5 100644 --- a/homeassistant/components/scene/deconz.py +++ b/homeassistant/components/scene/deconz.py @@ -6,8 +6,7 @@ """ import asyncio -from homeassistant.components.deconz import ( - DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) +from homeassistant.components.deconz import DOMAIN as DECONZ_DATA from homeassistant.components.scene import Scene DEPENDENCIES = ['deconz'] @@ -20,26 +19,19 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return scenes = hass.data[DECONZ_DATA].scenes - entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for scene in scenes.values(): - entities.append(DeconzScene(scene, entity_registry)) + entities.append(DeconzScene(scene)) async_add_devices(entities) class DeconzScene(Scene): """Representation of a deCONZ scene.""" - def __init__(self, scene, registry): + def __init__(self, scene): """Set up a scene.""" self._scene = scene - self._registry = registry - - @asyncio.coroutine - def async_added_to_hass(self): - """Add scene entity id and deconz id to entity registry.""" - self._registry[self.entity_id] = self._scene._deconz_id @asyncio.coroutine def async_activate(self): diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index 11d99b060dc5f2..61769d4492df25 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -6,8 +6,7 @@ """ import asyncio -from homeassistant.components.deconz import ( - DOMAIN as DECONZ_DATA, DECONZ_ENTITIES) +from homeassistant.components.deconz import DOMAIN as DECONZ_DATA from homeassistant.const import ATTR_BATTERY_LEVEL, CONF_EVENT, CONF_ID from homeassistant.core import EventOrigin, callback from homeassistant.helpers.entity import Entity @@ -27,7 +26,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE sensors = hass.data[DECONZ_DATA].sensors - entity_registry = hass.data[DECONZ_ENTITIES] + #entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for key in sorted(sensors.keys(), key=int): @@ -38,23 +37,22 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if sensor.battery: entities.append(DeconzBattery(sensor)) else: - entities.append(DeconzSensor(sensor, entity_registry)) + entities.append(DeconzSensor(sensor)) + #entities.append(DeconzSensor(sensor, entity_registry)) async_add_devices(entities, True) class DeconzSensor(Entity): """Representation of a sensor.""" - def __init__(self, sensor, registry): + def __init__(self, sensor): """Set up sensor and add update callback to get data from websocket.""" self._sensor = sensor - self._registry = registry @asyncio.coroutine def async_added_to_hass(self): """Subscribe to sensors events.""" self._sensor.register_async_callback(self.async_update_callback) - self._registry[self.entity_id] = self._sensor._deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index d33ca93f290e25..b1210ed5d0a994 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -91,6 +91,11 @@ def async_get_or_create(self, domain, platform, unique_id, *, self.async_schedule_save() return entity + @callback + def async_get_entry(self, entity_id): + """Get entity.""" + return self.entities.get(entity_id) + @asyncio.coroutine def async_ensure_loaded(self): """Load the registry from disk.""" From 197901c558d4d56779c2dfd23cbf980820877bfb Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Wed, 31 Jan 2018 22:02:58 +0100 Subject: [PATCH 05/15] Removed old code --- homeassistant/components/sensor/deconz.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index 61769d4492df25..b3adaa412ff2be 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -26,7 +26,6 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE sensors = hass.data[DECONZ_DATA].sensors - #entity_registry = hass.data[DECONZ_ENTITIES] entities = [] for key in sorted(sensors.keys(), key=int): @@ -38,7 +37,6 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entities.append(DeconzBattery(sensor)) else: entities.append(DeconzSensor(sensor)) - #entities.append(DeconzSensor(sensor, entity_registry)) async_add_devices(entities, True) From 31688e0966ff43bc70f0ad87c2b75a2a51934f7a Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Wed, 31 Jan 2018 22:05:49 +0100 Subject: [PATCH 06/15] Add test for get_entry --- tests/helpers/test_entity_registry.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/helpers/test_entity_registry.py b/tests/helpers/test_entity_registry.py index 7e1150638c1ed1..d6f960c132a1b2 100644 --- a/tests/helpers/test_entity_registry.py +++ b/tests/helpers/test_entity_registry.py @@ -162,3 +162,11 @@ def test_loading_extra_values(hass): 'test', 'super_platform', 'without-name') assert entry_with_name.name == 'registry override' assert entry_without_name.name is None + + +@asyncio.coroutine +def test_get_entry(registry): + """Test that get_entry works.""" + entry = registry.async_get_or_create('light', 'hue', '1234') + assert registry.async_get_entry(entry.entity_id) + assert not registry.async_get_entry('light.non_existing') From ba378fda68c8106edeb9def4e4edf9aacfd2829d Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Thu, 1 Feb 2018 21:49:11 +0100 Subject: [PATCH 07/15] Bump dependency to v28 Fixed call to protected member --- homeassistant/components/deconz/__init__.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index ce5655bd9f7302..89867861f49c49 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -19,7 +19,7 @@ from homeassistant.helpers.entity_component import DATA_REGISTRY from homeassistant.util.json import load_json, save_json -REQUIREMENTS = ['pydeconz==27'] +REQUIREMENTS = ['pydeconz==28'] _LOGGER = logging.getLogger(__name__) @@ -141,7 +141,7 @@ def async_configure(call): devices = groups + lights + sensors for device in devices: if device.uniqueid == entity.unique_id: - field = device._deconz_id + field = device.deconz_id break if field: diff --git a/requirements_all.txt b/requirements_all.txt index 82c98817affcba..11f7ec0a35e6a7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -688,7 +688,7 @@ pycsspeechtts==1.0.2 pydaikin==0.4 # homeassistant.components.deconz -pydeconz==27 +pydeconz==28 # homeassistant.components.zwave pydispatcher==2.0.5 From fc12bfe9350e18d4d2d4b61d835f3fb04d637420 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 2 Feb 2018 18:26:35 +0100 Subject: [PATCH 08/15] Use chain to iterate over dict values --- homeassistant/components/deconz/__init__.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 89867861f49c49..74e72f15ebdcc6 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -7,6 +7,7 @@ import asyncio import logging +from itertools import chain import voluptuous as vol @@ -135,11 +136,7 @@ def async_configure(call): registry = hass.data.get(DATA_REGISTRY) if registry.async_is_registered(entity_id): entity = registry.async_get_entry(entity_id) - groups = list(deconz.groups.values()) - lights = list(deconz.lights.values()) - sensors = list(deconz.sensors.values()) - devices = groups + lights + sensors - for device in devices: + for device in chain(deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()): if device.uniqueid == entity.unique_id: field = device.deconz_id break From df4b1f447e2f7b14c052c865b273d0be707f57e7 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 2 Feb 2018 18:34:06 +0100 Subject: [PATCH 09/15] Cleanup --- homeassistant/components/deconz/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 74e72f15ebdcc6..a5a1ea1fc80746 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -133,10 +133,11 @@ def async_configure(call): data = call.data.get(SERVICE_DATA) deconz = hass.data[DOMAIN] - registry = hass.data.get(DATA_REGISTRY) - if registry.async_is_registered(entity_id): + if entity_id: + registry = hass.data.get(DATA_REGISTRY) entity = registry.async_get_entry(entity_id) - for device in chain(deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()): + for device in chain( + deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()): if device.uniqueid == entity.unique_id: field = device.deconz_id break From a324785b7e101aa0931f1dc308d3b47d752241e9 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 2 Feb 2018 18:37:38 +0100 Subject: [PATCH 10/15] Fix hound comment --- homeassistant/components/deconz/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index a5a1ea1fc80746..fe546e601bcd32 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -136,8 +136,9 @@ def async_configure(call): if entity_id: registry = hass.data.get(DATA_REGISTRY) entity = registry.async_get_entry(entity_id) - for device in chain( - deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()): + for device in chain(deconz.groups.values(), + deconz.lights.values(), + deconz.sensors.values()): if device.uniqueid == entity.unique_id: field = device.deconz_id break From 757e1c2fd6328c7580951429dc2e1d9d3085825e Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Sat, 3 Feb 2018 14:18:57 +0100 Subject: [PATCH 11/15] Cleanup --- homeassistant/components/deconz/__init__.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index fe546e601bcd32..9aeb753b090463 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -132,21 +132,19 @@ def async_configure(call): entity_id = call.data.get(SERVICE_ENTITY) data = call.data.get(SERVICE_DATA) deconz = hass.data[DOMAIN] - if entity_id: registry = hass.data.get(DATA_REGISTRY) entity = registry.async_get_entry(entity_id) for device in chain(deconz.groups.values(), deconz.lights.values(), deconz.sensors.values()): - if device.uniqueid == entity.unique_id: + if entity is not None and device.uniqueid == entity.unique_id: field = device.deconz_id break - - if field: - yield from deconz.async_put_state(field, data) - elif entity_id: - _LOGGER.error('Could\'nt find the entity %s', entity_id) + if field is None: + _LOGGER.error('Could\'nt find the entity %s', entity_id) + return + yield from deconz.async_put_state(field, data) hass.services.async_register( DOMAIN, 'configure', async_configure, schema=SERVICE_SCHEMA) From 24f099fe8efc15060260431e7b266e03dc62a29c Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Mon, 12 Feb 2018 23:12:14 +0100 Subject: [PATCH 12/15] Follow refactoring of entity --- homeassistant/components/deconz/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 9aeb753b090463..576d60d4cbb39d 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -17,7 +17,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.entity_component import DATA_REGISTRY +from homeassistant.helpers.entity_platform import DATA_REGISTRY from homeassistant.util.json import load_json, save_json REQUIREMENTS = ['pydeconz==28'] From 478efd3e243954e4d74a5c812418b326e206dd0f Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Tue, 13 Feb 2018 18:35:41 +0100 Subject: [PATCH 13/15] Revert to using a local registry --- .../components/binary_sensor/deconz.py | 11 +++++++---- homeassistant/components/deconz/__init__.py | 16 ++++++---------- homeassistant/components/light/deconz.py | 15 +++++++++------ homeassistant/components/scene/deconz.py | 15 +++++++++++---- homeassistant/components/sensor/deconz.py | 17 +++++++++++------ homeassistant/helpers/entity_registry.py | 5 ----- tests/helpers/test_entity_registry.py | 8 -------- 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index 0d7c3e086bb869..75d23b118d2510 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -7,7 +7,8 @@ import asyncio from homeassistant.components.binary_sensor import BinarySensorDevice -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) from homeassistant.const import ATTR_BATTERY_LEVEL from homeassistant.core import callback @@ -21,27 +22,29 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return from pydeconz.sensor import DECONZ_BINARY_SENSOR - sensors = hass.data[DECONZ_DATA].sensors + sensors = hass.data[DATA_DECONZ].sensors entities = [] for key in sorted(sensors.keys(), key=int): sensor = sensors[key] if sensor and sensor.type in DECONZ_BINARY_SENSOR: - entities.append(DeconzBinarySensor(sensor)) + entities.append(DeconzBinarySensor(hass, sensor)) async_add_devices(entities, True) class DeconzBinarySensor(BinarySensorDevice): """Representation of a binary sensor.""" - def __init__(self, sensor): + def __init__(self, hass, sensor): """Set up sensor and add update callback to get data from websocket.""" + self.hass = hass self._sensor = sensor @asyncio.coroutine def async_added_to_hass(self): """Subscribe sensors events.""" self._sensor.register_async_callback(self.async_update_callback) + self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 576d60d4cbb39d..ca8dbb70e2e573 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -17,7 +17,6 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.entity_platform import DATA_REGISTRY from homeassistant.util.json import load_json, save_json REQUIREMENTS = ['pydeconz==28'] @@ -25,6 +24,7 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = 'deconz' +DATA_DECONZ_ID = 'deconz_entities' CONFIG_FILE = 'deconz.conf' @@ -106,6 +106,7 @@ def async_setup_deconz(hass, config, deconz_config): return False hass.data[DOMAIN] = deconz + hass.data[DATA_DECONZ_ID] = {} for component in ['binary_sensor', 'light', 'scene', 'sensor']: hass.async_add_job(discovery.async_load_platform( @@ -133,16 +134,11 @@ def async_configure(call): data = call.data.get(SERVICE_DATA) deconz = hass.data[DOMAIN] if entity_id: - registry = hass.data.get(DATA_REGISTRY) - entity = registry.async_get_entry(entity_id) - for device in chain(deconz.groups.values(), - deconz.lights.values(), - deconz.sensors.values()): - if entity is not None and device.uniqueid == entity.unique_id: - field = device.deconz_id - break + entities = hass.data.get(DATA_DECONZ_ID) + if entities: + field = entities.get(entity_id) if field is None: - _LOGGER.error('Could\'nt find the entity %s', entity_id) + _LOGGER.error('Could not find the entity %s', entity_id) return yield from deconz.async_put_state(field, data) hass.services.async_register( diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index 4b42a7574dd252..6b9762abacc522 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, @@ -24,24 +25,25 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if discovery_info is None: return - lights = hass.data[DECONZ_DATA].lights - groups = hass.data[DECONZ_DATA].groups + lights = hass.data[DATA_DECONZ].lights + groups = hass.data[DATA_DECONZ].groups entities = [] for light in lights.values(): - entities.append(DeconzLight(light)) + entities.append(DeconzLight(hass, light)) for group in groups.values(): if group.lights: # Don't create entity for group not containing light - entities.append(DeconzLight(group)) + entities.append(DeconzLight(hass, group)) async_add_devices(entities, True) class DeconzLight(Light): """Representation of a deCONZ light.""" - def __init__(self, light): + def __init__(self, hass, light): """Set up light and add update callback to get data from websocket.""" + self.hass = hass self._light = light self._features = SUPPORT_BRIGHTNESS @@ -62,6 +64,7 @@ def __init__(self, light): def async_added_to_hass(self): """Subscribe to lights events.""" self._light.register_async_callback(self.async_update_callback) + self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._light.deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/components/scene/deconz.py b/homeassistant/components/scene/deconz.py index b3400c306afca5..a4f402735b3669 100644 --- a/homeassistant/components/scene/deconz.py +++ b/homeassistant/components/scene/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) from homeassistant.components.scene import Scene DEPENDENCIES = ['deconz'] @@ -18,21 +19,27 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if discovery_info is None: return - scenes = hass.data[DECONZ_DATA].scenes + scenes = hass.data[DATA_DECONZ].scenes entities = [] for scene in scenes.values(): - entities.append(DeconzScene(scene)) + entities.append(DeconzScene(hass, scene)) async_add_devices(entities) class DeconzScene(Scene): """Representation of a deCONZ scene.""" - def __init__(self, scene): + def __init__(self, hass, scene): """Set up a scene.""" + self.hass = hass self._scene = scene + @asyncio.coroutine + def async_added_to_hass(self): + """Subscribe to sensors events.""" + self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._scene.deconz_id + @asyncio.coroutine def async_activate(self): """Activate the scene.""" diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index b3adaa412ff2be..4cc00b422712d9 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -6,7 +6,8 @@ """ import asyncio -from homeassistant.components.deconz import DOMAIN as DECONZ_DATA +from homeassistant.components.deconz import ( + DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) from homeassistant.const import ATTR_BATTERY_LEVEL, CONF_EVENT, CONF_ID from homeassistant.core import EventOrigin, callback from homeassistant.helpers.entity import Entity @@ -25,7 +26,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return from pydeconz.sensor import DECONZ_SENSOR, SWITCH as DECONZ_REMOTE - sensors = hass.data[DECONZ_DATA].sensors + sensors = hass.data[DATA_DECONZ].sensors entities = [] for key in sorted(sensors.keys(), key=int): @@ -34,23 +35,25 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if sensor.type in DECONZ_REMOTE: DeconzEvent(hass, sensor) if sensor.battery: - entities.append(DeconzBattery(sensor)) + entities.append(DeconzBattery(hass, sensor)) else: - entities.append(DeconzSensor(sensor)) + entities.append(DeconzSensor(hass, sensor)) async_add_devices(entities, True) class DeconzSensor(Entity): """Representation of a sensor.""" - def __init__(self, sensor): + def __init__(self, hass, sensor): """Set up sensor and add update callback to get data from websocket.""" + self.hass = hass self._sensor = sensor @asyncio.coroutine def async_added_to_hass(self): """Subscribe to sensors events.""" self._sensor.register_async_callback(self.async_update_callback) + self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id @callback def async_update_callback(self, reason): @@ -116,8 +119,9 @@ def device_state_attributes(self): class DeconzBattery(Entity): """Battery class for when a device is only represented as an event.""" - def __init__(self, device): + def __init__(self, hass, device): """Register dispatcher callback for update of battery state.""" + self.hass = hass self._device = device self._name = '{} {}'.format(self._device.name, 'Battery Level') self._device_class = 'battery' @@ -127,6 +131,7 @@ def __init__(self, device): def async_added_to_hass(self): """Subscribe to sensors events.""" self._device.register_async_callback(self.async_update_callback) + self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._device.deconz_id @callback def async_update_callback(self, reason): diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index b1210ed5d0a994..d33ca93f290e25 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -91,11 +91,6 @@ def async_get_or_create(self, domain, platform, unique_id, *, self.async_schedule_save() return entity - @callback - def async_get_entry(self, entity_id): - """Get entity.""" - return self.entities.get(entity_id) - @asyncio.coroutine def async_ensure_loaded(self): """Load the registry from disk.""" diff --git a/tests/helpers/test_entity_registry.py b/tests/helpers/test_entity_registry.py index d6f960c132a1b2..7e1150638c1ed1 100644 --- a/tests/helpers/test_entity_registry.py +++ b/tests/helpers/test_entity_registry.py @@ -162,11 +162,3 @@ def test_loading_extra_values(hass): 'test', 'super_platform', 'without-name') assert entry_with_name.name == 'registry override' assert entry_without_name.name is None - - -@asyncio.coroutine -def test_get_entry(registry): - """Test that get_entry works.""" - entry = registry.async_get_or_create('light', 'hue', '1234') - assert registry.async_get_entry(entry.entity_id) - assert not registry.async_get_entry('light.non_existing') From 7e0f48147390429ec529251a1e12c4ac4abb06c7 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Tue, 13 Feb 2018 18:38:51 +0100 Subject: [PATCH 14/15] Remove unused import --- homeassistant/components/deconz/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index ca8dbb70e2e573..8435f6ef8a6138 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -7,7 +7,6 @@ import asyncio import logging -from itertools import chain import voluptuous as vol From 042ffe67b3928d7299342cd9c38878a3d1b920e8 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Tue, 13 Feb 2018 21:02:39 +0100 Subject: [PATCH 15/15] self.hass is automatically available when entity is registered in hass --- homeassistant/components/binary_sensor/deconz.py | 5 ++--- homeassistant/components/light/deconz.py | 7 +++---- homeassistant/components/scene/deconz.py | 5 ++--- homeassistant/components/sensor/deconz.py | 10 ++++------ 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index 75d23b118d2510..8fea7891c3d3db 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -28,16 +28,15 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): for key in sorted(sensors.keys(), key=int): sensor = sensors[key] if sensor and sensor.type in DECONZ_BINARY_SENSOR: - entities.append(DeconzBinarySensor(hass, sensor)) + entities.append(DeconzBinarySensor(sensor)) async_add_devices(entities, True) class DeconzBinarySensor(BinarySensorDevice): """Representation of a binary sensor.""" - def __init__(self, hass, sensor): + def __init__(self, sensor): """Set up sensor and add update callback to get data from websocket.""" - self.hass = hass self._sensor = sensor @asyncio.coroutine diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index 6b9762abacc522..0eef5a868b40fb 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -30,20 +30,19 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entities = [] for light in lights.values(): - entities.append(DeconzLight(hass, light)) + entities.append(DeconzLight(light)) for group in groups.values(): if group.lights: # Don't create entity for group not containing light - entities.append(DeconzLight(hass, group)) + entities.append(DeconzLight(group)) async_add_devices(entities, True) class DeconzLight(Light): """Representation of a deCONZ light.""" - def __init__(self, hass, light): + def __init__(self, light): """Set up light and add update callback to get data from websocket.""" - self.hass = hass self._light = light self._features = SUPPORT_BRIGHTNESS diff --git a/homeassistant/components/scene/deconz.py b/homeassistant/components/scene/deconz.py index a4f402735b3669..db81d84c2b7c7f 100644 --- a/homeassistant/components/scene/deconz.py +++ b/homeassistant/components/scene/deconz.py @@ -23,16 +23,15 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entities = [] for scene in scenes.values(): - entities.append(DeconzScene(hass, scene)) + entities.append(DeconzScene(scene)) async_add_devices(entities) class DeconzScene(Scene): """Representation of a deCONZ scene.""" - def __init__(self, hass, scene): + def __init__(self, scene): """Set up a scene.""" - self.hass = hass self._scene = scene @asyncio.coroutine diff --git a/homeassistant/components/sensor/deconz.py b/homeassistant/components/sensor/deconz.py index 4cc00b422712d9..b60df1c6ac9896 100644 --- a/homeassistant/components/sensor/deconz.py +++ b/homeassistant/components/sensor/deconz.py @@ -35,18 +35,17 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): if sensor.type in DECONZ_REMOTE: DeconzEvent(hass, sensor) if sensor.battery: - entities.append(DeconzBattery(hass, sensor)) + entities.append(DeconzBattery(sensor)) else: - entities.append(DeconzSensor(hass, sensor)) + entities.append(DeconzSensor(sensor)) async_add_devices(entities, True) class DeconzSensor(Entity): """Representation of a sensor.""" - def __init__(self, hass, sensor): + def __init__(self, sensor): """Set up sensor and add update callback to get data from websocket.""" - self.hass = hass self._sensor = sensor @asyncio.coroutine @@ -119,9 +118,8 @@ def device_state_attributes(self): class DeconzBattery(Entity): """Battery class for when a device is only represented as an event.""" - def __init__(self, hass, device): + def __init__(self, device): """Register dispatcher callback for update of battery state.""" - self.hass = hass self._device = device self._name = '{} {}'.format(self._device.name, 'Battery Level') self._device_class = 'battery'