From 0bd4e15fcb6fb652e19b90d7fbc47b2be37d1172 Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Tue, 5 Apr 2016 00:22:58 -0400 Subject: [PATCH] Config validation for MQTT alarm_control_panel platform. --- .../alarm_control_panel/__init__.py | 1 + .../components/alarm_control_panel/mqtt.py | 56 ++++++----- .../alarm_control_panel/test_mqtt.py | 92 +++++++++++-------- 3 files changed, 88 insertions(+), 61 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/__init__.py b/homeassistant/components/alarm_control_panel/__init__.py index f70da3d54ec..e3bde441211 100644 --- a/homeassistant/components/alarm_control_panel/__init__.py +++ b/homeassistant/components/alarm_control_panel/__init__.py @@ -12,6 +12,7 @@ from homeassistant.const import ( ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER, SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY) from homeassistant.config import load_yaml_config_file +from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent diff --git a/homeassistant/components/alarm_control_panel/mqtt.py b/homeassistant/components/alarm_control_panel/mqtt.py index 0e86e0df875..687de5de474 100644 --- a/homeassistant/components/alarm_control_panel/mqtt.py +++ b/homeassistant/components/alarm_control_panel/mqtt.py @@ -6,42 +6,54 @@ https://home-assistant.io/components/alarm_control_panel.mqtt/ """ import logging +import voluptuous as vol + import homeassistant.components.alarm_control_panel as alarm import homeassistant.components.mqtt as mqtt from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, - STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN) + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN, + CONF_NAME) +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = "MQTT Alarm" -DEFAULT_QOS = 0 -DEFAULT_PAYLOAD_DISARM = "DISARM" -DEFAULT_PAYLOAD_ARM_HOME = "ARM_HOME" -DEFAULT_PAYLOAD_ARM_AWAY = "ARM_AWAY" - DEPENDENCIES = ['mqtt'] +CONF_STATE_TOPIC = 'state_topic' +CONF_COMMAND_TOPIC = 'command_topic' +CONF_PAYLOAD_DISARM = 'payload_disarm' +CONF_PAYLOAD_ARM_HOME = 'payload_arm_home' +CONF_PAYLOAD_ARM_AWAY = 'payload_arm_away' +CONF_CODE = 'code' + +DEFAULT_NAME = "MQTT Alarm" +DEFAULT_DISARM = "DISARM" +DEFAULT_ARM_HOME = "ARM_HOME" +DEFAULT_ARM_AWAY = "ARM_AWAY" + +PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic, + vol.Required(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic, + vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string, + vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string, + vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string, + vol.Optional(CONF_CODE): cv.string, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the MQTT platform.""" - if config.get('state_topic') is None: - _LOGGER.error("Missing required variable: state_topic") - return False - - if config.get('command_topic') is None: - _LOGGER.error("Missing required variable: command_topic") - return False - add_devices([MqttAlarm( hass, - config.get('name', DEFAULT_NAME), - config.get('state_topic'), - config.get('command_topic'), - config.get('qos', DEFAULT_QOS), - config.get('payload_disarm', DEFAULT_PAYLOAD_DISARM), - config.get('payload_arm_home', DEFAULT_PAYLOAD_ARM_HOME), - config.get('payload_arm_away', DEFAULT_PAYLOAD_ARM_AWAY), + config[CONF_NAME], + config[CONF_STATE_TOPIC], + config[CONF_COMMAND_TOPIC], + config[mqtt.CONF_QOS], + config[CONF_PAYLOAD_DISARM], + config[CONF_PAYLOAD_ARM_HOME], + config[CONF_PAYLOAD_ARM_AWAY], config.get('code'))]) diff --git a/tests/components/alarm_control_panel/test_mqtt.py b/tests/components/alarm_control_panel/test_mqtt.py index c44a2f3a120..9941c500a75 100644 --- a/tests/components/alarm_control_panel/test_mqtt.py +++ b/tests/components/alarm_control_panel/test_mqtt.py @@ -1,7 +1,7 @@ """The tests the MQTT alarm control panel component.""" import unittest -from unittest.mock import patch +from homeassistant.bootstrap import _setup_component from homeassistant.const import ( STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNKNOWN) @@ -25,37 +25,37 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): """Stop down stuff we started.""" self.hass.stop() - @patch('homeassistant.components.alarm_control_panel.mqtt._LOGGER.error') - def test_fail_setup_without_state_topic(self, mock_error): + def test_fail_setup_without_state_topic(self): """Test for failing with no state topic.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert not _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'command_topic': 'alarm/command' - }})) + } + }) - self.assertEqual(1, mock_error.call_count) - - @patch('homeassistant.components.alarm_control_panel.mqtt._LOGGER.error') - def test_fail_setup_without_command_topic(self, mock_error): + def test_fail_setup_without_command_topic(self): """Test failing with no command topic.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert not _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'state_topic': 'alarm/state' - }})) - - self.assertEqual(1, mock_error.call_count) + } + }) def test_update_state_via_state_topic(self): """Test updating with via state topic.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', - }})) + } + }) entity_id = 'alarm_control_panel.test' @@ -71,13 +71,15 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_ignore_update_state_if_unknown_via_state_topic(self): """Test ignoring updates via state topic.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', - }})) + } + }) entity_id = 'alarm_control_panel.test' @@ -90,13 +92,15 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_arm_home_publishes_mqtt(self): """Test publishing of MQTT messages while armed.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', - }})) + } + }) alarm_control_panel.alarm_arm_home(self.hass) self.hass.pool.block_till_done() @@ -105,14 +109,16 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_arm_home_not_publishes_mqtt_with_invalid_code(self): """Test not publishing of MQTT messages with invalid code.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', 'code': '1234' - }})) + } + }) call_count = self.mock_publish.call_count alarm_control_panel.alarm_arm_home(self.hass, 'abcd') @@ -121,13 +127,15 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_arm_away_publishes_mqtt(self): """Test publishing of MQTT messages while armed.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', - }})) + } + }) alarm_control_panel.alarm_arm_away(self.hass) self.hass.pool.block_till_done() @@ -136,14 +144,16 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_arm_away_not_publishes_mqtt_with_invalid_code(self): """Test not publishing of MQTT messages with invalid code.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', 'code': '1234' - }})) + } + }) call_count = self.mock_publish.call_count alarm_control_panel.alarm_arm_away(self.hass, 'abcd') @@ -152,13 +162,15 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_disarm_publishes_mqtt(self): """Test publishing of MQTT messages while disarmed.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', - }})) + } + }) alarm_control_panel.alarm_disarm(self.hass) self.hass.pool.block_till_done() @@ -167,14 +179,16 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): def test_disarm_not_publishes_mqtt_with_invalid_code(self): """Test not publishing of MQTT messages with invalid code.""" - self.assertTrue(alarm_control_panel.setup(self.hass, { - 'alarm_control_panel': { + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'alarm/state', 'command_topic': 'alarm/command', 'code': '1234' - }})) + } + }) call_count = self.mock_publish.call_count alarm_control_panel.alarm_disarm(self.hass, 'abcd')