mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
deCONZ - Always allow manual input of gateway (#33951)
* Always allow manual input of gateway
This commit is contained in:
parent
3776a06281
commit
4484afc0d6
@ -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}?",
|
"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"
|
"title": "deCONZ Zigbee gateway via Hass.io add-on"
|
||||||
},
|
},
|
||||||
"init": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"host": "Host",
|
"host": "Select discovered deCONZ gateway"
|
||||||
"port": "Port"
|
|
||||||
},
|
},
|
||||||
"title": "Define deCONZ gateway"
|
"title": "Select deCONZ gateway"
|
||||||
},
|
},
|
||||||
"link": {
|
"link": {
|
||||||
"description": "Unlock your deCONZ gateway to register with Home Assistant.\n\n1. Go to deCONZ Settings -> Gateway -> Advanced\n2. Press \"Authenticate app\" button",
|
"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"
|
"title": "Link with deCONZ"
|
||||||
|
},
|
||||||
|
"manual_input": {
|
||||||
|
"data": {
|
||||||
|
"host": "Host",
|
||||||
|
"port": "Port"
|
||||||
|
},
|
||||||
|
"title": "Configure deCONZ gateway"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -32,6 +32,7 @@ from .const import (
|
|||||||
|
|
||||||
DECONZ_MANUFACTURERURL = "http://www.dresden-elektronik.de"
|
DECONZ_MANUFACTURERURL = "http://www.dresden-elektronik.de"
|
||||||
CONF_SERIAL = "serial"
|
CONF_SERIAL = "serial"
|
||||||
|
CONF_MANUAL_INPUT = "Manually define gateway"
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -62,18 +63,17 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
self.bridges = []
|
self.bridges = []
|
||||||
self.deconz_config = {}
|
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):
|
async def async_step_user(self, user_input=None):
|
||||||
"""Handle a deCONZ config flow start.
|
"""Handle a deCONZ config flow start.
|
||||||
|
|
||||||
If only one bridge is found go to link step.
|
Let user choose between discovered bridges and manual configuration.
|
||||||
If more than one bridge is found let user choose bridge to link.
|
|
||||||
If no bridge is found allow user to manually input configuration.
|
If no bridge is found allow user to manually input configuration.
|
||||||
"""
|
"""
|
||||||
if user_input is not None:
|
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:
|
for bridge in self.bridges:
|
||||||
if bridge[CONF_HOST] == user_input[CONF_HOST]:
|
if bridge[CONF_HOST] == user_input[CONF_HOST]:
|
||||||
self.bridge_id = bridge[CONF_BRIDGE_ID]
|
self.bridge_id = bridge[CONF_BRIDGE_ID]
|
||||||
@ -83,9 +83,6 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
}
|
}
|
||||||
return await self.async_step_link()
|
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)
|
session = aiohttp_client.async_get_clientsession(self.hass)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -97,22 +94,29 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
LOGGER.debug("Discovered deCONZ gateways %s", pformat(self.bridges))
|
LOGGER.debug("Discovered deCONZ gateways %s", pformat(self.bridges))
|
||||||
|
|
||||||
if len(self.bridges) == 1:
|
if self.bridges:
|
||||||
return await self.async_step_user(self.bridges[0])
|
|
||||||
|
|
||||||
if len(self.bridges) > 1:
|
|
||||||
hosts = []
|
hosts = []
|
||||||
|
|
||||||
for bridge in self.bridges:
|
for bridge in self.bridges:
|
||||||
hosts.append(bridge[CONF_HOST])
|
hosts.append(bridge[CONF_HOST])
|
||||||
|
|
||||||
|
hosts.append(CONF_MANUAL_INPUT)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="init",
|
step_id="user",
|
||||||
data_schema=vol.Schema({vol.Required(CONF_HOST): vol.In(hosts)}),
|
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(
|
return self.async_show_form(
|
||||||
step_id="init",
|
step_id="manual_input",
|
||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_HOST): str,
|
vol.Required(CONF_HOST): str,
|
||||||
|
@ -2,9 +2,18 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"flow_title": "deCONZ Zigbee gateway ({host})",
|
"flow_title": "deCONZ Zigbee gateway ({host})",
|
||||||
"step": {
|
"step": {
|
||||||
"init": {
|
"user": {
|
||||||
"title": "Define deCONZ gateway",
|
"title": "Select deCONZ gateway",
|
||||||
"data": { "host": "Host", "port": "Port" }
|
"data": {
|
||||||
|
"host": "Select discovered deCONZ gateway"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"manual_input": {
|
||||||
|
"title": "Configure deCONZ gateway",
|
||||||
|
"data": {
|
||||||
|
"host": "Host",
|
||||||
|
"port": "Port"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"link": {
|
"link": {
|
||||||
"title": "Link with deCONZ",
|
"title": "Link with deCONZ",
|
||||||
|
@ -7,6 +7,7 @@ from homeassistant import data_entry_flow
|
|||||||
from homeassistant.components import ssdp
|
from homeassistant.components import ssdp
|
||||||
from homeassistant.components.deconz import config_flow
|
from homeassistant.components.deconz import config_flow
|
||||||
from homeassistant.components.deconz.config_flow import (
|
from homeassistant.components.deconz.config_flow import (
|
||||||
|
CONF_MANUAL_INPUT,
|
||||||
CONF_SERIAL,
|
CONF_SERIAL,
|
||||||
DECONZ_MANUFACTURERURL,
|
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
|
from .test_gateway import API_KEY, BRIDGEID, setup_deconz_integration
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_1_discovered_bridge(hass, aioclient_mock):
|
async def test_flow_discovered_bridges(hass, aioclient_mock):
|
||||||
"""Test that config flow for one discovered bridge works."""
|
"""Test that config flow works for discovered bridges."""
|
||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
pydeconz.utils.URL_DISCOVER,
|
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"},
|
headers={"content-type": "application/json"},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +37,13 @@ async def test_flow_1_discovered_bridge(hass, aioclient_mock):
|
|||||||
DOMAIN, context={"source": "user"}
|
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["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "link"
|
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):
|
async def test_flow_manual_configuration_decision(hass, aioclient_mock):
|
||||||
"""Test that config flow works for multiple discovered bridges."""
|
"""Test that config flow for one discovered bridge works."""
|
||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
pydeconz.utils.URL_DISCOVER,
|
pydeconz.utils.URL_DISCOVER,
|
||||||
json=[
|
json=[{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80}],
|
||||||
{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80},
|
|
||||||
{"id": "1234E567890A", "internalipaddress": "5.6.7.8", "internalport": 80},
|
|
||||||
],
|
|
||||||
headers={"content-type": "application/json"},
|
headers={"content-type": "application/json"},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,11 +78,15 @@ async def test_flow_2_discovered_bridges(hass, aioclient_mock):
|
|||||||
DOMAIN, context={"source": "user"}
|
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["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 = 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
|
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"},
|
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 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
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["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 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
|
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["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
|
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["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
|
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["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 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={CONF_HOST: "2.3.4.5", CONF_PORT: 80},
|
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["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 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
|
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["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 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={CONF_HOST: "1.2.3.4", CONF_PORT: 80},
|
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"}
|
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["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "link"
|
assert result["step_id"] == "link"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user