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
This commit is contained in:
parent
63fd5f2d31
commit
d7bbdb033d
4 changed files with 58 additions and 4 deletions
|
@ -41,6 +41,7 @@ SUPPORT_HUE = {
|
||||||
}
|
}
|
||||||
|
|
||||||
ATTR_IS_HUE_GROUP = 'is_hue_group'
|
ATTR_IS_HUE_GROUP = 'is_hue_group'
|
||||||
|
GAMUT_TYPE_UNAVAILABLE = 'None'
|
||||||
# Minimum Hue Bridge API version to support groups
|
# Minimum Hue Bridge API version to support groups
|
||||||
# 1.4.0 introduced extended group info
|
# 1.4.0 introduced extended group info
|
||||||
# 1.12 introduced the state object for groups
|
# 1.12 introduced the state object for groups
|
||||||
|
@ -221,7 +222,7 @@ class HueLight(Light):
|
||||||
if is_group:
|
if is_group:
|
||||||
self.is_osram = False
|
self.is_osram = False
|
||||||
self.is_philips = False
|
self.is_philips = False
|
||||||
self.gamut_typ = 'None'
|
self.gamut_typ = GAMUT_TYPE_UNAVAILABLE
|
||||||
self.gamut = None
|
self.gamut = None
|
||||||
else:
|
else:
|
||||||
self.is_osram = light.manufacturername == 'OSRAM'
|
self.is_osram = light.manufacturername == 'OSRAM'
|
||||||
|
@ -229,6 +230,15 @@ class HueLight(Light):
|
||||||
self.gamut_typ = self.light.colorgamuttype
|
self.gamut_typ = self.light.colorgamuttype
|
||||||
self.gamut = self.light.colorgamut
|
self.gamut = self.light.colorgamut
|
||||||
_LOGGER.debug("Color gamut of %s: %s", self.name, str(self.gamut))
|
_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
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
|
|
|
@ -600,3 +600,21 @@ def check_point_in_lamps_reach(p: Tuple[float, float],
|
||||||
t = cross_product(v1, q) / cross_product(v1, v2)
|
t = cross_product(v1, q) / cross_product(v1, v2)
|
||||||
|
|
||||||
return (s >= 0.0) and (t >= 0.0) and (s + t <= 1.0)
|
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
|
||||||
|
|
|
@ -701,7 +701,9 @@ def test_available():
|
||||||
"""Test available property."""
|
"""Test available property."""
|
||||||
light = hue_light.HueLight(
|
light = hue_light.HueLight(
|
||||||
light=Mock(state={'reachable': False},
|
light=Mock(state={'reachable': False},
|
||||||
raw=LIGHT_RAW),
|
raw=LIGHT_RAW,
|
||||||
|
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||||
|
colorgamut=LIGHT_GAMUT),
|
||||||
request_bridge_update=None,
|
request_bridge_update=None,
|
||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
@ -711,7 +713,9 @@ def test_available():
|
||||||
|
|
||||||
light = hue_light.HueLight(
|
light = hue_light.HueLight(
|
||||||
light=Mock(state={'reachable': False},
|
light=Mock(state={'reachable': False},
|
||||||
raw=LIGHT_RAW),
|
raw=LIGHT_RAW,
|
||||||
|
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||||
|
colorgamut=LIGHT_GAMUT),
|
||||||
request_bridge_update=None,
|
request_bridge_update=None,
|
||||||
bridge=Mock(allow_unreachable=True),
|
bridge=Mock(allow_unreachable=True),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
@ -721,7 +725,9 @@ def test_available():
|
||||||
|
|
||||||
light = hue_light.HueLight(
|
light = hue_light.HueLight(
|
||||||
light=Mock(state={'reachable': False},
|
light=Mock(state={'reachable': False},
|
||||||
raw=LIGHT_RAW),
|
raw=LIGHT_RAW,
|
||||||
|
colorgamuttype=LIGHT_GAMUT_TYPE,
|
||||||
|
colorgamut=LIGHT_GAMUT),
|
||||||
request_bridge_update=None,
|
request_bridge_update=None,
|
||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=True,
|
is_group=True,
|
||||||
|
|
|
@ -8,6 +8,18 @@ import voluptuous as vol
|
||||||
GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
|
GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
|
||||||
color_util.XYPoint(0.2151, 0.7106),
|
color_util.XYPoint(0.2151, 0.7106),
|
||||||
color_util.XYPoint(0.138, 0.08))
|
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):
|
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(51, 153, 255) == '3399ff'
|
||||||
assert color_util.color_rgb_to_hex(255, 67.9204190, 0) == 'ff4400'
|
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):
|
class ColorTemperatureMiredToKelvinTests(unittest.TestCase):
|
||||||
"""Test color_temperature_mired_to_kelvin."""
|
"""Test color_temperature_mired_to_kelvin."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue