Add zeroconf discovery to zwave_js (#69382)

This commit is contained in:
Raman Gupta 2022-04-06 12:46:13 -04:00 committed by GitHub
parent c0e9cfedfb
commit bc194cd209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 4 deletions

View File

@ -14,6 +14,7 @@ from zwave_js_server.version import VersionInfo, get_server_version
from homeassistant import config_entries, exceptions from homeassistant import config_entries, exceptions
from homeassistant.components import usb from homeassistant.components import usb
from homeassistant.components.hassio import HassioServiceInfo, is_hassio from homeassistant.components.hassio import HassioServiceInfo, is_hassio
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.const import CONF_NAME, CONF_URL from homeassistant.const import CONF_NAME, CONF_URL
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import ( from homeassistant.data_entry_flow import (
@ -337,6 +338,33 @@ class ConfigFlow(BaseZwaveJSFlow, config_entries.ConfigFlow, domain=DOMAIN):
return await self.async_step_manual() return await self.async_step_manual()
async def async_step_zeroconf(
self, discovery_info: ZeroconfServiceInfo
) -> FlowResult:
"""Handle zeroconf discovery."""
home_id = str(discovery_info.properties["homeId"])
await self.async_set_unique_id(home_id)
self._abort_if_unique_id_configured()
self.ws_address = f"ws://{discovery_info.host}:{discovery_info.port}"
self.context.update({"title_placeholders": {CONF_NAME: home_id}})
return await self.async_step_zeroconf_confirm()
async def async_step_zeroconf_confirm(
self, user_input: dict | None = None
) -> FlowResult:
"""Confirm the setup."""
if user_input is not None:
return await self.async_step_manual({CONF_URL: self.ws_address})
assert self.ws_address
return self.async_show_form(
step_id="zeroconf_confirm",
description_placeholders={
"home_id": self.unique_id,
CONF_URL: self.ws_address[5:],
},
)
async def async_step_usb(self, discovery_info: usb.UsbServiceInfo) -> FlowResult: async def async_step_usb(self, discovery_info: usb.UsbServiceInfo) -> FlowResult:
"""Handle USB Discovery.""" """Handle USB Discovery."""
if not is_hassio(self.hass): if not is_hassio(self.hass):

View File

@ -29,5 +29,6 @@
] ]
} }
], ],
"zeroconf": ["_zwave-js-server._tcp.local."],
"loggers": ["zwave_js_server"] "loggers": ["zwave_js_server"]
} }

View File

@ -36,6 +36,10 @@
}, },
"hassio_confirm": { "hassio_confirm": {
"title": "Set up Z-Wave JS integration with the Z-Wave JS add-on" "title": "Set up Z-Wave JS integration with the Z-Wave JS add-on"
},
"zeroconf_confirm": {
"description": "Do you want to add the Z-Wave JS Server with home ID {home_id} found at {url} to Home Assistant?",
"title": "Discovered Z-Wave JS Server"
} }
}, },
"error": { "error": {

View File

@ -26,7 +26,6 @@
"step": { "step": {
"configure_addon": { "configure_addon": {
"data": { "data": {
"network_key": "Network Key",
"s0_legacy_key": "S0 Key (Legacy)", "s0_legacy_key": "S0 Key (Legacy)",
"s2_access_control_key": "S2 Access Control Key", "s2_access_control_key": "S2 Access Control Key",
"s2_authenticated_key": "S2 Authenticated Key", "s2_authenticated_key": "S2 Authenticated Key",
@ -59,6 +58,10 @@
}, },
"usb_confirm": { "usb_confirm": {
"description": "Do you want to setup {name} with the Z-Wave JS add-on?" "description": "Do you want to setup {name} with the Z-Wave JS add-on?"
},
"zeroconf_confirm": {
"description": "Do you want to add the Z-Wave JS Server with home ID {home_id} found at {url} to Home Assistant?",
"title": "Discovered Z-Wave JS Server"
} }
} }
}, },
@ -113,7 +116,6 @@
"data": { "data": {
"emulate_hardware": "Emulate Hardware", "emulate_hardware": "Emulate Hardware",
"log_level": "Log level", "log_level": "Log level",
"network_key": "Network Key",
"s0_legacy_key": "S0 Key (Legacy)", "s0_legacy_key": "S0 Key (Legacy)",
"s2_access_control_key": "S2 Access Control Key", "s2_access_control_key": "S2 Access Control Key",
"s2_authenticated_key": "S2 Authenticated Key", "s2_authenticated_key": "S2 Authenticated Key",
@ -142,6 +144,5 @@
"title": "The Z-Wave JS add-on is starting." "title": "The Z-Wave JS add-on is starting."
} }
} }
}, }
"title": "Z-Wave JS"
} }

View File

@ -377,6 +377,11 @@ ZEROCONF = {
{ {
"domain": "kodi" "domain": "kodi"
} }
],
"_zwave-js-server._tcp.local.": [
{
"domain": "zwave_js"
}
] ]
} }

View File

@ -10,6 +10,7 @@ from homeassistant import config_entries
from homeassistant.components import usb from homeassistant.components import usb
from homeassistant.components.hassio import HassioServiceInfo from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.hassio.handler import HassioAPIError from homeassistant.components.hassio.handler import HassioAPIError
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.components.zwave_js.config_flow import SERVER_VERSION_TIMEOUT, TITLE from homeassistant.components.zwave_js.config_flow import SERVER_VERSION_TIMEOUT, TITLE
from homeassistant.components.zwave_js.const import DOMAIN from homeassistant.components.zwave_js.const import DOMAIN
@ -2459,3 +2460,48 @@ async def test_import_addon_installed(
} }
assert len(mock_setup.mock_calls) == 1 assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_zeroconf(hass):
"""Test zeroconf discovery."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
host="localhost",
addresses=["127.0.0.1"],
hostname="mock_hostname",
name="mock_name",
port=3000,
type="_zwave-js-server._tcp.local.",
properties={"homeId": "1234"},
),
)
assert result["type"] == "form"
assert result["step_id"] == "zeroconf_confirm"
with patch(
"homeassistant.components.zwave_js.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.zwave_js.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"] == {
"url": "ws://localhost:3000",
"usb_path": None,
"s0_legacy_key": None,
"s2_access_control_key": None,
"s2_authenticated_key": None,
"s2_unauthenticated_key": None,
"use_addon": False,
"integration_created_addon": False,
}
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1