From d7bbdb033decce3d59eb643516877210a79cb42e Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 29 Jan 2019 02:52:00 +0100 Subject: [PATCH] Add check to validate gamut (#20518) * color.util - Add check to validate gamut * fix indents * fix typo * Add check to validate gamut * Add tests for gamut checker * fix test * fix pylint issues * fix hue light gamut tests * add check to validate gamut * move None check * Move None check * Include prompt to update bridge/bulb on error * fix wrong commit * fix error message * Update light.py --- homeassistant/components/hue/light.py | 12 +++++++++++- homeassistant/util/color.py | 18 ++++++++++++++++++ tests/components/hue/test_light.py | 12 +++++++++--- tests/util/test_color.py | 20 ++++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index a10b42fbeee..3327d0f9dc2 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -41,6 +41,7 @@ SUPPORT_HUE = { } ATTR_IS_HUE_GROUP = 'is_hue_group' +GAMUT_TYPE_UNAVAILABLE = 'None' # Minimum Hue Bridge API version to support groups # 1.4.0 introduced extended group info # 1.12 introduced the state object for groups @@ -221,7 +222,7 @@ class HueLight(Light): if is_group: self.is_osram = False self.is_philips = False - self.gamut_typ = 'None' + self.gamut_typ = GAMUT_TYPE_UNAVAILABLE self.gamut = None else: self.is_osram = light.manufacturername == 'OSRAM' @@ -229,6 +230,15 @@ class HueLight(Light): self.gamut_typ = self.light.colorgamuttype self.gamut = self.light.colorgamut _LOGGER.debug("Color gamut of %s: %s", self.name, str(self.gamut)) + if self.gamut: + if not color.check_valid_gamut(self.gamut): + err = "Please check for software updates of the bridge " \ + "and/or bulb in the Philips Hue App, " \ + "Color gamut of %s: %s, not valid, " \ + "setting gamut to None." + _LOGGER.warning(err, self.name, str(self.gamut)) + self.gamut_typ = GAMUT_TYPE_UNAVAILABLE + self.gamut = None @property def unique_id(self): diff --git a/homeassistant/util/color.py b/homeassistant/util/color.py index 5a32d89a793..6d7f3336566 100644 --- a/homeassistant/util/color.py +++ b/homeassistant/util/color.py @@ -600,3 +600,21 @@ def check_point_in_lamps_reach(p: Tuple[float, float], t = cross_product(v1, q) / cross_product(v1, v2) return (s >= 0.0) and (t >= 0.0) and (s + t <= 1.0) + + +def check_valid_gamut(Gamut: GamutType) -> bool: + """Check if the supplied gamut is valid.""" + # Check if the three points of the supplied gamut are not on the same line. + v1 = XYPoint(Gamut.green.x - Gamut.red.x, Gamut.green.y - Gamut.red.y) + v2 = XYPoint(Gamut.blue.x - Gamut.red.x, Gamut.blue.y - Gamut.red.y) + not_on_line = cross_product(v1, v2) > 0.0001 + + # Check if all six coordinates of the gamut lie between 0 and 1. + red_valid = Gamut.red.x >= 0 and Gamut.red.x <= 1 and \ + Gamut.red.y >= 0 and Gamut.red.y <= 1 + green_valid = Gamut.green.x >= 0 and Gamut.green.x <= 1 and \ + Gamut.green.y >= 0 and Gamut.green.y <= 1 + blue_valid = Gamut.blue.x >= 0 and Gamut.blue.x <= 1 and \ + Gamut.blue.y >= 0 and Gamut.blue.y <= 1 + + return not_on_line and red_valid and green_valid and blue_valid diff --git a/tests/components/hue/test_light.py b/tests/components/hue/test_light.py index f7865fcf4f8..eabfd6d35aa 100644 --- a/tests/components/hue/test_light.py +++ b/tests/components/hue/test_light.py @@ -701,7 +701,9 @@ def test_available(): """Test available property.""" light = hue_light.HueLight( light=Mock(state={'reachable': False}, - raw=LIGHT_RAW), + raw=LIGHT_RAW, + colorgamuttype=LIGHT_GAMUT_TYPE, + colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(allow_unreachable=False), is_group=False, @@ -711,7 +713,9 @@ def test_available(): light = hue_light.HueLight( light=Mock(state={'reachable': False}, - raw=LIGHT_RAW), + raw=LIGHT_RAW, + colorgamuttype=LIGHT_GAMUT_TYPE, + colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(allow_unreachable=True), is_group=False, @@ -721,7 +725,9 @@ def test_available(): light = hue_light.HueLight( light=Mock(state={'reachable': False}, - raw=LIGHT_RAW), + raw=LIGHT_RAW, + colorgamuttype=LIGHT_GAMUT_TYPE, + colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(allow_unreachable=False), is_group=True, diff --git a/tests/util/test_color.py b/tests/util/test_color.py index b54b2bc5776..14195d43821 100644 --- a/tests/util/test_color.py +++ b/tests/util/test_color.py @@ -8,6 +8,18 @@ import voluptuous as vol GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296), color_util.XYPoint(0.2151, 0.7106), color_util.XYPoint(0.138, 0.08)) +GAMUT_INVALID_1 = color_util.GamutType(color_util.XYPoint(0.704, 0.296), + color_util.XYPoint(-0.201, 0.7106), + color_util.XYPoint(0.138, 0.08)) +GAMUT_INVALID_2 = color_util.GamutType(color_util.XYPoint(0.704, 1.296), + color_util.XYPoint(0.2151, 0.7106), + color_util.XYPoint(0.138, 0.08)) +GAMUT_INVALID_3 = color_util.GamutType(color_util.XYPoint(0.0, 0.0), + color_util.XYPoint(0.0, 0.0), + color_util.XYPoint(0.0, 0.0)) +GAMUT_INVALID_4 = color_util.GamutType(color_util.XYPoint(0.1, 0.1), + color_util.XYPoint(0.3, 0.3), + color_util.XYPoint(0.7, 0.7)) class TestColorUtil(unittest.TestCase): @@ -338,6 +350,14 @@ class TestColorUtil(unittest.TestCase): assert color_util.color_rgb_to_hex(51, 153, 255) == '3399ff' assert color_util.color_rgb_to_hex(255, 67.9204190, 0) == 'ff4400' + def test_gamut(self): + """Test gamut functions.""" + assert color_util.check_valid_gamut(GAMUT) + assert not color_util.check_valid_gamut(GAMUT_INVALID_1) + assert not color_util.check_valid_gamut(GAMUT_INVALID_2) + assert not color_util.check_valid_gamut(GAMUT_INVALID_3) + assert not color_util.check_valid_gamut(GAMUT_INVALID_4) + class ColorTemperatureMiredToKelvinTests(unittest.TestCase): """Test color_temperature_mired_to_kelvin."""