mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Light effects (#4538)
* Add support for light effects * Move PLATFORM_SCHEMA changes in light to mqtt_template * Add effect validation * Add unittests * Add light effect to demo and unittests * Use cv.string for config validation * Use cv.ensure_list for config validation * Fix typo * Remove unused exception management for effect
This commit is contained in:
parent
cf57db919e
commit
f0db698f75
@ -64,6 +64,9 @@ ATTR_FLASH = "flash"
|
|||||||
FLASH_SHORT = "short"
|
FLASH_SHORT = "short"
|
||||||
FLASH_LONG = "long"
|
FLASH_LONG = "long"
|
||||||
|
|
||||||
|
# List of possible effects
|
||||||
|
ATTR_EFFECT_LIST = "effect_list"
|
||||||
|
|
||||||
# Apply an effect to the light, can be EFFECT_COLORLOOP.
|
# Apply an effect to the light, can be EFFECT_COLORLOOP.
|
||||||
ATTR_EFFECT = "effect"
|
ATTR_EFFECT = "effect"
|
||||||
EFFECT_COLORLOOP = "colorloop"
|
EFFECT_COLORLOOP = "colorloop"
|
||||||
@ -78,6 +81,8 @@ PROP_TO_ATTR = {
|
|||||||
'rgb_color': ATTR_RGB_COLOR,
|
'rgb_color': ATTR_RGB_COLOR,
|
||||||
'xy_color': ATTR_XY_COLOR,
|
'xy_color': ATTR_XY_COLOR,
|
||||||
'white_value': ATTR_WHITE_VALUE,
|
'white_value': ATTR_WHITE_VALUE,
|
||||||
|
'effect_list': ATTR_EFFECT_LIST,
|
||||||
|
'effect': ATTR_EFFECT,
|
||||||
'supported_features': ATTR_SUPPORTED_FEATURES,
|
'supported_features': ATTR_SUPPORTED_FEATURES,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,10 +92,10 @@ VALID_BRIGHTNESS = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255))
|
|||||||
|
|
||||||
LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
||||||
ATTR_ENTITY_ID: cv.entity_ids,
|
ATTR_ENTITY_ID: cv.entity_ids,
|
||||||
ATTR_PROFILE: str,
|
ATTR_PROFILE: cv.string,
|
||||||
ATTR_TRANSITION: VALID_TRANSITION,
|
ATTR_TRANSITION: VALID_TRANSITION,
|
||||||
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
||||||
ATTR_COLOR_NAME: str,
|
ATTR_COLOR_NAME: cv.string,
|
||||||
ATTR_RGB_COLOR: vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)),
|
ATTR_RGB_COLOR: vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)),
|
||||||
vol.Coerce(tuple)),
|
vol.Coerce(tuple)),
|
||||||
ATTR_XY_COLOR: vol.All(vol.ExactSequence((cv.small_float, cv.small_float)),
|
ATTR_XY_COLOR: vol.All(vol.ExactSequence((cv.small_float, cv.small_float)),
|
||||||
@ -99,7 +104,7 @@ LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
|||||||
max=color_util.HASS_COLOR_MAX)),
|
max=color_util.HASS_COLOR_MAX)),
|
||||||
ATTR_WHITE_VALUE: vol.All(int, vol.Range(min=0, max=255)),
|
ATTR_WHITE_VALUE: vol.All(int, vol.Range(min=0, max=255)),
|
||||||
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
||||||
ATTR_EFFECT: vol.In([EFFECT_COLORLOOP, EFFECT_RANDOM, EFFECT_WHITE]),
|
ATTR_EFFECT: cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
LIGHT_TURN_OFF_SCHEMA = vol.Schema({
|
LIGHT_TURN_OFF_SCHEMA = vol.Schema({
|
||||||
@ -314,6 +319,16 @@ class Light(ToggleEntity):
|
|||||||
"""Return the white value of this light between 0..255."""
|
"""Return the white value of this light between 0..255."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect_list(self):
|
||||||
|
"""Return the list of supported effects."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect(self):
|
||||||
|
"""Return the current effect."""
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_attributes(self):
|
def state_attributes(self):
|
||||||
"""Return optional state attributes."""
|
"""Return optional state attributes."""
|
||||||
|
@ -7,25 +7,29 @@ https://home-assistant.io/components/demo/
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_WHITE_VALUE,
|
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT,
|
||||||
ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR,
|
ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_XY_COLOR, SUPPORT_BRIGHTNESS,
|
||||||
SUPPORT_WHITE_VALUE, Light)
|
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE,
|
||||||
|
Light)
|
||||||
|
|
||||||
LIGHT_COLORS = [
|
LIGHT_COLORS = [
|
||||||
[237, 224, 33],
|
[237, 224, 33],
|
||||||
[255, 63, 111],
|
[255, 63, 111],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
LIGHT_EFFECT_LIST = ['rainbow', 'none']
|
||||||
|
|
||||||
LIGHT_TEMPS = [240, 380]
|
LIGHT_TEMPS = [240, 380]
|
||||||
|
|
||||||
SUPPORT_DEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR |
|
SUPPORT_DEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT |
|
||||||
SUPPORT_WHITE_VALUE)
|
SUPPORT_RGB_COLOR | SUPPORT_WHITE_VALUE)
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||||
"""Setup the demo light platform."""
|
"""Setup the demo light platform."""
|
||||||
add_devices_callback([
|
add_devices_callback([
|
||||||
DemoLight("Bed Light", False),
|
DemoLight("Bed Light", False, effect_list=LIGHT_EFFECT_LIST,
|
||||||
|
effect=LIGHT_EFFECT_LIST[0]),
|
||||||
DemoLight("Ceiling Lights", True, LIGHT_COLORS[0], LIGHT_TEMPS[1]),
|
DemoLight("Ceiling Lights", True, LIGHT_COLORS[0], LIGHT_TEMPS[1]),
|
||||||
DemoLight("Kitchen Lights", True, LIGHT_COLORS[1], LIGHT_TEMPS[0])
|
DemoLight("Kitchen Lights", True, LIGHT_COLORS[1], LIGHT_TEMPS[0])
|
||||||
])
|
])
|
||||||
@ -36,7 +40,7 @@ class DemoLight(Light):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, name, state, rgb=None, ct=None, brightness=180,
|
self, name, state, rgb=None, ct=None, brightness=180,
|
||||||
xy_color=(.5, .5), white=200):
|
xy_color=(.5, .5), white=200, effect_list=None, effect=None):
|
||||||
"""Initialize the light."""
|
"""Initialize the light."""
|
||||||
self._name = name
|
self._name = name
|
||||||
self._state = state
|
self._state = state
|
||||||
@ -45,6 +49,8 @@ class DemoLight(Light):
|
|||||||
self._brightness = brightness
|
self._brightness = brightness
|
||||||
self._xy_color = xy_color
|
self._xy_color = xy_color
|
||||||
self._white = white
|
self._white = white
|
||||||
|
self._effect_list = effect_list
|
||||||
|
self._effect = effect
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -81,6 +87,16 @@ class DemoLight(Light):
|
|||||||
"""Return the white value of this light between 0..255."""
|
"""Return the white value of this light between 0..255."""
|
||||||
return self._white
|
return self._white
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect_list(self):
|
||||||
|
"""Return the list of supported effects."""
|
||||||
|
return self._effect_list
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect(self):
|
||||||
|
"""Return the current effect."""
|
||||||
|
return self._effect
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return true if light is on."""
|
"""Return true if light is on."""
|
||||||
@ -110,6 +126,9 @@ class DemoLight(Light):
|
|||||||
if ATTR_WHITE_VALUE in kwargs:
|
if ATTR_WHITE_VALUE in kwargs:
|
||||||
self._white = kwargs[ATTR_WHITE_VALUE]
|
self._white = kwargs[ATTR_WHITE_VALUE]
|
||||||
|
|
||||||
|
if ATTR_EFFECT in kwargs:
|
||||||
|
self._effect = kwargs[ATTR_EFFECT]
|
||||||
|
|
||||||
self.update_ha_state()
|
self.update_ha_state()
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
def turn_off(self, **kwargs):
|
||||||
|
@ -10,8 +10,8 @@ import voluptuous as vol
|
|||||||
|
|
||||||
import homeassistant.components.mqtt as mqtt
|
import homeassistant.components.mqtt as mqtt
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, PLATFORM_SCHEMA,
|
ATTR_BRIGHTNESS, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION,
|
||||||
ATTR_FLASH, SUPPORT_BRIGHTNESS, SUPPORT_FLASH,
|
PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, SUPPORT_EFFECT, SUPPORT_FLASH,
|
||||||
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light)
|
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light)
|
||||||
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, STATE_ON, STATE_OFF
|
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, STATE_ON, STATE_OFF
|
||||||
from homeassistant.components.mqtt import (
|
from homeassistant.components.mqtt import (
|
||||||
@ -27,6 +27,7 @@ DEPENDENCIES = ['mqtt']
|
|||||||
DEFAULT_NAME = 'MQTT Template Light'
|
DEFAULT_NAME = 'MQTT Template Light'
|
||||||
DEFAULT_OPTIMISTIC = False
|
DEFAULT_OPTIMISTIC = False
|
||||||
|
|
||||||
|
CONF_EFFECT_LIST = "effect_list"
|
||||||
CONF_COMMAND_ON_TEMPLATE = 'command_on_template'
|
CONF_COMMAND_ON_TEMPLATE = 'command_on_template'
|
||||||
CONF_COMMAND_OFF_TEMPLATE = 'command_off_template'
|
CONF_COMMAND_OFF_TEMPLATE = 'command_off_template'
|
||||||
CONF_STATE_TEMPLATE = 'state_template'
|
CONF_STATE_TEMPLATE = 'state_template'
|
||||||
@ -34,12 +35,14 @@ CONF_BRIGHTNESS_TEMPLATE = 'brightness_template'
|
|||||||
CONF_RED_TEMPLATE = 'red_template'
|
CONF_RED_TEMPLATE = 'red_template'
|
||||||
CONF_GREEN_TEMPLATE = 'green_template'
|
CONF_GREEN_TEMPLATE = 'green_template'
|
||||||
CONF_BLUE_TEMPLATE = 'blue_template'
|
CONF_BLUE_TEMPLATE = 'blue_template'
|
||||||
|
CONF_EFFECT_TEMPLATE = 'effect_template'
|
||||||
|
|
||||||
SUPPORT_MQTT_TEMPLATE = (SUPPORT_BRIGHTNESS | SUPPORT_FLASH |
|
SUPPORT_MQTT_TEMPLATE = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_FLASH |
|
||||||
SUPPORT_RGB_COLOR | SUPPORT_TRANSITION)
|
SUPPORT_RGB_COLOR | SUPPORT_TRANSITION)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_EFFECT_LIST): vol.All(cv.ensure_list, [cv.string]),
|
||||||
vol.Required(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
vol.Required(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
vol.Optional(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
vol.Optional(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
vol.Required(CONF_COMMAND_ON_TEMPLATE): cv.template,
|
vol.Required(CONF_COMMAND_ON_TEMPLATE): cv.template,
|
||||||
@ -49,6 +52,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_RED_TEMPLATE): cv.template,
|
vol.Optional(CONF_RED_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_GREEN_TEMPLATE): cv.template,
|
vol.Optional(CONF_GREEN_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_BLUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_BLUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_EFFECT_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
vol.Optional(CONF_QOS, default=mqtt.DEFAULT_QOS):
|
vol.Optional(CONF_QOS, default=mqtt.DEFAULT_QOS):
|
||||||
vol.All(vol.Coerce(int), vol.In([0, 1, 2])),
|
vol.All(vol.Coerce(int), vol.In([0, 1, 2])),
|
||||||
@ -61,6 +65,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
add_devices([MqttTemplate(
|
add_devices([MqttTemplate(
|
||||||
hass,
|
hass,
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
|
config.get(CONF_EFFECT_LIST),
|
||||||
{
|
{
|
||||||
key: config.get(key) for key in (
|
key: config.get(key) for key in (
|
||||||
CONF_STATE_TOPIC,
|
CONF_STATE_TOPIC,
|
||||||
@ -75,7 +80,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
CONF_BRIGHTNESS_TEMPLATE,
|
CONF_BRIGHTNESS_TEMPLATE,
|
||||||
CONF_RED_TEMPLATE,
|
CONF_RED_TEMPLATE,
|
||||||
CONF_GREEN_TEMPLATE,
|
CONF_GREEN_TEMPLATE,
|
||||||
CONF_BLUE_TEMPLATE
|
CONF_BLUE_TEMPLATE,
|
||||||
|
CONF_EFFECT_TEMPLATE
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
config.get(CONF_OPTIMISTIC),
|
config.get(CONF_OPTIMISTIC),
|
||||||
@ -87,10 +93,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
class MqttTemplate(Light):
|
class MqttTemplate(Light):
|
||||||
"""Representation of a MQTT Template light."""
|
"""Representation of a MQTT Template light."""
|
||||||
|
|
||||||
def __init__(self, hass, name, topics, templates, optimistic, qos, retain):
|
def __init__(self, hass, name, effect_list, topics, templates, optimistic,
|
||||||
|
qos, retain):
|
||||||
"""Initialize MQTT Template light."""
|
"""Initialize MQTT Template light."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._effect_list = effect_list
|
||||||
self._topics = topics
|
self._topics = topics
|
||||||
self._templates = templates
|
self._templates = templates
|
||||||
for tpl in self._templates.values():
|
for tpl in self._templates.values():
|
||||||
@ -114,6 +122,7 @@ class MqttTemplate(Light):
|
|||||||
self._rgb = [0, 0, 0]
|
self._rgb = [0, 0, 0]
|
||||||
else:
|
else:
|
||||||
self._rgb = None
|
self._rgb = None
|
||||||
|
self._effect = None
|
||||||
|
|
||||||
def state_received(topic, payload, qos):
|
def state_received(topic, payload, qos):
|
||||||
"""A new MQTT message has been received."""
|
"""A new MQTT message has been received."""
|
||||||
@ -152,6 +161,17 @@ class MqttTemplate(Light):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.warning('Invalid color value received')
|
_LOGGER.warning('Invalid color value received')
|
||||||
|
|
||||||
|
# read effect
|
||||||
|
if self._templates[CONF_EFFECT_TEMPLATE] is not None:
|
||||||
|
effect = self._templates[CONF_EFFECT_TEMPLATE].\
|
||||||
|
render_with_possible_json_value(payload)
|
||||||
|
|
||||||
|
# validate effect value
|
||||||
|
if effect in self._effect_list:
|
||||||
|
self._effect = effect
|
||||||
|
else:
|
||||||
|
_LOGGER.warning('Unsupported effect value received')
|
||||||
|
|
||||||
self.update_ha_state()
|
self.update_ha_state()
|
||||||
|
|
||||||
if self._topics[CONF_STATE_TOPIC] is not None:
|
if self._topics[CONF_STATE_TOPIC] is not None:
|
||||||
@ -191,6 +211,16 @@ class MqttTemplate(Light):
|
|||||||
"""Return True if unable to access real state of the entity."""
|
"""Return True if unable to access real state of the entity."""
|
||||||
return self._optimistic
|
return self._optimistic
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect_list(self):
|
||||||
|
"""Return the list of supported effects."""
|
||||||
|
return self._effect_list
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect(self):
|
||||||
|
"""Return the current effect."""
|
||||||
|
return self._effect
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
def turn_on(self, **kwargs):
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
# state
|
# state
|
||||||
@ -214,6 +244,10 @@ class MqttTemplate(Light):
|
|||||||
if self._optimistic:
|
if self._optimistic:
|
||||||
self._rgb = kwargs[ATTR_RGB_COLOR]
|
self._rgb = kwargs[ATTR_RGB_COLOR]
|
||||||
|
|
||||||
|
# effect
|
||||||
|
if ATTR_EFFECT in kwargs:
|
||||||
|
values['effect'] = kwargs.get(ATTR_EFFECT)
|
||||||
|
|
||||||
# flash
|
# flash
|
||||||
if ATTR_FLASH in kwargs:
|
if ATTR_FLASH in kwargs:
|
||||||
values['flash'] = kwargs.get(ATTR_FLASH)
|
values['flash'] = kwargs.get(ATTR_FLASH)
|
||||||
|
@ -37,6 +37,7 @@ class TestDemoClimate(unittest.TestCase):
|
|||||||
self.assertEqual(25, state.attributes.get(light.ATTR_BRIGHTNESS))
|
self.assertEqual(25, state.attributes.get(light.ATTR_BRIGHTNESS))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(82, 91, 0), state.attributes.get(light.ATTR_RGB_COLOR))
|
(82, 91, 0), state.attributes.get(light.ATTR_RGB_COLOR))
|
||||||
|
self.assertEqual('rainbow', state.attributes.get(light.ATTR_EFFECT))
|
||||||
light.turn_on(
|
light.turn_on(
|
||||||
self.hass, ENTITY_LIGHT, rgb_color=(251, 252, 253),
|
self.hass, ENTITY_LIGHT, rgb_color=(251, 252, 253),
|
||||||
white_value=254)
|
white_value=254)
|
||||||
@ -45,10 +46,11 @@ class TestDemoClimate(unittest.TestCase):
|
|||||||
self.assertEqual(254, state.attributes.get(light.ATTR_WHITE_VALUE))
|
self.assertEqual(254, state.attributes.get(light.ATTR_WHITE_VALUE))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(251, 252, 253), state.attributes.get(light.ATTR_RGB_COLOR))
|
(251, 252, 253), state.attributes.get(light.ATTR_RGB_COLOR))
|
||||||
light.turn_on(self.hass, ENTITY_LIGHT, color_temp=400)
|
light.turn_on(self.hass, ENTITY_LIGHT, color_temp=400, effect='none')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
state = self.hass.states.get(ENTITY_LIGHT)
|
state = self.hass.states.get(ENTITY_LIGHT)
|
||||||
self.assertEqual(400, state.attributes.get(light.ATTR_COLOR_TEMP))
|
self.assertEqual(400, state.attributes.get(light.ATTR_COLOR_TEMP))
|
||||||
|
self.assertEqual('none', state.attributes.get(light.ATTR_EFFECT))
|
||||||
|
|
||||||
def test_turn_off(self):
|
def test_turn_off(self):
|
||||||
"""Test light turn off method."""
|
"""Test light turn off method."""
|
||||||
|
@ -90,22 +90,24 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
self.assertIsNone(state.attributes.get('rgb_color'))
|
self.assertIsNone(state.attributes.get('rgb_color'))
|
||||||
self.assertIsNone(state.attributes.get('brightness'))
|
self.assertIsNone(state.attributes.get('brightness'))
|
||||||
|
|
||||||
def test_state_brightness_color_change_via_topic(self): \
|
def test_state_brightness_color_effect_change_via_topic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test state, brightness and color change via topic."""
|
"""Test state, brightness, color and effect change via topic."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_template',
|
'platform': 'mqtt_template',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
'effect_list': ['rainbow', 'colorloop'],
|
||||||
'state_topic': 'test_light_rgb',
|
'state_topic': 'test_light_rgb',
|
||||||
'command_topic': 'test_light_rgb/set',
|
'command_topic': 'test_light_rgb/set',
|
||||||
'command_on_template': 'on,'
|
'command_on_template': 'on,'
|
||||||
'{{ brightness|d }},'
|
'{{ brightness|d }},'
|
||||||
'{{ red|d }}-'
|
'{{ red|d }}-'
|
||||||
'{{ green|d }}-'
|
'{{ green|d }}-'
|
||||||
'{{ blue|d }}',
|
'{{ blue|d }},'
|
||||||
|
'{{ effect|d }}',
|
||||||
'command_off_template': 'off',
|
'command_off_template': 'off',
|
||||||
'state_template': '{{ value.split(",")[0] }}',
|
'state_template': '{{ value.split(",")[0] }}',
|
||||||
'brightness_template': '{{ value.split(",")[1] }}',
|
'brightness_template': '{{ value.split(",")[1] }}',
|
||||||
@ -114,7 +116,8 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
'green_template': '{{ value.split(",")[2].'
|
'green_template': '{{ value.split(",")[2].'
|
||||||
'split("-")[1] }}',
|
'split("-")[1] }}',
|
||||||
'blue_template': '{{ value.split(",")[2].'
|
'blue_template': '{{ value.split(",")[2].'
|
||||||
'split("-")[2] }}'
|
'split("-")[2] }}',
|
||||||
|
'effect_template': '{{ value.split(",")[3] }}'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -122,16 +125,18 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
self.assertIsNone(state.attributes.get('rgb_color'))
|
self.assertIsNone(state.attributes.get('rgb_color'))
|
||||||
self.assertIsNone(state.attributes.get('brightness'))
|
self.assertIsNone(state.attributes.get('brightness'))
|
||||||
|
self.assertIsNone(state.attributes.get('effect'))
|
||||||
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
|
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
|
||||||
|
|
||||||
# turn on the light, full white
|
# turn on the light, full white
|
||||||
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,255-255-255')
|
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,255-255-255,')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_ON, state.state)
|
self.assertEqual(STATE_ON, state.state)
|
||||||
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
||||||
self.assertEqual(255, state.attributes.get('brightness'))
|
self.assertEqual(255, state.attributes.get('brightness'))
|
||||||
|
self.assertIsNone(state.attributes.get('effect'))
|
||||||
|
|
||||||
# turn the light off
|
# turn the light off
|
||||||
fire_mqtt_message(self.hass, 'test_light_rgb', 'off')
|
fire_mqtt_message(self.hass, 'test_light_rgb', 'off')
|
||||||
@ -155,6 +160,13 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
light_state = self.hass.states.get('light.test')
|
light_state = self.hass.states.get('light.test')
|
||||||
self.assertEqual([41, 42, 43], light_state.attributes.get('rgb_color'))
|
self.assertEqual([41, 42, 43], light_state.attributes.get('rgb_color'))
|
||||||
|
|
||||||
|
# change the effect
|
||||||
|
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,41-42-43,rainbow')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
light_state = self.hass.states.get('light.test')
|
||||||
|
self.assertEqual('rainbow', light_state.attributes.get('effect'))
|
||||||
|
|
||||||
def test_optimistic(self): \
|
def test_optimistic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test optimistic mode."""
|
"""Test optimistic mode."""
|
||||||
@ -314,13 +326,15 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_template',
|
'platform': 'mqtt_template',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
'effect_list': ['rainbow', 'colorloop'],
|
||||||
'state_topic': 'test_light_rgb',
|
'state_topic': 'test_light_rgb',
|
||||||
'command_topic': 'test_light_rgb/set',
|
'command_topic': 'test_light_rgb/set',
|
||||||
'command_on_template': 'on,'
|
'command_on_template': 'on,'
|
||||||
'{{ brightness|d }},'
|
'{{ brightness|d }},'
|
||||||
'{{ red|d }}-'
|
'{{ red|d }}-'
|
||||||
'{{ green|d }}-'
|
'{{ green|d }}-'
|
||||||
'{{ blue|d }}',
|
'{{ blue|d }},'
|
||||||
|
'{{ effect|d }}',
|
||||||
'command_off_template': 'off',
|
'command_off_template': 'off',
|
||||||
'state_template': '{{ value.split(",")[0] }}',
|
'state_template': '{{ value.split(",")[0] }}',
|
||||||
'brightness_template': '{{ value.split(",")[1] }}',
|
'brightness_template': '{{ value.split(",")[1] }}',
|
||||||
@ -329,7 +343,8 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
'green_template': '{{ value.split(",")[2].'
|
'green_template': '{{ value.split(",")[2].'
|
||||||
'split("-")[1] }}',
|
'split("-")[1] }}',
|
||||||
'blue_template': '{{ value.split(",")[2].'
|
'blue_template': '{{ value.split(",")[2].'
|
||||||
'split("-")[2] }}'
|
'split("-")[2] }}',
|
||||||
|
'effect_template': '{{ value.split(",")[3] }}',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -337,16 +352,19 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
self.assertIsNone(state.attributes.get('rgb_color'))
|
self.assertIsNone(state.attributes.get('rgb_color'))
|
||||||
self.assertIsNone(state.attributes.get('brightness'))
|
self.assertIsNone(state.attributes.get('brightness'))
|
||||||
|
self.assertIsNone(state.attributes.get('effect'))
|
||||||
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
|
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
|
||||||
|
|
||||||
# turn on the light, full white
|
# turn on the light, full white
|
||||||
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,255-255-255')
|
fire_mqtt_message(self.hass, 'test_light_rgb',
|
||||||
|
'on,255,255-255-255,rainbow')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_ON, state.state)
|
self.assertEqual(STATE_ON, state.state)
|
||||||
self.assertEqual(255, state.attributes.get('brightness'))
|
self.assertEqual(255, state.attributes.get('brightness'))
|
||||||
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
||||||
|
self.assertEqual('rainbow', state.attributes.get('effect'))
|
||||||
|
|
||||||
# bad state value
|
# bad state value
|
||||||
fire_mqtt_message(self.hass, 'test_light_rgb', 'offf')
|
fire_mqtt_message(self.hass, 'test_light_rgb', 'offf')
|
||||||
@ -371,3 +389,11 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
# color should not have changed
|
# color should not have changed
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color'))
|
||||||
|
|
||||||
|
# bad effect value
|
||||||
|
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,255,a-b-c,white')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
# effect should not have changed
|
||||||
|
state = self.hass.states.get('light.test')
|
||||||
|
self.assertEqual('rainbow', state.attributes.get('effect'))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user