diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index f631ee45f87..7c7b8f6eb11 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -42,7 +42,7 @@ from homeassistant.util.logging import catch_log_exception # Loading the config flow file will register the flow from . import config_flow # noqa: F401 pylint: disable=unused-import -from . import debug_info, discovery, server +from . import debug_info, discovery from .const import ( ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_TOPIC, @@ -80,8 +80,6 @@ DATA_MQTT_CONFIG = "mqtt_config" SERVICE_PUBLISH = "publish" SERVICE_DUMP = "dump" -CONF_EMBEDDED = "embedded" - CONF_DISCOVERY_PREFIX = "discovery_prefix" CONF_KEEPALIVE = "keepalive" CONF_CERTIFICATE = "certificate" @@ -169,7 +167,7 @@ CONFIG_SCHEMA = vol.Schema( vol.Optional(CONF_KEEPALIVE, default=DEFAULT_KEEPALIVE): vol.All( vol.Coerce(int), vol.Range(min=15) ), - vol.Optional(CONF_BROKER): cv.string, + vol.Required(CONF_BROKER): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, @@ -187,9 +185,6 @@ CONFIG_SCHEMA = vol.Schema( vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL): vol.All( cv.string, vol.In([PROTOCOL_31, PROTOCOL_311]) ), - vol.Optional(CONF_EMBEDDED): vol.All( - server.HBMQTT_CONFIG_SCHEMA, embedded_broker_deprecated - ), vol.Optional(CONF_WILL_MESSAGE): MQTT_WILL_BIRTH_SCHEMA, vol.Optional(CONF_BIRTH_MESSAGE): MQTT_WILL_BIRTH_SCHEMA, vol.Optional(CONF_DISCOVERY, default=DEFAULT_DISCOVERY): cv.boolean, @@ -418,23 +413,6 @@ def subscribe( return remove -async def _async_setup_server(hass: HomeAssistantType, config: ConfigType): - """Try to start embedded MQTT broker. - - This method is a coroutine. - """ - conf: ConfigType = config.get(DOMAIN, {}) - - success, broker_config = await server.async_start( - hass, conf.get(CONF_PASSWORD), conf.get(CONF_EMBEDDED) - ) - - if not success: - return None - - return broker_config - - async def _async_setup_discovery( hass: HomeAssistantType, conf: ConfigType, config_entry ) -> bool: @@ -464,28 +442,6 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: conf = dict(conf) - if CONF_EMBEDDED in conf or CONF_BROKER not in conf: - - broker_config = await _async_setup_server(hass, config) - - if broker_config is None: - _LOGGER.error("Unable to start embedded MQTT broker") - return False - - conf.update( - { - CONF_BROKER: broker_config[0], - CONF_PORT: broker_config[1], - CONF_USERNAME: broker_config[2], - CONF_PASSWORD: broker_config[3], - CONF_CERTIFICATE: broker_config[4], - CONF_PROTOCOL: broker_config[5], - CONF_CLIENT_KEY: None, - CONF_CLIENT_CERT: None, - CONF_TLS_INSECURE: None, - } - ) - hass.data[DATA_MQTT_CONFIG] = conf # Only import if we haven't before. diff --git a/homeassistant/components/mqtt/manifest.json b/homeassistant/components/mqtt/manifest.json index 37070627477..8b293eb06f6 100644 --- a/homeassistant/components/mqtt/manifest.json +++ b/homeassistant/components/mqtt/manifest.json @@ -3,7 +3,7 @@ "name": "MQTT", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/mqtt", - "requirements": ["hbmqtt==0.9.5", "paho-mqtt==1.5.0"], + "requirements": ["paho-mqtt==1.5.0"], "dependencies": ["http"], "codeowners": ["@home-assistant/core", "@emontnemery"] } diff --git a/homeassistant/components/mqtt/server.py b/homeassistant/components/mqtt/server.py deleted file mode 100644 index 1b2a56a2195..00000000000 --- a/homeassistant/components/mqtt/server.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Support for a local MQTT broker.""" -import logging -import tempfile - -import voluptuous as vol - -from homeassistant.const import EVENT_HOMEASSISTANT_STOP -import homeassistant.helpers.config_validation as cv - -from .const import PROTOCOL_311 - -_LOGGER = logging.getLogger(__name__) - -# 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, - ), -) - - -async def async_start(hass, password, server_config): - """Initialize MQTT Server. - - This method is a coroutine. - """ - # pylint: disable=import-outside-toplevel - from hbmqtt.broker import Broker, BrokerException - - passwd = tempfile.NamedTemporaryFile() - - gen_server_config, client_config = generate_config(hass, passwd, password) - - try: - if server_config is None: - server_config = gen_server_config - - broker = Broker(server_config, hass.loop) - await broker.start() - except BrokerException: - _LOGGER.exception("Error initializing MQTT server") - return False, None - finally: - passwd.close() - - async def async_shutdown_mqtt_server(event): - """Shut down the MQTT server.""" - await broker.shutdown() - - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_shutdown_mqtt_server) - - return True, client_config - - -def generate_config(hass, passwd, password): - """Generate a configuration based on current Home Assistant instance.""" - # pylint: disable=import-outside-toplevel - from passlib.apps import custom_app_context - - 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": password is None}, - "plugins": ["auth_anonymous"], - "topic-check": {"enabled": True, "plugins": ["topic_taboo"]}, - } - - if password: - username = "homeassistant" - - # Encrypt with what hbmqtt uses to verify - passwd.write( - f"homeassistant:{custom_app_context.encrypt(password)}\n".encode("utf-8") - ) - passwd.flush() - - config["auth"]["password-file"] = passwd.name - config["plugins"].append("auth_file") - else: - username = None - - client_config = ("localhost", 1883, username, password, None, PROTOCOL_311) - - return config, client_config diff --git a/requirements_all.txt b/requirements_all.txt index 9e33aadca33..d053a03a145 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -713,9 +713,6 @@ hangups==0.4.9 # homeassistant.components.cloud hass-nabucasa==0.34.7 -# homeassistant.components.mqtt -hbmqtt==0.9.5 - # homeassistant.components.jewish_calendar hdate==0.9.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9231d3846e1..494f27a2961 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -324,9 +324,6 @@ hangups==0.4.9 # homeassistant.components.cloud hass-nabucasa==0.34.7 -# homeassistant.components.mqtt -hbmqtt==0.9.5 - # homeassistant.components.jewish_calendar hdate==0.9.5 diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 247f616f379..97031427142 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -670,32 +670,6 @@ async def test_restore_all_active_subscriptions_on_reconnect( assert mqtt_client_mock.subscribe.mock_calls == expected -@pytest.fixture -def mqtt_server_start_mock(hass): - """Mock embedded server start.""" - client_config = ("localhost", 1883, "user", "pass", None, "3.1.1") - - with patch( - "homeassistant.components.mqtt.server.async_start", - return_value=(True, client_config), - ) as _start: - yield _start - - -@pytest.mark.parametrize("mqtt_config", [{}]) -async def test_setup_embedded_starts_with_no_config( - hass, mqtt_server_start_mock, mqtt_mock -): - """Test setting up embedded server with no config.""" - assert mqtt_server_start_mock.call_count == 1 - - -@pytest.mark.parametrize("mqtt_config", [{"embedded": None}]) -async def test_setup_embedded_with_embedded(hass, mqtt_server_start_mock, mqtt_mock): - """Test setting up embedded server with empty embedded config.""" - assert mqtt_server_start_mock.call_count == 1 - - async def test_setup_logs_error_if_no_connect_broker(hass, caplog): """Test for setup failure if connection to broker is missing.""" entry = MockConfigEntry(domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}) diff --git a/tests/components/mqtt/test_server.py b/tests/components/mqtt/test_server.py deleted file mode 100644 index 95f61e7c82b..00000000000 --- a/tests/components/mqtt/test_server.py +++ /dev/null @@ -1,87 +0,0 @@ -"""The tests for the MQTT component embedded server.""" -from unittest.mock import MagicMock, Mock - -import pytest - -import homeassistant.components.mqtt as mqtt -from homeassistant.const import CONF_PASSWORD -from homeassistant.setup import setup_component - -from tests.async_mock import AsyncMock, patch -from tests.common import get_test_home_assistant, mock_coro - - -@pytest.fixture(autouse=True) -def inject_fixture(hass_storage): - """Inject pytest fixtures.""" - - -class TestMQTT: - """Test the MQTT component.""" - - def setup_method(self, method): - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() - - def teardown_method(self, method): - """Stop everything that was started.""" - self.hass.stop() - - @patch("passlib.apps.custom_app_context", Mock(return_value="")) - @patch("tempfile.NamedTemporaryFile", Mock(return_value=MagicMock())) - @patch("hbmqtt.broker.Broker", Mock(return_value=MagicMock(start=AsyncMock()))) - @patch("hbmqtt.broker.Broker.start", AsyncMock(return_value=None)) - @patch("homeassistant.components.mqtt.MQTT") - def test_creating_config_with_pass_and_no_http_pass(self, mock_mqtt): - """Test if the MQTT server gets started with password. - - Since 0.77, MQTT server has to set up its own password. - """ - mock_mqtt().async_connect = AsyncMock(return_value=True) - self.hass.bus.listen_once = MagicMock() - password = "mqtt_secret" - - assert setup_component( - self.hass, mqtt.DOMAIN, {mqtt.DOMAIN: {CONF_PASSWORD: password}} - ) - self.hass.block_till_done() - assert mock_mqtt.called - assert mock_mqtt.mock_calls[1][1][2]["username"] == "homeassistant" - assert mock_mqtt.mock_calls[1][1][2]["password"] == password - - @patch("passlib.apps.custom_app_context", Mock(return_value="")) - @patch("tempfile.NamedTemporaryFile", Mock(return_value=MagicMock())) - @patch("hbmqtt.broker.Broker", Mock(return_value=MagicMock(start=AsyncMock()))) - @patch("hbmqtt.broker.Broker.start", AsyncMock(return_value=None)) - @patch("homeassistant.components.mqtt.MQTT") - def test_creating_config_with_pass_and_http_pass(self, mock_mqtt): - """Test if the MQTT server gets started with password. - - Since 0.77, MQTT server has to set up its own password. - """ - mock_mqtt().async_connect = AsyncMock(return_value=True) - self.hass.bus.listen_once = MagicMock() - password = "mqtt_secret" - - self.hass.config.api = MagicMock(api_password="api_password") - assert setup_component( - self.hass, mqtt.DOMAIN, {mqtt.DOMAIN: {CONF_PASSWORD: password}} - ) - self.hass.block_till_done() - assert mock_mqtt.called - assert mock_mqtt.mock_calls[1][1][2]["username"] == "homeassistant" - assert mock_mqtt.mock_calls[1][1][2]["password"] == password - - @patch("tempfile.NamedTemporaryFile", Mock(return_value=MagicMock())) - @patch("hbmqtt.broker.Broker.start", return_value=mock_coro()) - def test_broker_config_fails(self, mock_run): - """Test if the MQTT component fails if server fails.""" - from hbmqtt.broker import BrokerException - - mock_run.side_effect = BrokerException - - self.hass.config.api = MagicMock(api_password=None) - - assert not setup_component( - self.hass, mqtt.DOMAIN, {mqtt.DOMAIN: {mqtt.CONF_EMBEDDED: {}}} - )