From 0cc9798c8f5756d36c9ca34fe8355e9e2e10c26b Mon Sep 17 00:00:00 2001 From: Daniel Kalmar Date: Tue, 24 Jul 2018 20:29:59 +0200 Subject: [PATCH] Allow defining default turn-on values for lights in the profiles file. (#15493) * Allow defining default turn-on values for lights in the profiles file. * Mock out file operations in unit test. * Fix unit test flakiness. * Avoid unnecessary copy --- homeassistant/components/light/__init__.py | 18 ++++- tests/components/light/test_init.py | 78 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index bd428a84bed..472be92583a 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -346,7 +346,12 @@ async def async_setup(hass, config): update_tasks = [] for light in target_lights: if service.service == SERVICE_TURN_ON: - await light.async_turn_on(**params) + pars = params + if not pars: + pars = params.copy() + pars[ATTR_PROFILE] = Profiles.get_default(light.entity_id) + preprocess_turn_on_alternatives(pars) + await light.async_turn_on(**pars) elif service.service == SERVICE_TURN_OFF: await light.async_turn_off(**params) else: @@ -431,6 +436,17 @@ class Profiles: """Return a named profile.""" return cls._all.get(name) + @classmethod + def get_default(cls, entity_id): + """Return the default turn-on profile for the given light.""" + name = entity_id + ".default" + if name in cls._all: + return name + name = ENTITY_ID_ALL_LIGHTS + ".default" + if name in cls._all: + return name + return None + class Light(ToggleEntity): """Representation of a light.""" diff --git a/tests/components/light/test_init.py b/tests/components/light/test_init.py index 634e3774b8a..74f8c85b532 100644 --- a/tests/components/light/test_init.py +++ b/tests/components/light/test_init.py @@ -1,7 +1,9 @@ """The tests for the Light component.""" # pylint: disable=protected-access import unittest +import unittest.mock as mock import os +from io import StringIO from homeassistant.setup import setup_component import homeassistant.loader as loader @@ -308,6 +310,82 @@ class TestLight(unittest.TestCase): light.ATTR_BRIGHTNESS: 100 }, data) + def test_default_profiles_group(self): + """Test default turn-on light profile for all lights.""" + platform = loader.get_component(self.hass, 'light.test') + platform.init() + + user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) + real_isfile = os.path.isfile + real_open = open + + def _mock_isfile(path): + if path == user_light_file: + return True + return real_isfile(path) + + def _mock_open(path): + if path == user_light_file: + return StringIO(profile_data) + return real_open(path) + + profile_data = "id,x,y,brightness\n" +\ + "group.all_lights.default,.4,.6,99\n" + with mock.patch('os.path.isfile', side_effect=_mock_isfile): + with mock.patch('builtins.open', side_effect=_mock_open): + self.assertTrue(setup_component( + self.hass, light.DOMAIN, + {light.DOMAIN: {CONF_PLATFORM: 'test'}} + )) + + dev, _, _ = platform.DEVICES + light.turn_on(self.hass, dev.entity_id) + self.hass.block_till_done() + _, data = dev.last_call('turn_on') + self.assertEqual({ + light.ATTR_HS_COLOR: (71.059, 100), + light.ATTR_BRIGHTNESS: 99 + }, data) + + def test_default_profiles_light(self): + """Test default turn-on light profile for a specific light.""" + platform = loader.get_component(self.hass, 'light.test') + platform.init() + + user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) + real_isfile = os.path.isfile + real_open = open + + def _mock_isfile(path): + if path == user_light_file: + return True + return real_isfile(path) + + def _mock_open(path): + if path == user_light_file: + return StringIO(profile_data) + return real_open(path) + + profile_data = "id,x,y,brightness\n" +\ + "group.all_lights.default,.3,.5,200\n" +\ + "light.ceiling_2.default,.6,.6,100\n" + with mock.patch('os.path.isfile', side_effect=_mock_isfile): + with mock.patch('builtins.open', side_effect=_mock_open): + self.assertTrue(setup_component( + self.hass, light.DOMAIN, + {light.DOMAIN: {CONF_PLATFORM: 'test'}} + )) + + dev = next(filter(lambda x: x.entity_id == 'light.ceiling_2', + platform.DEVICES)) + light.turn_on(self.hass, dev.entity_id) + self.hass.block_till_done() + _, data = dev.last_call('turn_on') + self.assertEqual({ + light.ATTR_HS_COLOR: (50.353, 100), + light.ATTR_BRIGHTNESS: 100 + }, data) + async def test_intent_set_color(hass): """Test the set color intent."""