Config validation for MQTT

This commit is contained in:
Jan Harkes 2016-04-04 00:22:04 -04:00
parent 2e9bf42688
commit 8cca2bb344
4 changed files with 47 additions and 24 deletions

View file

@ -14,7 +14,6 @@ import voluptuous as vol
from homeassistant.bootstrap import prepare_setup_platform
from homeassistant.config import load_yaml_config_file
from homeassistant.exceptions import HomeAssistantError
import homeassistant.util as util
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
@ -58,6 +57,25 @@ ATTR_RETAIN = 'retain'
MAX_RECONNECT_WAIT = 300 # seconds
_HBMQTT_CONFIG_SCHEMA = vol.Schema(dict)
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_CLIENT_ID): cv.string,
vol.Optional(CONF_KEEPALIVE, default=DEFAULT_KEEPALIVE):
vol.All(vol.Coerce(int), vol.Range(min=15)),
vol.Optional(CONF_BROKER): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT):
vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)),
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CERTIFICATE): vol.IsFile,
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL):
[PROTOCOL_31, PROTOCOL_311],
vol.Optional(CONF_EMBEDDED): _HBMQTT_CONFIG_SCHEMA,
}),
})
# Service call validation schema
def mqtt_topic(value):
@ -136,8 +154,8 @@ def setup(hass, config):
# pylint: disable=too-many-locals
conf = config.get(DOMAIN, {})
client_id = util.convert(conf.get(CONF_CLIENT_ID), str)
keepalive = util.convert(conf.get(CONF_KEEPALIVE), int, DEFAULT_KEEPALIVE)
client_id = conf.get(CONF_CLIENT_ID)
keepalive = conf.get(CONF_KEEPALIVE)
broker_config = _setup_server(hass, config)
@ -151,16 +169,11 @@ def setup(hass, config):
if CONF_BROKER in conf:
broker = conf[CONF_BROKER]
port = util.convert(conf.get(CONF_PORT), int, DEFAULT_PORT)
username = util.convert(conf.get(CONF_USERNAME), str)
password = util.convert(conf.get(CONF_PASSWORD), str)
certificate = util.convert(conf.get(CONF_CERTIFICATE), str)
protocol = util.convert(conf.get(CONF_PROTOCOL), str, DEFAULT_PROTOCOL)
if protocol not in (PROTOCOL_31, PROTOCOL_311):
_LOGGER.error('Invalid protocol specified: %s. Allowed values: %s, %s',
protocol, PROTOCOL_31, PROTOCOL_311)
return False
port = conf[CONF_PORT]
username = conf.get(CONF_USERNAME)
password = conf.get(CONF_PASSWORD)
certificate = conf.get(CONF_CERTIFICATE)
protocol = conf[CONF_PROTOCOL]
# For cloudmqtt.com, secured connection, auto fill in certificate
if certificate is None and 19999 < port < 30000 and \

View file

@ -4,6 +4,7 @@ from datetime import timedelta
from unittest import mock
from homeassistant import core as ha, loader
from homeassistant.bootstrap import _setup_component
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.const import (
STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, EVENT_TIME_CHANGED,
@ -123,7 +124,7 @@ def mock_http_component(hass):
@mock.patch('homeassistant.components.mqtt.MQTT')
def mock_mqtt_component(hass, mock_mqtt):
"""Mock the MQTT component."""
mqtt.setup(hass, {
_setup_component(hass, mqtt.DOMAIN, {
mqtt.DOMAIN: {
mqtt.CONF_BROKER: 'mock-broker',
}

View file

@ -4,6 +4,7 @@ import unittest
from unittest import mock
import socket
from homeassistant.bootstrap import _setup_component
import homeassistant.components.mqtt as mqtt
from homeassistant.const import (
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, EVENT_HOMEASSISTANT_START,
@ -48,9 +49,11 @@ class TestMQTT(unittest.TestCase):
"""Test for setup failure if connection to broker is missing."""
with mock.patch('homeassistant.components.mqtt.MQTT',
side_effect=socket.error()):
self.assertFalse(mqtt.setup(self.hass, {mqtt.DOMAIN: {
assert not _setup_component(self.hass, mqtt.DOMAIN, {
mqtt.DOMAIN: {
mqtt.CONF_BROKER: 'test-broker',
}}))
}
})
def test_publish_calls_service(self):
"""Test the publishing of call to services."""
@ -211,7 +214,7 @@ class TestMQTTCallbacks(unittest.TestCase):
# mock_mqtt_component(self.hass)
with mock.patch('paho.mqtt.client.Client'):
mqtt.setup(self.hass, {
_setup_component(self.hass, mqtt.DOMAIN, {
mqtt.DOMAIN: {
mqtt.CONF_BROKER: 'mock-broker',
}

View file

@ -1,6 +1,7 @@
"""The tests for the MQTT component embedded server."""
from unittest.mock import MagicMock, patch
from homeassistant.bootstrap import _setup_component
import homeassistant.components.mqtt as mqtt
from tests.common import get_test_home_assistant
@ -27,15 +28,20 @@ class TestMQTT:
password = 'super_secret'
self.hass.config.api = MagicMock(api_password=password)
assert mqtt.setup(self.hass, {})
assert _setup_component(self.hass, mqtt.DOMAIN, {})
assert mock_mqtt.called
assert mock_mqtt.mock_calls[0][1][5] == 'homeassistant'
assert mock_mqtt.mock_calls[0][1][6] == password
mock_mqtt.reset_mock()
@patch('homeassistant.components.mqtt.MQTT')
@patch('asyncio.gather')
@patch('asyncio.new_event_loop')
def test_creating_config_no_http_pass(self, mock_new_loop, mock_gather,
mock_mqtt):
"""Test if the MQTT server gets started and subscribe/publish msg."""
self.hass.config.components.append('http')
self.hass.config.api = MagicMock(api_password=None)
assert mqtt.setup(self.hass, {})
assert _setup_component(self.hass, mqtt.DOMAIN, {})
assert mock_mqtt.called
assert mock_mqtt.mock_calls[0][1][5] is None
assert mock_mqtt.mock_calls[0][1][6] is None
@ -50,6 +56,6 @@ class TestMQTT:
mock_gather.side_effect = BrokerException
self.hass.config.api = MagicMock(api_password=None)
assert not mqtt.setup(self.hass, {
'mqtt': {'embedded': {}}
assert not _setup_component(self.hass, mqtt.DOMAIN, {
mqtt.DOMAIN: {mqtt.CONF_EMBEDDED: {}}
})