From f77b3dbd0a43da331ebbad49c86677667cb82df2 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 00:39:35 -0400 Subject: [PATCH 1/7] Added decorate option to configuration file to allow a user to set custom images for different entities. --- homeassistant/bootstrap.py | 8 ++++++-- homeassistant/const.py | 1 + homeassistant/helpers/entity.py | 23 +++++++++++++++-------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index ecd5be36dee..7bccfd5c6db 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -24,7 +24,8 @@ from homeassistant.helpers.entity import Entity from homeassistant.const import ( EVENT_COMPONENT_LOADED, CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, CONF_VISIBILITY, - TEMP_CELCIUS, TEMP_FAHRENHEIT) + CONF_DECORATE, TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_ENTITY_PICTURE, + ATTR_HIDDEN) _LOGGER = logging.getLogger(__name__) @@ -209,7 +210,10 @@ def process_ha_core_config(hass, config): setattr(hass.config, attr, config[key]) for entity_id, hidden in config.get(CONF_VISIBILITY, {}).items(): - Entity.overwrite_hidden(entity_id, hidden == 'hide') + Entity.overwrite_attribute(entity_id, ATTR_HIDDEN, hidden == 'hide') + + for entity_id, image in config.get(CONF_DECORATE, {}).items(): + Entity.overwrite_attribute(entity_id, ATTR_ENTITY_PICTURE, image) if CONF_TEMPERATURE_UNIT in config: unit = config[CONF_TEMPERATURE_UNIT] diff --git a/homeassistant/const.py b/homeassistant/const.py index 0e859eaf943..82727541134 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -12,6 +12,7 @@ CONF_TEMPERATURE_UNIT = "temperature_unit" CONF_NAME = "name" CONF_TIME_ZONE = "time_zone" CONF_VISIBILITY = "visibility" +CONF_DECORATE = "decorate" CONF_PLATFORM = "platform" CONF_HOST = "host" diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index a39d46a29f6..90ad57f7535 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -5,14 +5,17 @@ homeassistant.helpers.entity Provides ABC for entities in HA. """ +from collections import defaultdict + from homeassistant import NoEntitySpecifiedError from homeassistant.const import ( - ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, ATTR_HIDDEN, STATE_ON, - STATE_OFF, DEVICE_DEFAULT_NAME, TEMP_CELCIUS, TEMP_FAHRENHEIT) + ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, ATTR_HIDDEN, + ATTR_ENTITY_PICTURE, STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, + TEMP_CELCIUS, TEMP_FAHRENHEIT) # Dict mapping entity_id to a boolean that overwrites the hidden property -_OVERWRITE_HIDDEN = {} +_OVERWRITE = defaultdict(dict) class Entity(object): @@ -121,9 +124,13 @@ class Entity(object): if ATTR_UNIT_OF_MEASUREMENT not in attr and self.unit_of_measurement: attr[ATTR_UNIT_OF_MEASUREMENT] = self.unit_of_measurement - if _OVERWRITE_HIDDEN.get(self.entity_id, self.hidden): + if _OVERWRITE[ATTR_HIDDEN].get(self.entity_id, self.hidden): attr[ATTR_HIDDEN] = True + if _OVERWRITE[ATTR_ENTITY_PICTURE].get(self.entity_id, False): + attr[ATTR_ENTITY_PICTURE] = \ + _OVERWRITE[ATTR_ENTITY_PICTURE][self.entity_id] + # Convert temperature if we detect one if attr.get(ATTR_UNIT_OF_MEASUREMENT) in (TEMP_CELCIUS, TEMP_FAHRENHEIT): @@ -143,15 +150,15 @@ class Entity(object): return "".format(self.name, self.state) @staticmethod - def overwrite_hidden(entity_id, hidden): + def overwrite_attribute(entity_id, attr, val): """ Overwrite the hidden property of an entity. Set hidden to None to remove any overwritten value in place. """ - if hidden is None: - _OVERWRITE_HIDDEN.pop(entity_id, None) + if val is None: + _OVERWRITE[attr].pop(entity_id, None) else: - _OVERWRITE_HIDDEN[entity_id.lower()] = hidden + _OVERWRITE[attr][entity_id.lower()] = val class ToggleEntity(Entity): From f130ad6c277efb4f3a6f778a051f3679585fce10 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 01:10:41 -0400 Subject: [PATCH 2/7] Subscribed isy994 component to EVENT_HOMEASSISTANT_STOP event to clean itself up before quitting. --- homeassistant/components/isy994.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/isy994.py b/homeassistant/components/isy994.py index f6ecebb9b2c..d3ee1008889 100644 --- a/homeassistant/components/isy994.py +++ b/homeassistant/components/isy994.py @@ -16,7 +16,8 @@ from homeassistant.helpers import validate_config from homeassistant.helpers.entity import ToggleEntity from homeassistant.const import ( CONF_HOST, CONF_USERNAME, CONF_PASSWORD, EVENT_PLATFORM_DISCOVERED, - ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME) + EVENT_HOMEASSISTANT_STOP, ATTR_SERVICE, ATTR_DISCOVERED, + ATTR_FRIENDLY_NAME) # homeassistant constants DOMAIN = "isy994" @@ -73,6 +74,9 @@ def setup(hass, config): if not ISY.connected: return False + # listen for HA stop to disconnect + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop) + # Load components for the devices in the ISY controller that we support for comp_name, discovery in ((('sensor', DISCOVER_SENSORS), ('light', DISCOVER_LIGHTS), @@ -87,6 +91,11 @@ def setup(hass, config): return True +def stop(event): + """ Cleanup the ISY subscription. """ + ISY.auto_update = False + + class ISYDeviceABC(ToggleEntity): """ Abstract Class for an ISY device within home assistant. """ From a95aad324f49b8ef960f84d03144ec0e646755b0 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 01:29:42 -0400 Subject: [PATCH 3/7] Updated a comment in the entity class. --- homeassistant/helpers/entity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 90ad57f7535..9aa8aa98143 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -152,8 +152,8 @@ class Entity(object): @staticmethod def overwrite_attribute(entity_id, attr, val): """ - Overwrite the hidden property of an entity. - Set hidden to None to remove any overwritten value in place. + Overwrite any attribute of an entity. + Set attribute to None to remove any overwritten value in place. """ if val is None: _OVERWRITE[attr].pop(entity_id, None) From 04a98f99b78b143216d493394908844fa5ce4843 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 01:43:03 -0400 Subject: [PATCH 4/7] Updated entity tests to work with new attribute overwritting logic. --- tests/test_helper_entity.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_helper_entity.py b/tests/test_helper_entity.py index a36365afc3b..e418b26e4b6 100644 --- a/tests/test_helper_entity.py +++ b/tests/test_helper_entity.py @@ -25,7 +25,8 @@ class TestHelpersEntity(unittest.TestCase): def tearDown(self): # pylint: disable=invalid-name """ Stop down stuff we started. """ self.hass.stop() - entity.Entity.overwrite_hidden(self.entity.entity_id, None) + entity.Entity.overwrite_attribute(self.entity.entity_id, + ATTR_HIDDEN, None) def test_default_hidden_not_in_attributes(self): """ Test that the default hidden property is set to False. """ @@ -43,7 +44,8 @@ class TestHelpersEntity(unittest.TestCase): def test_overwriting_hidden_property_to_true(self): """ Test we can overwrite hidden property to True. """ - entity.Entity.overwrite_hidden(self.entity.entity_id, True) + entity.Entity.overwrite_attribute(self.entity.entity_id, + ATTR_HIDDEN, True) self.entity.update_ha_state() state = self.hass.states.get(self.entity.entity_id) @@ -51,7 +53,8 @@ class TestHelpersEntity(unittest.TestCase): def test_overwriting_hidden_property_to_false(self): """ Test we can overwrite hidden property to True. """ - entity.Entity.overwrite_hidden(self.entity.entity_id, False) + entity.Entity.overwrite_attribute(self.entity.entity_id, + ATTR_HIDDEN, False) self.entity.hidden = True self.entity.update_ha_state() From 8255164eda4673d7c7a59425ede6fde9cc5d9d1a Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 14:47:15 -0400 Subject: [PATCH 5/7] Rearranged visibility control and image control in the configuration file. Now a single generic clause can be used to customize any attribute. --- homeassistant/bootstrap.py | 12 ++++-------- homeassistant/const.py | 3 +-- homeassistant/helpers/entity.py | 29 ++++++++++++++++------------- tests/test_helper_entity.py | 6 +++--- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 7bccfd5c6db..e35d2115c65 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -23,9 +23,8 @@ import homeassistant.components.group as group from homeassistant.helpers.entity import Entity from homeassistant.const import ( EVENT_COMPONENT_LOADED, CONF_LATITUDE, CONF_LONGITUDE, - CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, CONF_VISIBILITY, - CONF_DECORATE, TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_ENTITY_PICTURE, - ATTR_HIDDEN) + CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, CONF_CUSTOMIZE, + TEMP_CELCIUS, TEMP_FAHRENHEIT) _LOGGER = logging.getLogger(__name__) @@ -209,11 +208,8 @@ def process_ha_core_config(hass, config): if key in config: setattr(hass.config, attr, config[key]) - for entity_id, hidden in config.get(CONF_VISIBILITY, {}).items(): - Entity.overwrite_attribute(entity_id, ATTR_HIDDEN, hidden == 'hide') - - for entity_id, image in config.get(CONF_DECORATE, {}).items(): - Entity.overwrite_attribute(entity_id, ATTR_ENTITY_PICTURE, image) + for entity_id, attrs in config.get(CONF_CUSTOMIZE, {}).items(): + Entity.overwrite_attribute(entity_id, attrs.keys(), attrs.values()) if CONF_TEMPERATURE_UNIT in config: unit = config[CONF_TEMPERATURE_UNIT] diff --git a/homeassistant/const.py b/homeassistant/const.py index 82727541134..b85340263f0 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -11,8 +11,7 @@ CONF_LONGITUDE = "longitude" CONF_TEMPERATURE_UNIT = "temperature_unit" CONF_NAME = "name" CONF_TIME_ZONE = "time_zone" -CONF_VISIBILITY = "visibility" -CONF_DECORATE = "decorate" +CONF_CUSTOMIZE = "customize" CONF_PLATFORM = "platform" CONF_HOST = "host" diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 9aa8aa98143..d68ad7d632f 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -11,8 +11,8 @@ from homeassistant import NoEntitySpecifiedError from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, ATTR_HIDDEN, - ATTR_ENTITY_PICTURE, STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, - TEMP_CELCIUS, TEMP_FAHRENHEIT) + STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, TEMP_CELCIUS, + TEMP_FAHRENHEIT) # Dict mapping entity_id to a boolean that overwrites the hidden property _OVERWRITE = defaultdict(dict) @@ -124,12 +124,12 @@ class Entity(object): if ATTR_UNIT_OF_MEASUREMENT not in attr and self.unit_of_measurement: attr[ATTR_UNIT_OF_MEASUREMENT] = self.unit_of_measurement - if _OVERWRITE[ATTR_HIDDEN].get(self.entity_id, self.hidden): - attr[ATTR_HIDDEN] = True + for attr_name, val in _OVERWRITE[self.entity_id].items(): + attr[attr_name] = val - if _OVERWRITE[ATTR_ENTITY_PICTURE].get(self.entity_id, False): - attr[ATTR_ENTITY_PICTURE] = \ - _OVERWRITE[ATTR_ENTITY_PICTURE][self.entity_id] + # remove hidden property if false so it won't show up + if not attr.get(ATTR_HIDDEN, True): + attr.pop(ATTR_HIDDEN) # Convert temperature if we detect one if attr.get(ATTR_UNIT_OF_MEASUREMENT) in (TEMP_CELCIUS, @@ -150,15 +150,18 @@ class Entity(object): return "".format(self.name, self.state) @staticmethod - def overwrite_attribute(entity_id, attr, val): + def overwrite_attribute(entity_id, attrs, vals): """ Overwrite any attribute of an entity. - Set attribute to None to remove any overwritten value in place. + This function should receive a list of attributes and a + list of values. Set attribute to None to remove any overwritten + value in place. """ - if val is None: - _OVERWRITE[attr].pop(entity_id, None) - else: - _OVERWRITE[attr][entity_id.lower()] = val + for attr, val in zip(attrs, vals): + if val is None: + _OVERWRITE[entity_id.lower()].pop(attr, None) + else: + _OVERWRITE[entity_id.lower()][attr] = val class ToggleEntity(Entity): diff --git a/tests/test_helper_entity.py b/tests/test_helper_entity.py index e418b26e4b6..14559ded39a 100644 --- a/tests/test_helper_entity.py +++ b/tests/test_helper_entity.py @@ -26,7 +26,7 @@ class TestHelpersEntity(unittest.TestCase): """ Stop down stuff we started. """ self.hass.stop() entity.Entity.overwrite_attribute(self.entity.entity_id, - ATTR_HIDDEN, None) + [ATTR_HIDDEN], [None]) def test_default_hidden_not_in_attributes(self): """ Test that the default hidden property is set to False. """ @@ -45,7 +45,7 @@ class TestHelpersEntity(unittest.TestCase): def test_overwriting_hidden_property_to_true(self): """ Test we can overwrite hidden property to True. """ entity.Entity.overwrite_attribute(self.entity.entity_id, - ATTR_HIDDEN, True) + [ATTR_HIDDEN], [True]) self.entity.update_ha_state() state = self.hass.states.get(self.entity.entity_id) @@ -54,7 +54,7 @@ class TestHelpersEntity(unittest.TestCase): def test_overwriting_hidden_property_to_false(self): """ Test we can overwrite hidden property to True. """ entity.Entity.overwrite_attribute(self.entity.entity_id, - ATTR_HIDDEN, False) + [ATTR_HIDDEN], [False]) self.entity.hidden = True self.entity.update_ha_state() From be3be0478b9a93ffca8e4725504d8f68a83f5f93 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 14:59:27 -0400 Subject: [PATCH 6/7] Fixed bug in entity helper that ignored suggestions for hiding states. --- homeassistant/helpers/entity.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index d68ad7d632f..1097b684e60 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -124,6 +124,10 @@ class Entity(object): if ATTR_UNIT_OF_MEASUREMENT not in attr and self.unit_of_measurement: attr[ATTR_UNIT_OF_MEASUREMENT] = self.unit_of_measurement + if self.hidden: + attr[ATTR_HIDDEN] = self.hidden + + # overwrite properties that have been set in the config file for attr_name, val in _OVERWRITE[self.entity_id].items(): attr[attr_name] = val From 45f2f07b6d6b688ce18f5272502174302c622038 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 25 Apr 2015 18:29:37 -0400 Subject: [PATCH 7/7] Used better method for overwritting attributes in entity. --- homeassistant/helpers/entity.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 1097b684e60..f9751ffc14c 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -128,8 +128,7 @@ class Entity(object): attr[ATTR_HIDDEN] = self.hidden # overwrite properties that have been set in the config file - for attr_name, val in _OVERWRITE[self.entity_id].items(): - attr[attr_name] = val + attr.update(_OVERWRITE.get(self.entity_id, {})) # remove hidden property if false so it won't show up if not attr.get(ATTR_HIDDEN, True):