mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add ozw add-on discovery and mqtt client (#43838)
This commit is contained in:
parent
8efa9c5097
commit
9043b7b214
@ -2,6 +2,7 @@
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -23,6 +24,7 @@ from homeassistant.util.dt import utcnow
|
||||
|
||||
from .addon_panel import async_setup_addon_panel
|
||||
from .auth import async_setup_auth_view
|
||||
from .const import ATTR_DISCOVERY
|
||||
from .discovery import async_setup_discovery_view
|
||||
from .handler import HassIO, HassioAPIError, api_data
|
||||
from .http import HassIOView
|
||||
@ -200,6 +202,17 @@ async def async_set_addon_options(
|
||||
return await hassio.send_command(command, payload=options)
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_get_addon_discovery_info(
|
||||
hass: HomeAssistantType, slug: str
|
||||
) -> Optional[dict]:
|
||||
"""Return discovery data for an add-on."""
|
||||
hassio = hass.data[DOMAIN]
|
||||
data = await hassio.retrieve_discovery_messages()
|
||||
discovered_addons = data[ATTR_DISCOVERY]
|
||||
return next((addon for addon in discovered_addons if addon["addon"] == slug), None)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_info(hass):
|
||||
|
@ -17,22 +17,25 @@ from openzwavemqtt.const import (
|
||||
)
|
||||
from openzwavemqtt.models.node import OZWNode
|
||||
from openzwavemqtt.models.value import OZWValue
|
||||
from openzwavemqtt.util.mqtt_client import MQTTClient
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.hassio.handler import HassioAPIError
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from . import const
|
||||
from .const import (
|
||||
CONF_INTEGRATION_CREATED_ADDON,
|
||||
CONF_USE_ADDON,
|
||||
DATA_UNSUBSCRIBE,
|
||||
DOMAIN,
|
||||
MANAGER,
|
||||
OPTIONS,
|
||||
PLATFORMS,
|
||||
TOPIC_OPENZWAVE,
|
||||
)
|
||||
@ -50,13 +53,11 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
||||
DATA_DEVICES = "zwave-mqtt-devices"
|
||||
DATA_STOP_MQTT_CLIENT = "ozw_stop_mqtt_client"
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Initialize basic config of ozw component."""
|
||||
if "mqtt" not in hass.config.components:
|
||||
_LOGGER.error("MQTT integration is not set up")
|
||||
return False
|
||||
hass.data[DOMAIN] = {}
|
||||
return True
|
||||
|
||||
@ -69,16 +70,46 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
data_nodes = {}
|
||||
data_values = {}
|
||||
removed_nodes = []
|
||||
manager_options = {"topic_prefix": f"{TOPIC_OPENZWAVE}/"}
|
||||
|
||||
@callback
|
||||
def send_message(topic, payload):
|
||||
mqtt.async_publish(hass, topic, json.dumps(payload))
|
||||
if entry.unique_id is None:
|
||||
hass.config_entries.async_update_entry(entry, unique_id=DOMAIN)
|
||||
|
||||
options = OZWOptions(send_message=send_message, topic_prefix=f"{TOPIC_OPENZWAVE}/")
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
# Do not use MQTT integration. Use own MQTT client.
|
||||
# Retrieve discovery info from the OpenZWave add-on.
|
||||
discovery_info = await hass.components.hassio.async_get_addon_discovery_info(
|
||||
"core_zwave"
|
||||
)
|
||||
|
||||
if not discovery_info:
|
||||
_LOGGER.error("Failed to get add-on discovery info")
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
discovery_info_config = discovery_info["config"]
|
||||
|
||||
host = discovery_info_config["host"]
|
||||
port = discovery_info_config["port"]
|
||||
username = discovery_info_config["username"]
|
||||
password = discovery_info_config["password"]
|
||||
mqtt_client = MQTTClient(host, port, username=username, password=password)
|
||||
manager_options["send_message"] = mqtt_client.send_message
|
||||
|
||||
else:
|
||||
if "mqtt" not in hass.config.components:
|
||||
_LOGGER.error("MQTT integration is not set up")
|
||||
return False
|
||||
|
||||
@callback
|
||||
def send_message(topic, payload):
|
||||
mqtt.async_publish(hass, topic, json.dumps(payload))
|
||||
|
||||
manager_options["send_message"] = send_message
|
||||
|
||||
options = OZWOptions(**manager_options)
|
||||
manager = OZWManager(options)
|
||||
|
||||
hass.data[DOMAIN][MANAGER] = manager
|
||||
hass.data[DOMAIN][OPTIONS] = options
|
||||
|
||||
@callback
|
||||
def async_node_added(node):
|
||||
@ -234,11 +265,29 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
for component in PLATFORMS
|
||||
]
|
||||
)
|
||||
ozw_data[DATA_UNSUBSCRIBE].append(
|
||||
await mqtt.async_subscribe(
|
||||
hass, f"{TOPIC_OPENZWAVE}/#", async_receive_message
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
mqtt_client_task = asyncio.create_task(mqtt_client.start_client(manager))
|
||||
|
||||
async def async_stop_mqtt_client(event=None):
|
||||
"""Stop the mqtt client.
|
||||
|
||||
Do not unsubscribe the manager topic.
|
||||
"""
|
||||
mqtt_client_task.cancel()
|
||||
try:
|
||||
await mqtt_client_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt_client)
|
||||
ozw_data[DATA_STOP_MQTT_CLIENT] = async_stop_mqtt_client
|
||||
|
||||
else:
|
||||
ozw_data[DATA_UNSUBSCRIBE].append(
|
||||
await mqtt.async_subscribe(
|
||||
hass, f"{manager.options.topic_prefix}#", async_receive_message
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
hass.async_create_task(start_platforms())
|
||||
|
||||
@ -262,6 +311,13 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
# unsubscribe all listeners
|
||||
for unsubscribe_listener in hass.data[DOMAIN][entry.entry_id][DATA_UNSUBSCRIBE]:
|
||||
unsubscribe_listener()
|
||||
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
async_stop_mqtt_client = hass.data[DOMAIN][entry.entry_id][
|
||||
DATA_STOP_MQTT_CLIENT
|
||||
]
|
||||
await async_stop_mqtt_client()
|
||||
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return True
|
||||
|
@ -7,7 +7,7 @@ from homeassistant import config_entries
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import AbortFlow
|
||||
|
||||
from .const import CONF_INTEGRATION_CREATED_ADDON
|
||||
from .const import CONF_INTEGRATION_CREATED_ADDON, CONF_USE_ADDON
|
||||
from .const import DOMAIN # pylint:disable=unused-import
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -16,7 +16,6 @@ CONF_ADDON_DEVICE = "device"
|
||||
CONF_ADDON_NETWORK_KEY = "network_key"
|
||||
CONF_NETWORK_KEY = "network_key"
|
||||
CONF_USB_PATH = "usb_path"
|
||||
CONF_USE_ADDON = "use_addon"
|
||||
TITLE = "OpenZWave"
|
||||
|
||||
ON_SUPERVISOR_SCHEMA = vol.Schema({vol.Optional(CONF_USE_ADDON, default=False): bool})
|
||||
@ -43,17 +42,36 @@ class DomainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
# Currently all flow results need the MQTT integration.
|
||||
# This will change when we have the direct MQTT client connection.
|
||||
# When that is implemented, move this check to _async_use_mqtt_integration.
|
||||
if "mqtt" not in self.hass.config.components:
|
||||
return self.async_abort(reason="mqtt_required")
|
||||
# Set a unique_id to make sure discovery flow is aborted on progress.
|
||||
await self.async_set_unique_id(DOMAIN, raise_on_progress=False)
|
||||
|
||||
if not self.hass.components.hassio.is_hassio():
|
||||
return self._async_use_mqtt_integration()
|
||||
|
||||
return await self.async_step_on_supervisor()
|
||||
|
||||
async def async_step_hassio(self, discovery_info):
|
||||
"""Receive configuration from add-on discovery info.
|
||||
|
||||
This flow is triggered by the OpenZWave add-on.
|
||||
"""
|
||||
await self.async_set_unique_id(DOMAIN)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
addon_config = await self._async_get_addon_config()
|
||||
self.usb_path = addon_config[CONF_ADDON_DEVICE]
|
||||
self.network_key = addon_config.get(CONF_ADDON_NETWORK_KEY, "")
|
||||
|
||||
return await self.async_step_hassio_confirm()
|
||||
|
||||
async def async_step_hassio_confirm(self, user_input=None):
|
||||
"""Confirm the add-on discovery."""
|
||||
if user_input is not None:
|
||||
self.use_addon = True
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
return self.async_show_form(step_id="hassio_confirm")
|
||||
|
||||
def _async_create_entry_from_vars(self):
|
||||
"""Return a config entry for the flow."""
|
||||
return self.async_create_entry(
|
||||
@ -73,6 +91,8 @@ class DomainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
This is the entry point for the logic that is needed
|
||||
when this integration will depend on the MQTT integration.
|
||||
"""
|
||||
if "mqtt" not in self.hass.config.components:
|
||||
return self.async_abort(reason="mqtt_required")
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
async def async_step_on_supervisor(self, user_input=None):
|
||||
|
@ -12,6 +12,7 @@ DOMAIN = "ozw"
|
||||
DATA_UNSUBSCRIBE = "unsubscribe"
|
||||
|
||||
CONF_INTEGRATION_CREATED_ADDON = "integration_created_addon"
|
||||
CONF_USE_ADDON = "use_addon"
|
||||
|
||||
PLATFORMS = [
|
||||
BINARY_SENSOR_DOMAIN,
|
||||
@ -24,7 +25,6 @@ PLATFORMS = [
|
||||
SWITCH_DOMAIN,
|
||||
]
|
||||
MANAGER = "manager"
|
||||
OPTIONS = "options"
|
||||
|
||||
# MQTT Topics
|
||||
TOPIC_OPENZWAVE = "OpenZWave"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/ozw",
|
||||
"requirements": [
|
||||
"python-openzwave-mqtt==1.3.2"
|
||||
"python-openzwave-mqtt[mqtt-client]==1.4.0"
|
||||
],
|
||||
"after_dependencies": [
|
||||
"mqtt"
|
||||
@ -14,4 +14,4 @@
|
||||
"@marcelveldt",
|
||||
"@MartinHjelmare"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,25 @@
|
||||
"on_supervisor": {
|
||||
"title": "Select connection method",
|
||||
"description": "Do you want to use the OpenZWave Supervisor add-on?",
|
||||
"data": {"use_addon": "Use the OpenZWave Supervisor add-on"}
|
||||
"data": { "use_addon": "Use the OpenZWave Supervisor add-on" }
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The OpenZWave add-on installation has started"
|
||||
},
|
||||
"start_addon": {
|
||||
"title": "Enter the OpenZWave add-on configuration",
|
||||
"data": {"usb_path": "[%key:common::config_flow::data::usb_path%]", "network_key": "Network Key"}
|
||||
"data": {
|
||||
"usb_path": "[%key:common::config_flow::data::usb_path%]",
|
||||
"network_key": "Network Key"
|
||||
}
|
||||
},
|
||||
"hassio_confirm": {
|
||||
"title": "Set up OpenZWave integration with the OpenZWave add-on"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"addon_info_failed": "Failed to get OpenZWave add-on info.",
|
||||
"addon_install_failed": "Failed to install the OpenZWave add-on.",
|
||||
"addon_set_config_failed": "Failed to set OpenZWave configuration.",
|
||||
|
@ -4,6 +4,8 @@
|
||||
"addon_info_failed": "Failed to get OpenZWave add-on info.",
|
||||
"addon_install_failed": "Failed to install the OpenZWave add-on.",
|
||||
"addon_set_config_failed": "Failed to set OpenZWave configuration.",
|
||||
"already_configured": "Device is already configured",
|
||||
"already_in_progress": "Configuration flow is already in progress",
|
||||
"mqtt_required": "The MQTT integration is not set up",
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
@ -14,6 +16,9 @@
|
||||
"install_addon": "Please wait while the OpenZWave add-on installation finishes. This can take several minutes."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Set up OpenZWave integration with the OpenZWave add-on"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The OpenZWave add-on installation has started"
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ from homeassistant.components import websocket_api
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .const import ATTR_CONFIG_PARAMETER, ATTR_CONFIG_VALUE, DOMAIN, MANAGER, OPTIONS
|
||||
from .const import ATTR_CONFIG_PARAMETER, ATTR_CONFIG_VALUE, DOMAIN, MANAGER
|
||||
from .lock import ATTR_USERCODE
|
||||
|
||||
TYPE = "type"
|
||||
@ -461,7 +461,7 @@ def websocket_refresh_node_info(hass, connection, msg):
|
||||
"""Tell OpenZWave to re-interview a node."""
|
||||
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
options = hass.data[DOMAIN][OPTIONS]
|
||||
options = manager.options
|
||||
|
||||
@callback
|
||||
def forward_node(node):
|
||||
|
@ -1794,7 +1794,7 @@ python-nest==4.1.0
|
||||
python-nmap==0.6.1
|
||||
|
||||
# homeassistant.components.ozw
|
||||
python-openzwave-mqtt==1.3.2
|
||||
python-openzwave-mqtt[mqtt-client]==1.4.0
|
||||
|
||||
# homeassistant.components.qbittorrent
|
||||
python-qbittorrent==0.4.1
|
||||
|
@ -884,7 +884,7 @@ python-miio==0.5.4
|
||||
python-nest==4.1.0
|
||||
|
||||
# homeassistant.components.ozw
|
||||
python-openzwave-mqtt==1.3.2
|
||||
python-openzwave-mqtt[mqtt-client]==1.4.0
|
||||
|
||||
# homeassistant.components.songpal
|
||||
python-songpal==0.12
|
||||
|
@ -253,3 +253,12 @@ def mock_uninstall_addon():
|
||||
"homeassistant.components.hassio.async_uninstall_addon"
|
||||
) as uninstall_addon:
|
||||
yield uninstall_addon
|
||||
|
||||
|
||||
@pytest.fixture(name="get_addon_discovery_info")
|
||||
def mock_get_addon_discovery_info():
|
||||
"""Mock get add-on discovery info."""
|
||||
with patch(
|
||||
"homeassistant.components.hassio.async_get_addon_discovery_info"
|
||||
) as get_addon_discovery_info:
|
||||
yield get_addon_discovery_info
|
||||
|
@ -9,6 +9,14 @@ from homeassistant.components.ozw.const import DOMAIN
|
||||
from tests.async_mock import patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
ADDON_DISCOVERY_INFO = {
|
||||
"addon": "OpenZWave",
|
||||
"host": "host1",
|
||||
"port": 1234,
|
||||
"username": "name1",
|
||||
"password": "pass1",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor")
|
||||
def mock_supervisor_fixture():
|
||||
@ -44,7 +52,7 @@ def mock_addon_installed(addon_info):
|
||||
def mock_addon_options(addon_info):
|
||||
"""Mock add-on options."""
|
||||
addon_info.return_value["options"] = {}
|
||||
return addon_info
|
||||
return addon_info.return_value["options"]
|
||||
|
||||
|
||||
@pytest.fixture(name="set_addon_options")
|
||||
@ -361,3 +369,122 @@ async def test_install_addon_failure(hass, supervisor, addon_installed, install_
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "addon_install_failed"
|
||||
|
||||
|
||||
async def test_supervisor_discovery(hass, supervisor, addon_running, addon_options):
|
||||
"""Test flow started from Supervisor discovery."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
addon_options["device"] = "/test"
|
||||
addon_options["network_key"] = "abc123"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": "/test",
|
||||
"network_key": "abc123",
|
||||
"use_addon": True,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_clean_discovery_on_user_create(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is cleaned up when a user flow is finished."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
addon_options["device"] = "/test"
|
||||
addon_options["network_key"] = "abc123"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": False}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.config_entries.flow.async_progress()) == 0
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": None,
|
||||
"network_key": None,
|
||||
"use_addon": False,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_abort_discovery_with_user_flow(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is aborted if a user flow is in progress."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_in_progress"
|
||||
assert len(hass.config_entries.flow.async_progress()) == 1
|
||||
|
||||
|
||||
async def test_abort_discovery_with_existing_entry(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is aborted if an entry already exists."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
entry = MockConfigEntry(domain=DOMAIN, data={}, title=TITLE, unique_id=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
|
@ -5,6 +5,7 @@ from homeassistant.components.ozw import DOMAIN, PLATFORMS, const
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@ -23,6 +24,18 @@ async def test_init_entry(hass, generic_data):
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_REMOVE_NODE)
|
||||
|
||||
|
||||
async def test_setup_entry_without_mqtt(hass):
|
||||
"""Test setting up config entry without mqtt integration setup."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert not await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
|
||||
async def test_unload_entry(hass, generic_data, switch_msg, caplog):
|
||||
"""Test unload the config entry."""
|
||||
entry = MockConfigEntry(
|
||||
@ -128,3 +141,75 @@ async def test_remove_entry(hass, stop_addon, uninstall_addon, caplog):
|
||||
assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||
assert "Failed to uninstall the OpenZWave add-on" in caplog.text
|
||||
|
||||
|
||||
async def test_setup_entry_with_addon(hass, get_addon_discovery_info):
|
||||
"""Test set up entry using OpenZWave add-on."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 1
|
||||
|
||||
# Verify integration + platform loaded.
|
||||
assert "ozw" in hass.config.components
|
||||
for platform in PLATFORMS:
|
||||
assert platform in hass.config.components, platform
|
||||
assert f"{platform}.{DOMAIN}" in hass.config.components, f"{platform}.{DOMAIN}"
|
||||
|
||||
# Verify services registered
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_ADD_NODE)
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_REMOVE_NODE)
|
||||
|
||||
|
||||
async def test_setup_entry_without_addon_info(hass, get_addon_discovery_info):
|
||||
"""Test set up entry using OpenZWave add-on but missing discovery info."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
get_addon_discovery_info.return_value = None
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert not await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 0
|
||||
assert entry.state == config_entries.ENTRY_STATE_SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_entry_with_addon(
|
||||
hass, get_addon_discovery_info, generic_data, switch_msg, caplog
|
||||
):
|
||||
"""Test unload the config entry using the OpenZWave add-on."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 1
|
||||
assert entry.state == config_entries.ENTRY_STATE_LOADED
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
|
||||
assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED
|
||||
|
Loading…
x
Reference in New Issue
Block a user