RFC: Only use supported light properties (#15484)
* Only use supported light properties * Fix tests
This commit is contained in:
parent
e62e2bb131
commit
e427f9ee38
5 changed files with 43 additions and 34 deletions
|
@ -83,17 +83,6 @@ COLOR_GROUP = "Color descriptors"
|
|||
|
||||
LIGHT_PROFILES_FILE = "light_profiles.csv"
|
||||
|
||||
PROP_TO_ATTR = {
|
||||
'brightness': ATTR_BRIGHTNESS,
|
||||
'color_temp': ATTR_COLOR_TEMP,
|
||||
'min_mireds': ATTR_MIN_MIREDS,
|
||||
'max_mireds': ATTR_MAX_MIREDS,
|
||||
'hs_color': ATTR_HS_COLOR,
|
||||
'white_value': ATTR_WHITE_VALUE,
|
||||
'effect_list': ATTR_EFFECT_LIST,
|
||||
'effect': ATTR_EFFECT,
|
||||
}
|
||||
|
||||
# Service call validation schemas
|
||||
VALID_TRANSITION = vol.All(vol.Coerce(float), vol.Clamp(min=0, max=6553))
|
||||
VALID_BRIGHTNESS = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255))
|
||||
|
@ -494,29 +483,37 @@ class Light(ToggleEntity):
|
|||
def state_attributes(self):
|
||||
"""Return optional state attributes."""
|
||||
data = {}
|
||||
supported_features = self.supported_features
|
||||
|
||||
if self.supported_features & SUPPORT_COLOR_TEMP:
|
||||
if supported_features & SUPPORT_COLOR_TEMP:
|
||||
data[ATTR_MIN_MIREDS] = self.min_mireds
|
||||
data[ATTR_MAX_MIREDS] = self.max_mireds
|
||||
|
||||
if self.is_on:
|
||||
for prop, attr in PROP_TO_ATTR.items():
|
||||
value = getattr(self, prop)
|
||||
if value is not None:
|
||||
data[attr] = value
|
||||
if supported_features & SUPPORT_BRIGHTNESS:
|
||||
data[ATTR_BRIGHTNESS] = self.brightness
|
||||
|
||||
# Expose current color also as RGB and XY
|
||||
if ATTR_HS_COLOR in data:
|
||||
data[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(
|
||||
*data[ATTR_HS_COLOR])
|
||||
data[ATTR_XY_COLOR] = color_util.color_hs_to_xy(
|
||||
*data[ATTR_HS_COLOR])
|
||||
if supported_features & SUPPORT_COLOR_TEMP:
|
||||
data[ATTR_COLOR_TEMP] = self.color_temp
|
||||
|
||||
if self.supported_features & SUPPORT_COLOR and self.hs_color:
|
||||
# pylint: disable=unsubscriptable-object,not-an-iterable
|
||||
hs_color = self.hs_color
|
||||
data[ATTR_HS_COLOR] = (
|
||||
round(data[ATTR_HS_COLOR][0], 3),
|
||||
round(data[ATTR_HS_COLOR][1], 3),
|
||||
round(hs_color[0], 3),
|
||||
round(hs_color[1], 3),
|
||||
)
|
||||
data[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(*hs_color)
|
||||
data[ATTR_XY_COLOR] = color_util.color_hs_to_xy(*hs_color)
|
||||
|
||||
return data
|
||||
if supported_features & SUPPORT_WHITE_VALUE:
|
||||
data[ATTR_WHITE_VALUE] = self.white_value
|
||||
|
||||
if supported_features & SUPPORT_EFFECT:
|
||||
data[ATTR_EFFECT_LIST] = self.effect_list
|
||||
data[ATTR_EFFECT] = self.effect
|
||||
|
||||
return {key: val for key, val in data.items() if val is not None}
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
|
|
|
@ -205,7 +205,7 @@ class MqttLight(MqttAvailability, Light):
|
|||
topic[CONF_COLOR_TEMP_COMMAND_TOPIC] is not None and
|
||||
SUPPORT_COLOR_TEMP)
|
||||
self._supported_features |= (
|
||||
topic[CONF_EFFECT_STATE_TOPIC] is not None and
|
||||
topic[CONF_EFFECT_COMMAND_TOPIC] is not None and
|
||||
SUPPORT_EFFECT)
|
||||
self._supported_features |= (
|
||||
topic[CONF_WHITE_VALUE_COMMAND_TOPIC] is not None and
|
||||
|
|
|
@ -200,21 +200,24 @@ async def test_effect_list(hass):
|
|||
}})
|
||||
|
||||
hass.states.async_set('light.test1', 'on',
|
||||
{'effect_list': ['None', 'Random', 'Colorloop']})
|
||||
{'effect_list': ['None', 'Random', 'Colorloop'],
|
||||
'supported_features': 4})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert set(state.attributes['effect_list']) == {
|
||||
'None', 'Random', 'Colorloop'}
|
||||
|
||||
hass.states.async_set('light.test2', 'on',
|
||||
{'effect_list': ['None', 'Random', 'Rainbow']})
|
||||
{'effect_list': ['None', 'Random', 'Rainbow'],
|
||||
'supported_features': 4})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert set(state.attributes['effect_list']) == {
|
||||
'None', 'Random', 'Colorloop', 'Rainbow'}
|
||||
|
||||
hass.states.async_set('light.test1', 'off',
|
||||
{'effect_list': ['None', 'Colorloop', 'Seven']})
|
||||
{'effect_list': ['None', 'Colorloop', 'Seven'],
|
||||
'supported_features': 4})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert set(state.attributes['effect_list']) == {
|
||||
|
@ -229,27 +232,27 @@ async def test_effect(hass):
|
|||
}})
|
||||
|
||||
hass.states.async_set('light.test1', 'on',
|
||||
{'effect': 'None', 'supported_features': 2})
|
||||
{'effect': 'None', 'supported_features': 6})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert state.attributes['effect'] == 'None'
|
||||
|
||||
hass.states.async_set('light.test2', 'on',
|
||||
{'effect': 'None', 'supported_features': 2})
|
||||
{'effect': 'None', 'supported_features': 6})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert state.attributes['effect'] == 'None'
|
||||
|
||||
hass.states.async_set('light.test3', 'on',
|
||||
{'effect': 'Random', 'supported_features': 2})
|
||||
{'effect': 'Random', 'supported_features': 6})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert state.attributes['effect'] == 'None'
|
||||
|
||||
hass.states.async_set('light.test1', 'off',
|
||||
{'effect': 'None', 'supported_features': 2})
|
||||
{'effect': 'None', 'supported_features': 6})
|
||||
hass.states.async_set('light.test2', 'off',
|
||||
{'effect': 'None', 'supported_features': 2})
|
||||
{'effect': 'None', 'supported_features': 6})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get('light.light_group')
|
||||
assert state.attributes['effect'] == 'Random'
|
||||
|
|
|
@ -415,6 +415,12 @@ class TestLightMQTT(unittest.TestCase):
|
|||
'name': 'test',
|
||||
'state_topic': 'test_light_rgb/status',
|
||||
'command_topic': 'test_light_rgb/set',
|
||||
'brightness_command_topic': 'test_light_rgb/brightness/set',
|
||||
'rgb_command_topic': 'test_light_rgb/rgb/set',
|
||||
'color_temp_command_topic': 'test_light_rgb/color_temp/set',
|
||||
'effect_command_topic': 'test_light_rgb/effect/set',
|
||||
'white_value_command_topic': 'test_light_rgb/white_value/set',
|
||||
'xy_command_topic': 'test_light_rgb/xy/set',
|
||||
'brightness_state_topic': 'test_light_rgb/brightness/status',
|
||||
'color_temp_state_topic': 'test_light_rgb/color_temp/status',
|
||||
'effect_state_topic': 'test_light_rgb/effect/status',
|
||||
|
@ -475,6 +481,7 @@ class TestLightMQTT(unittest.TestCase):
|
|||
'effect_command_topic': 'test_light_rgb/effect/set',
|
||||
'white_value_command_topic': 'test_light_rgb/white_value/set',
|
||||
'xy_command_topic': 'test_light_rgb/xy/set',
|
||||
'effect_list': ['colorloop', 'random'],
|
||||
'qos': 2,
|
||||
'payload_on': 'on',
|
||||
'payload_off': 'off'
|
||||
|
|
|
@ -228,6 +228,8 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||
'{{ green|d }}-'
|
||||
'{{ blue|d }}',
|
||||
'command_off_template': 'off',
|
||||
'effect_list': ['colorloop', 'random'],
|
||||
'effect_command_topic': 'test_light_rgb/effect/set',
|
||||
'qos': 2
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue