deCONZ - Always allow manual input of gateway (#33951)

* Always allow manual input of gateway
This commit is contained in:
Robert Svensson 2020-04-17 23:51:35 +02:00 committed by GitHub
parent 3776a06281
commit 4484afc0d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 40 deletions

View File

@ -17,16 +17,22 @@
"description": "Do you want to configure Home Assistant to connect to the deCONZ gateway provided by the Hass.io add-on {addon}?",
"title": "deCONZ Zigbee gateway via Hass.io add-on"
},
"init": {
"user": {
"data": {
"host": "Host",
"port": "Port"
"host": "Select discovered deCONZ gateway"
},
"title": "Define deCONZ gateway"
"title": "Select deCONZ gateway"
},
"link": {
"description": "Unlock your deCONZ gateway to register with Home Assistant.\n\n1. Go to deCONZ Settings -> Gateway -> Advanced\n2. Press \"Authenticate app\" button",
"title": "Link with deCONZ"
},
"manual_input": {
"data": {
"host": "Host",
"port": "Port"
},
"title": "Configure deCONZ gateway"
}
}
},

View File

@ -32,6 +32,7 @@ from .const import (
DECONZ_MANUFACTURERURL = "http://www.dresden-elektronik.de"
CONF_SERIAL = "serial"
CONF_MANUAL_INPUT = "Manually define gateway"
@callback
@ -62,18 +63,17 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
self.bridges = []
self.deconz_config = {}
async def async_step_init(self, user_input=None):
"""Needed in order to not require re-translation of strings."""
return await self.async_step_user(user_input)
async def async_step_user(self, user_input=None):
"""Handle a deCONZ config flow start.
If only one bridge is found go to link step.
If more than one bridge is found let user choose bridge to link.
Let user choose between discovered bridges and manual configuration.
If no bridge is found allow user to manually input configuration.
"""
if user_input is not None:
if CONF_MANUAL_INPUT == user_input[CONF_HOST]:
return await self.async_step_manual_input()
for bridge in self.bridges:
if bridge[CONF_HOST] == user_input[CONF_HOST]:
self.bridge_id = bridge[CONF_BRIDGE_ID]
@ -83,9 +83,6 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
}
return await self.async_step_link()
self.deconz_config = user_input
return await self.async_step_link()
session = aiohttp_client.async_get_clientsession(self.hass)
try:
@ -97,22 +94,29 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
LOGGER.debug("Discovered deCONZ gateways %s", pformat(self.bridges))
if len(self.bridges) == 1:
return await self.async_step_user(self.bridges[0])
if len(self.bridges) > 1:
if self.bridges:
hosts = []
for bridge in self.bridges:
hosts.append(bridge[CONF_HOST])
hosts.append(CONF_MANUAL_INPUT)
return self.async_show_form(
step_id="init",
data_schema=vol.Schema({vol.Required(CONF_HOST): vol.In(hosts)}),
step_id="user",
data_schema=vol.Schema({vol.Optional(CONF_HOST): vol.In(hosts)}),
)
return await self.async_step_manual_input()
async def async_step_manual_input(self, user_input=None):
"""Manual configuration."""
if user_input:
self.deconz_config = user_input
return await self.async_step_link()
return self.async_show_form(
step_id="init",
step_id="manual_input",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST): str,

View File

@ -2,9 +2,18 @@
"config": {
"flow_title": "deCONZ Zigbee gateway ({host})",
"step": {
"init": {
"title": "Define deCONZ gateway",
"data": { "host": "Host", "port": "Port" }
"user": {
"title": "Select deCONZ gateway",
"data": {
"host": "Select discovered deCONZ gateway"
}
},
"manual_input": {
"title": "Configure deCONZ gateway",
"data": {
"host": "Host",
"port": "Port"
}
},
"link": {
"title": "Link with deCONZ",

View File

@ -7,6 +7,7 @@ from homeassistant import data_entry_flow
from homeassistant.components import ssdp
from homeassistant.components.deconz import config_flow
from homeassistant.components.deconz.config_flow import (
CONF_MANUAL_INPUT,
CONF_SERIAL,
DECONZ_MANUFACTURERURL,
)
@ -21,11 +22,14 @@ from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
from .test_gateway import API_KEY, BRIDGEID, setup_deconz_integration
async def test_flow_1_discovered_bridge(hass, aioclient_mock):
"""Test that config flow for one discovered bridge works."""
async def test_flow_discovered_bridges(hass, aioclient_mock):
"""Test that config flow works for discovered bridges."""
aioclient_mock.get(
pydeconz.utils.URL_DISCOVER,
json=[{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80}],
json=[
{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80},
{"id": "1234E567890A", "internalipaddress": "5.6.7.8", "internalport": 80},
],
headers={"content-type": "application/json"},
)
@ -33,6 +37,13 @@ async def test_flow_1_discovered_bridge(hass, aioclient_mock):
DOMAIN, context={"source": "user"}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4"}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "link"
@ -55,14 +66,11 @@ async def test_flow_1_discovered_bridge(hass, aioclient_mock):
}
async def test_flow_2_discovered_bridges(hass, aioclient_mock):
"""Test that config flow works for multiple discovered bridges."""
async def test_flow_manual_configuration_decision(hass, aioclient_mock):
"""Test that config flow for one discovered bridge works."""
aioclient_mock.get(
pydeconz.utils.URL_DISCOVER,
json=[
{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80},
{"id": "1234E567890A", "internalipaddress": "5.6.7.8", "internalport": 80},
],
json=[{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80}],
headers={"content-type": "application/json"},
)
@ -70,11 +78,15 @@ async def test_flow_2_discovered_bridges(hass, aioclient_mock):
DOMAIN, context={"source": "user"}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: CONF_MANUAL_INPUT}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4"}
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
@ -86,6 +98,12 @@ async def test_flow_2_discovered_bridges(hass, aioclient_mock):
headers={"content-type": "application/json"},
)
aioclient_mock.get(
f"http://1.2.3.4:80/api/{API_KEY}/config",
json={"bridgeid": BRIDGEID},
headers={"content-type": "application/json"},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={}
)
@ -112,7 +130,7 @@ async def test_flow_manual_configuration(hass, aioclient_mock):
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
@ -155,7 +173,7 @@ async def test_manual_configuration_after_discovery_timeout(hass, aioclient_mock
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
assert not hass.config_entries.flow._progress[result["flow_id"]].bridges
@ -168,7 +186,7 @@ async def test_manual_configuration_after_discovery_ResponseError(hass, aioclien
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
assert not hass.config_entries.flow._progress[result["flow_id"]].bridges
@ -187,7 +205,7 @@ async def test_manual_configuration_update_configuration(hass, aioclient_mock):
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "2.3.4.5", CONF_PORT: 80},
@ -232,7 +250,7 @@ async def test_manual_configuration_dont_update_configuration(hass, aioclient_mo
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
@ -274,7 +292,7 @@ async def test_manual_configuration_timeout_get_bridge(hass, aioclient_mock):
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
assert result["step_id"] == "manual_input"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
@ -313,6 +331,10 @@ async def test_link_get_api_key_ResponseError(hass, aioclient_mock):
DOMAIN, context={"source": "user"}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "1.2.3.4"}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "link"