Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions homeassistant/components/mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import template, config_validation as cv
from homeassistant.helpers.event import threaded_listener_factory
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE)
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE,
CONF_USERNAME, CONF_PASSWORD, CONF_PORT)

_LOGGER = logging.getLogger(__name__)

Expand All @@ -33,17 +34,17 @@

CONF_EMBEDDED = 'embedded'
CONF_BROKER = 'broker'
CONF_PORT = 'port'
CONF_CLIENT_ID = 'client_id'
CONF_KEEPALIVE = 'keepalive'
CONF_USERNAME = 'username'
CONF_PASSWORD = 'password'
CONF_CERTIFICATE = 'certificate'
CONF_CLIENT_KEY = 'client_key'
CONF_CLIENT_CERT = 'client_cert'
CONF_TLS_INSECURE = 'tls_insecure'
CONF_PROTOCOL = 'protocol'

CONF_BIRTH_MESSAGE = 'birth_message'
CONF_WILL_MESSAGE = 'will_message'

CONF_STATE_TOPIC = 'state_topic'
CONF_COMMAND_TOPIC = 'command_topic'
CONF_QOS = 'qos'
Expand Down Expand Up @@ -84,14 +85,20 @@ def valid_publish_topic(value):
CLIENT_KEY_AUTH_MSG = 'client_key and client_cert must both be present in ' \
'the mqtt broker config'

MQTT_PUBLISH_SCHEMA = vol.Schema({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intended to overwrite the service schema with the same name on line 140? I think we should have separate names.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed... I commited the wrong version

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe @fabaff can fix this in #4400 ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please submit a fix for this @bestlibre or we'll have to rollback this PR before the next release (Friday).

vol.Required(ATTR_TOPIC): valid_publish_topic,
vol.Required(ATTR_PAYLOAD, 'payload'): cv.string,
vol.Required(ATTR_QOS, default=DEFAULT_QOS): _VALID_QOS_SCHEMA,
vol.Required(ATTR_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
}, required=True)

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_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CERTIFICATE): cv.isfile,
Expand All @@ -103,6 +110,8 @@ def valid_publish_topic(value):
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL):
vol.All(cv.string, vol.In([PROTOCOL_31, PROTOCOL_311])),
vol.Optional(CONF_EMBEDDED): _HBMQTT_CONFIG_SCHEMA,
vol.Optional(CONF_WILL_MESSAGE): MQTT_PUBLISH_SCHEMA,
vol.Optional(CONF_BIRTH_MESSAGE): MQTT_PUBLISH_SCHEMA
}),
}, extra=vol.ALLOW_EXTRA)

Expand Down Expand Up @@ -241,11 +250,15 @@ def setup(hass, config):
certificate = os.path.join(os.path.dirname(__file__),
'addtrustexternalcaroot.crt')

will_message = conf.get(CONF_WILL_MESSAGE)
birth_message = conf.get(CONF_BIRTH_MESSAGE)

global MQTT_CLIENT
try:
MQTT_CLIENT = MQTT(hass, broker, port, client_id, keepalive,
username, password, certificate, client_key,
client_cert, tls_insecure, protocol)
client_cert, tls_insecure, protocol, will_message,
birth_message)
except socket.error:
_LOGGER.exception("Can't connect to the broker. "
"Please check your settings and the broker "
Expand Down Expand Up @@ -296,13 +309,14 @@ class MQTT(object):

def __init__(self, hass, broker, port, client_id, keepalive, username,
password, certificate, client_key, client_cert,
tls_insecure, protocol):
tls_insecure, protocol, will_message, birth_message):
"""Initialize Home Assistant MQTT client."""
import paho.mqtt.client as mqtt

self.hass = hass
self.topics = {}
self.progress = {}
self.birth_message = birth_message

if protocol == PROTOCOL_31:
proto = mqtt.MQTTv31
Expand All @@ -329,7 +343,11 @@ def __init__(self, hass, broker, port, client_id, keepalive, username,
self._mqttc.on_connect = self._mqtt_on_connect
self._mqttc.on_disconnect = self._mqtt_on_disconnect
self._mqttc.on_message = self._mqtt_on_message

if will_message:
self._mqttc.will_set(will_message.get(ATTR_TOPIC),
will_message.get(ATTR_PAYLOAD),
will_message.get(ATTR_QOS),
will_message.get(ATTR_RETAIN))
self._mqttc.connect(broker, port, keepalive)

def publish(self, topic, payload, qos, retain):
Expand Down Expand Up @@ -365,7 +383,8 @@ def unsubscribe(self, topic):
def _mqtt_on_connect(self, _mqttc, _userdata, _flags, result_code):
"""On connect callback.

Resubscribe to all topics we were subscribed to.
Resubscribe to all topics we were subscribed to and publish birth
message.
"""
if result_code != 0:
_LOGGER.error('Unable to connect to the MQTT broker: %s', {
Expand All @@ -387,6 +406,11 @@ def _mqtt_on_connect(self, _mqttc, _userdata, _flags, result_code):
# qos is None if we were in process of subscribing
if qos is not None:
self.subscribe(topic, qos)
if self.birth_message:
self.publish(self.birth_message.get(ATTR_TOPIC),
self.birth_message.get(ATTR_PAYLOAD),
self.birth_message.get(ATTR_QOS),
self.birth_message.get(ATTR_RETAIN))

def _mqtt_on_subscribe(self, _mqttc, _userdata, mid, granted_qos):
"""Subscribe successful callback."""
Expand Down
8 changes: 8 additions & 0 deletions tests/components/mqtt/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ def setUp(self): # pylint: disable=invalid-name
assert setup_component(self.hass, mqtt.DOMAIN, {
mqtt.DOMAIN: {
mqtt.CONF_BROKER: 'mock-broker',
mqtt.CONF_BIRTH_MESSAGE: {mqtt.ATTR_TOPIC: 'birth',
mqtt.ATTR_PAYLOAD: 'birth'}
}
})

Expand Down Expand Up @@ -291,6 +293,12 @@ def test_mqtt_subscribes_topics_on_connect(self):
3: 'home/sensor',
}, mqtt.MQTT_CLIENT.progress)

def test_mqtt_birth_message_on_connect(self):
"""Test birth message on connect."""
mqtt.MQTT_CLIENT._mqtt_on_connect(None, None, 0, 0)
mqtt.MQTT_CLIENT._mqttc.publish.assert_called_with('birth', 'birth', 0,
False)

def test_mqtt_disconnect_tries_no_reconnect_on_stop(self):
"""Test the disconnect tries."""
mqtt.MQTT_CLIENT._mqtt_on_disconnect(None, None, 0)
Expand Down