diff --git a/homeassistant/components/light/mqtt.py b/homeassistant/components/light/mqtt.py index f55cc310192..47d770e4cd2 100644 --- a/homeassistant/components/light/mqtt.py +++ b/homeassistant/components/light/mqtt.py @@ -7,46 +7,85 @@ https://home-assistant.io/components/light.mqtt/ import logging from functools import partial +import voluptuous as vol + import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( 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.util import convert _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_QOS = 0 DEFAULT_PAYLOAD_ON = 'ON' DEFAULT_PAYLOAD_OFF = 'OFF' DEFAULT_OPTIMISTIC = False 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): """Add MQTT Light.""" - if config.get('command_topic') is None: - _LOGGER.error("Missing required variable: command_topic") - return False - add_devices_callback([MqttLight( hass, - convert(config.get('name'), str, DEFAULT_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), + config[CONF_NAME], { - 'on': convert(config.get('payload_on'), str, DEFAULT_PAYLOAD_ON), - 'off': convert(config.get('payload_off'), str, DEFAULT_PAYLOAD_OFF) + key: config.get(key) for key in ( + 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], )]) diff --git a/tests/components/light/test_mqtt.py b/tests/components/light/test_mqtt.py index d9343908f46..b830c2d0dd3 100644 --- a/tests/components/light/test_mqtt.py +++ b/tests/components/light/test_mqtt.py @@ -58,6 +58,7 @@ light: """ import unittest +from homeassistant.bootstrap import _setup_component from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE import homeassistant.components.light as light from tests.common import ( @@ -78,24 +79,26 @@ class TestLightMQTT(unittest.TestCase): def test_fail_setup_if_no_command_topic(self): """Test if command fails with command topic.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert not _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', } - })) + }) self.assertIsNone(self.hass.states.get('light.test')) def test_no_color_or_brightness_if_no_topics(self): """Test if there is no color and brightness if no topic.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_light_rgb/status', 'command_topic': 'test_light_rgb/set', } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) @@ -112,8 +115,9 @@ class TestLightMQTT(unittest.TestCase): def test_controlling_state_via_topic(self): """Test the controlling of the state via topic.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_light_rgb/status', @@ -126,7 +130,7 @@ class TestLightMQTT(unittest.TestCase): 'payload_on': 1, 'payload_off': 0 } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) @@ -172,8 +176,9 @@ class TestLightMQTT(unittest.TestCase): def test_controlling_scale(self): """Test the controlling scale.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_scale/status', @@ -185,7 +190,7 @@ class TestLightMQTT(unittest.TestCase): 'payload_on': 'on', 'payload_off': 'off' } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) @@ -218,8 +223,9 @@ class TestLightMQTT(unittest.TestCase): def test_controlling_state_via_topic_with_templates(self): """Test the setting og the state with a template.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_light_rgb/status', @@ -230,7 +236,7 @@ class TestLightMQTT(unittest.TestCase): 'brightness_value_template': '{{ value_json.hello }}', 'rgb_value_template': '{{ value_json.hello | join(",") }}', } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) @@ -252,8 +258,9 @@ class TestLightMQTT(unittest.TestCase): def test_sending_mqtt_commands_and_optimistic(self): """Test the sending of command in optimistic mode.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'command_topic': 'test_light_rgb/set', @@ -263,7 +270,7 @@ class TestLightMQTT(unittest.TestCase): 'payload_on': 'on', 'payload_off': 'off' } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) @@ -310,15 +317,16 @@ class TestLightMQTT(unittest.TestCase): def test_show_brightness_if_only_command_topic(self): """Test the brightness if only a command topic is present.""" - self.assertTrue(light.setup(self.hass, { - 'light': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, light.DOMAIN, { + light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'brightness_command_topic': 'test_light_rgb/brightness/set', 'command_topic': 'test_light_rgb/set', 'state_topic': 'test_light_rgb/status', } - })) + }) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state)