2016-04-13 11:50:28 +00:00
|
|
|
"""
|
|
|
|
Support for a local MQTT broker.
|
|
|
|
|
|
|
|
For more details about this component, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/mqtt/#use-the-embedded-broker
|
|
|
|
"""
|
2017-02-18 22:17:18 +00:00
|
|
|
import asyncio
|
2016-03-08 00:45:37 +00:00
|
|
|
import logging
|
|
|
|
import tempfile
|
|
|
|
|
2017-01-03 22:17:56 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2016-03-08 00:45:37 +00:00
|
|
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
2017-01-03 22:17:56 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2016-03-08 00:45:37 +00:00
|
|
|
|
2018-05-07 13:52:33 +00:00
|
|
|
REQUIREMENTS = ['hbmqtt==0.9.2']
|
2016-03-08 00:45:37 +00:00
|
|
|
DEPENDENCIES = ['http']
|
|
|
|
|
2017-01-03 22:17:56 +00:00
|
|
|
# None allows custom config to be created through generate_config
|
|
|
|
HBMQTT_CONFIG_SCHEMA = vol.Any(None, vol.Schema({
|
|
|
|
vol.Optional('auth'): vol.Schema({
|
|
|
|
vol.Optional('password-file'): cv.isfile,
|
|
|
|
}, extra=vol.ALLOW_EXTRA),
|
|
|
|
vol.Optional('listeners'): vol.Schema({
|
|
|
|
vol.Required('default'): vol.Schema(dict),
|
|
|
|
str: vol.Schema(dict)
|
|
|
|
})
|
|
|
|
}, extra=vol.ALLOW_EXTRA))
|
|
|
|
|
2016-03-08 00:45:37 +00:00
|
|
|
|
2017-02-18 22:17:18 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_start(hass, server_config):
|
|
|
|
"""Initialize MQTT Server.
|
|
|
|
|
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
2016-11-11 06:45:38 +00:00
|
|
|
from hbmqtt.broker import Broker, BrokerException
|
2016-03-08 00:45:37 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
passwd = tempfile.NamedTemporaryFile()
|
|
|
|
|
|
|
|
if server_config is None:
|
|
|
|
server_config, client_config = generate_config(hass, passwd)
|
|
|
|
else:
|
|
|
|
client_config = None
|
|
|
|
|
2016-11-11 06:45:38 +00:00
|
|
|
broker = Broker(server_config, hass.loop)
|
2017-02-18 22:17:18 +00:00
|
|
|
yield from broker.start()
|
2016-03-08 00:45:37 +00:00
|
|
|
except BrokerException:
|
2017-05-02 16:18:47 +00:00
|
|
|
logging.getLogger(__name__).exception("Error initializing MQTT server")
|
2016-03-08 00:45:37 +00:00
|
|
|
return False, None
|
|
|
|
finally:
|
|
|
|
passwd.close()
|
|
|
|
|
2017-02-18 22:17:18 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_shutdown_mqtt_server(event):
|
2016-11-11 06:45:38 +00:00
|
|
|
"""Shut down the MQTT server."""
|
2017-02-18 22:17:18 +00:00
|
|
|
yield from broker.shutdown()
|
2016-03-08 00:45:37 +00:00
|
|
|
|
2017-02-18 22:17:18 +00:00
|
|
|
hass.bus.async_listen_once(
|
|
|
|
EVENT_HOMEASSISTANT_STOP, async_shutdown_mqtt_server)
|
2016-03-08 00:45:37 +00:00
|
|
|
|
|
|
|
return True, client_config
|
|
|
|
|
|
|
|
|
|
|
|
def generate_config(hass, passwd):
|
|
|
|
"""Generate a configuration based on current Home Assistant instance."""
|
2017-01-03 22:17:56 +00:00
|
|
|
from homeassistant.components.mqtt import PROTOCOL_311
|
2016-03-08 00:45:37 +00:00
|
|
|
config = {
|
|
|
|
'listeners': {
|
|
|
|
'default': {
|
|
|
|
'max-connections': 50000,
|
|
|
|
'bind': '0.0.0.0:1883',
|
|
|
|
'type': 'tcp',
|
|
|
|
},
|
|
|
|
'ws-1': {
|
|
|
|
'bind': '0.0.0.0:8080',
|
|
|
|
'type': 'ws',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'auth': {
|
|
|
|
'allow-anonymous': hass.config.api.api_password is None
|
|
|
|
},
|
|
|
|
'plugins': ['auth_anonymous'],
|
|
|
|
}
|
|
|
|
|
|
|
|
if hass.config.api.api_password:
|
|
|
|
username = 'homeassistant'
|
|
|
|
password = hass.config.api.api_password
|
|
|
|
|
|
|
|
# Encrypt with what hbmqtt uses to verify
|
|
|
|
from passlib.apps import custom_app_context
|
|
|
|
|
|
|
|
passwd.write(
|
|
|
|
'homeassistant:{}\n'.format(
|
|
|
|
custom_app_context.encrypt(
|
|
|
|
hass.config.api.api_password)).encode('utf-8'))
|
|
|
|
passwd.flush()
|
|
|
|
|
|
|
|
config['auth']['password-file'] = passwd.name
|
|
|
|
config['plugins'].append('auth_file')
|
|
|
|
else:
|
|
|
|
username = None
|
|
|
|
password = None
|
|
|
|
|
|
|
|
client_config = ('localhost', 1883, username, password, None, PROTOCOL_311)
|
|
|
|
|
|
|
|
return config, client_config
|