Config validation for MQTT light platform.
This commit is contained in:
parent
88da42fe62
commit
29a8403741
2 changed files with 87 additions and 40 deletions
|
@ -7,46 +7,85 @@ https://home-assistant.io/components/light.mqtt/
|
||||||
import logging
|
import logging
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
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, Light)
|
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, Light)
|
||||||
|
from homeassistant.const import CONF_NAME
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.template import render_with_possible_json_value
|
from homeassistant.helpers.template import render_with_possible_json_value
|
||||||
from homeassistant.util import convert
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DEPENDENCIES = ['mqtt']
|
||||||
|
|
||||||
|
CONF_STATE_TOPIC = 'state_topic'
|
||||||
|
CONF_COMMAND_TOPIC = 'command_topic'
|
||||||
|
CONF_STATE_VALUE_TEMPLATE = 'state_value_template'
|
||||||
|
CONF_BRIGHTNESS_STATE_TOPIC = 'brightness_state_topic'
|
||||||
|
CONF_BRIGHTNESS_COMMAND_TOPIC = 'brightness_command_topic'
|
||||||
|
CONF_BRIGHTNESS_VALUE_TEMPLATE = 'brightness_value_template'
|
||||||
|
CONF_RGB_STATE_TOPIC = 'rgb_state_topic'
|
||||||
|
CONF_RGB_COMMAND_TOPIC = 'rgb_command_topic'
|
||||||
|
CONF_RGB_VALUE_TEMPLATE = 'rgb_value_template'
|
||||||
|
CONF_PAYLOAD_ON = 'payload_on'
|
||||||
|
CONF_PAYLOAD_OFF = 'payload_off'
|
||||||
|
CONF_OPTIMISTIC = 'optimistic'
|
||||||
|
CONF_BRIGHTNESS_SCALE = 'brightness_scale'
|
||||||
|
|
||||||
DEFAULT_NAME = 'MQTT Light'
|
DEFAULT_NAME = 'MQTT Light'
|
||||||
DEFAULT_QOS = 0
|
|
||||||
DEFAULT_PAYLOAD_ON = 'ON'
|
DEFAULT_PAYLOAD_ON = 'ON'
|
||||||
DEFAULT_PAYLOAD_OFF = 'OFF'
|
DEFAULT_PAYLOAD_OFF = 'OFF'
|
||||||
DEFAULT_OPTIMISTIC = False
|
DEFAULT_OPTIMISTIC = False
|
||||||
DEFAULT_BRIGHTNESS_SCALE = 255
|
DEFAULT_BRIGHTNESS_SCALE = 255
|
||||||
|
|
||||||
DEPENDENCIES = ['mqtt']
|
PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
|
vol.Required(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
|
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_BRIGHTNESS_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
|
vol.Optional(CONF_BRIGHTNESS_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
|
vol.Optional(CONF_BRIGHTNESS_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_RGB_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
|
vol.Optional(CONF_RGB_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
|
vol.Optional(CONF_RGB_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||||
|
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||||
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
|
vol.Optional(CONF_BRIGHTNESS_SCALE, default=DEFAULT_BRIGHTNESS_SCALE):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=1)),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||||
"""Add MQTT Light."""
|
"""Add MQTT Light."""
|
||||||
if config.get('command_topic') is None:
|
|
||||||
_LOGGER.error("Missing required variable: command_topic")
|
|
||||||
return False
|
|
||||||
|
|
||||||
add_devices_callback([MqttLight(
|
add_devices_callback([MqttLight(
|
||||||
hass,
|
hass,
|
||||||
convert(config.get('name'), str, DEFAULT_NAME),
|
config[CONF_NAME],
|
||||||
{key: convert(config.get(key), str) for key in
|
|
||||||
(typ + topic
|
|
||||||
for typ in ('', 'brightness_', 'rgb_')
|
|
||||||
for topic in ('state_topic', 'command_topic'))},
|
|
||||||
{key: convert(config.get(key + '_value_template'), str)
|
|
||||||
for key in ('state', 'brightness', 'rgb')},
|
|
||||||
convert(config.get('qos'), int, DEFAULT_QOS),
|
|
||||||
{
|
{
|
||||||
'on': convert(config.get('payload_on'), str, DEFAULT_PAYLOAD_ON),
|
key: config.get(key) for key in (
|
||||||
'off': convert(config.get('payload_off'), str, DEFAULT_PAYLOAD_OFF)
|
CONF_STATE_TOPIC,
|
||||||
|
CONF_COMMAND_TOPIC,
|
||||||
|
CONF_BRIGHTNESS_STATE_TOPIC,
|
||||||
|
CONF_BRIGHTNESS_COMMAND_TOPIC,
|
||||||
|
CONF_RGB_STATE_TOPIC,
|
||||||
|
CONF_RGB_COMMAND_TOPIC,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
convert(config.get('optimistic'), bool, DEFAULT_OPTIMISTIC),
|
{
|
||||||
convert(config.get('brightness_scale'), int, DEFAULT_BRIGHTNESS_SCALE)
|
'state': config.get(CONF_STATE_VALUE_TEMPLATE),
|
||||||
|
'brightness': config.get(CONF_BRIGHTNESS_VALUE_TEMPLATE),
|
||||||
|
'rgb': config.get(CONF_RGB_VALUE_TEMPLATE)
|
||||||
|
},
|
||||||
|
config[mqtt.CONF_QOS],
|
||||||
|
{
|
||||||
|
'on': config[CONF_PAYLOAD_ON],
|
||||||
|
'off': config[CONF_PAYLOAD_OFF],
|
||||||
|
},
|
||||||
|
config[CONF_OPTIMISTIC],
|
||||||
|
config[CONF_BRIGHTNESS_SCALE],
|
||||||
)])
|
)])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ light:
|
||||||
"""
|
"""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import _setup_component
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
||||||
import homeassistant.components.light as light
|
import homeassistant.components.light as light
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
|
@ -78,24 +79,26 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_fail_setup_if_no_command_topic(self):
|
def test_fail_setup_if_no_command_topic(self):
|
||||||
"""Test if command fails with command topic."""
|
"""Test if command fails with command topic."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert not _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
self.assertIsNone(self.hass.states.get('light.test'))
|
self.assertIsNone(self.hass.states.get('light.test'))
|
||||||
|
|
||||||
def test_no_color_or_brightness_if_no_topics(self):
|
def test_no_color_or_brightness_if_no_topics(self):
|
||||||
"""Test if there is no color and brightness if no topic."""
|
"""Test if there is no color and brightness if no topic."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'state_topic': 'test_light_rgb/status',
|
'state_topic': 'test_light_rgb/status',
|
||||||
'command_topic': 'test_light_rgb/set',
|
'command_topic': 'test_light_rgb/set',
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
@ -112,8 +115,9 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_controlling_state_via_topic(self):
|
def test_controlling_state_via_topic(self):
|
||||||
"""Test the controlling of the state via topic."""
|
"""Test the controlling of the state via topic."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'state_topic': 'test_light_rgb/status',
|
'state_topic': 'test_light_rgb/status',
|
||||||
|
@ -126,7 +130,7 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
'payload_on': 1,
|
'payload_on': 1,
|
||||||
'payload_off': 0
|
'payload_off': 0
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
@ -172,8 +176,9 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_controlling_scale(self):
|
def test_controlling_scale(self):
|
||||||
"""Test the controlling scale."""
|
"""Test the controlling scale."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'state_topic': 'test_scale/status',
|
'state_topic': 'test_scale/status',
|
||||||
|
@ -185,7 +190,7 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
'payload_on': 'on',
|
'payload_on': 'on',
|
||||||
'payload_off': 'off'
|
'payload_off': 'off'
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
@ -218,8 +223,9 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_controlling_state_via_topic_with_templates(self):
|
def test_controlling_state_via_topic_with_templates(self):
|
||||||
"""Test the setting og the state with a template."""
|
"""Test the setting og the state with a template."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'state_topic': 'test_light_rgb/status',
|
'state_topic': 'test_light_rgb/status',
|
||||||
|
@ -230,7 +236,7 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
'brightness_value_template': '{{ value_json.hello }}',
|
'brightness_value_template': '{{ value_json.hello }}',
|
||||||
'rgb_value_template': '{{ value_json.hello | join(",") }}',
|
'rgb_value_template': '{{ value_json.hello | join(",") }}',
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
@ -252,8 +258,9 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_sending_mqtt_commands_and_optimistic(self):
|
def test_sending_mqtt_commands_and_optimistic(self):
|
||||||
"""Test the sending of command in optimistic mode."""
|
"""Test the sending of command in optimistic mode."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'command_topic': 'test_light_rgb/set',
|
'command_topic': 'test_light_rgb/set',
|
||||||
|
@ -263,7 +270,7 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
'payload_on': 'on',
|
'payload_on': 'on',
|
||||||
'payload_off': 'off'
|
'payload_off': 'off'
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
@ -310,15 +317,16 @@ class TestLightMQTT(unittest.TestCase):
|
||||||
|
|
||||||
def test_show_brightness_if_only_command_topic(self):
|
def test_show_brightness_if_only_command_topic(self):
|
||||||
"""Test the brightness if only a command topic is present."""
|
"""Test the brightness if only a command topic is present."""
|
||||||
self.assertTrue(light.setup(self.hass, {
|
self.hass.config.components = ['mqtt']
|
||||||
'light': {
|
assert _setup_component(self.hass, light.DOMAIN, {
|
||||||
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
'brightness_command_topic': 'test_light_rgb/brightness/set',
|
'brightness_command_topic': 'test_light_rgb/brightness/set',
|
||||||
'command_topic': 'test_light_rgb/set',
|
'command_topic': 'test_light_rgb/set',
|
||||||
'state_topic': 'test_light_rgb/status',
|
'state_topic': 'test_light_rgb/status',
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
|
||||||
state = self.hass.states.get('light.test')
|
state = self.hass.states.get('light.test')
|
||||||
self.assertEqual(STATE_OFF, state.state)
|
self.assertEqual(STATE_OFF, state.state)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue