Update WiZ with IP address validation (#66117)

This commit is contained in:
Stephan Traub 2022-02-09 19:53:32 +01:00 committed by GitHub
parent 83a10cca53
commit a6013dc0de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 35 deletions

View File

@ -13,6 +13,7 @@ from homeassistant import config_entries
from homeassistant.components import dhcp from homeassistant.components import dhcp
from homeassistant.const import CONF_HOST from homeassistant.const import CONF_HOST
from homeassistant.data_entry_flow import FlowResult from homeassistant.data_entry_flow import FlowResult
from homeassistant.util.network import is_ip_address
from .const import DEFAULT_NAME, DISCOVER_SCAN_TIMEOUT, DOMAIN, WIZ_EXCEPTIONS from .const import DEFAULT_NAME, DISCOVER_SCAN_TIMEOUT, DOMAIN, WIZ_EXCEPTIONS
from .discovery import async_discover_devices from .discovery import async_discover_devices
@ -139,29 +140,32 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if user_input is not None: if user_input is not None:
if not (host := user_input[CONF_HOST]): if not (host := user_input[CONF_HOST]):
return await self.async_step_pick_device() return await self.async_step_pick_device()
bulb = wizlight(host) if not is_ip_address(user_input[CONF_HOST]):
try: errors["base"] = "no_ip"
mac = await bulb.getMac()
bulbtype = await bulb.get_bulbtype()
except WizLightTimeOutError:
errors["base"] = "bulb_time_out"
except ConnectionRefusedError:
errors["base"] = "cannot_connect"
except WizLightConnectionError:
errors["base"] = "no_wiz_light"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else: else:
await self.async_set_unique_id(mac, raise_on_progress=False) bulb = wizlight(host)
self._abort_if_unique_id_configured( try:
updates={CONF_HOST: user_input[CONF_HOST]} bulbtype = await bulb.get_bulbtype()
) mac = await bulb.getMac()
name = name_from_bulb_type_and_mac(bulbtype, mac) except WizLightTimeOutError:
return self.async_create_entry( errors["base"] = "bulb_time_out"
title=name, except ConnectionRefusedError:
data=user_input, errors["base"] = "cannot_connect"
) except WizLightConnectionError:
errors["base"] = "no_wiz_light"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(mac, raise_on_progress=False)
self._abort_if_unique_id_configured(
updates={CONF_HOST: user_input[CONF_HOST]}
)
name = name_from_bulb_type_and_mac(bulbtype, mac)
return self.async_create_entry(
title=name,
data=user_input,
)
return self.async_show_form( return self.async_show_form(
step_id="user", step_id="user",

View File

@ -4,9 +4,9 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"host": "[%key:common::config_flow::data::host%]" "host": "[%key:common::config_flow::data::ip%]"
}, },
"description": "If you leave the host empty, discovery will be used to find devices." "description": "If you leave the IP Address empty, discovery will be used to find devices."
}, },
"discovery_confirm": { "discovery_confirm": {
"description": "Do you want to setup {name} ({host})?" "description": "Do you want to setup {name} ({host})?"
@ -20,8 +20,9 @@
"error": { "error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"unknown": "[%key:common::config_flow::error::unknown%]", "unknown": "[%key:common::config_flow::error::unknown%]",
"bulb_time_out": "Can not connect to the bulb. Maybe the bulb is offline or a wrong IP/host was entered. Please turn on the light and try again!", "bulb_time_out": "Can not connect to the bulb. Maybe the bulb is offline or a wrong IP was entered. Please turn on the light and try again!",
"no_wiz_light": "The bulb can not be connected via WiZ Platform integration." "no_wiz_light": "The bulb can not be connected via WiZ Platform integration.",
"no_ip": "Not a valid IP address."
}, },
"abort": { "abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]" "already_configured": "[%key:common::config_flow::abort::already_configured_device%]"

View File

@ -1,20 +1,17 @@
{ {
"config": { "config": {
"abort": { "abort": {
"already_configured": "Device is already configured", "already_configured": "Device is already configured"
"no_devices_found": "No devices found on the network"
}, },
"error": { "error": {
"bulb_time_out": "Can not connect to the bulb. Maybe the bulb is offline or a wrong IP/host was entered. Please turn on the light and try again!", "bulb_time_out": "Can not connect to the bulb. Maybe the bulb is offline or a wrong IP was entered. Please turn on the light and try again!",
"cannot_connect": "Failed to connect", "cannot_connect": "Failed to connect",
"no_ip": "Not a valid IP address.",
"no_wiz_light": "The bulb can not be connected via WiZ Platform integration.", "no_wiz_light": "The bulb can not be connected via WiZ Platform integration.",
"unknown": "Unexpected error" "unknown": "Unexpected error"
}, },
"flow_title": "{name} ({host})", "flow_title": "{name} ({host})",
"step": { "step": {
"confirm": {
"description": "Do you want to start set up?"
},
"discovery_confirm": { "discovery_confirm": {
"description": "Do you want to setup {name} ({host})?" "description": "Do you want to setup {name} ({host})?"
}, },
@ -25,10 +22,9 @@
}, },
"user": { "user": {
"data": { "data": {
"host": "Host", "host": "IP Address"
"name": "Name"
}, },
"description": "If you leave the host empty, discovery will be used to find devices." "description": "If you leave the IP Address empty, discovery will be used to find devices."
} }
} }
} }

View File

@ -114,6 +114,44 @@ async def test_form(hass):
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_user_flow_enters_dns_name(hass):
"""Test we reject dns names and want ips."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "ip.only"},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_FORM
assert result2["errors"] == {"base": "no_ip"}
with _patch_wizlight(), patch(
"homeassistant.components.wiz.async_setup_entry",
return_value=True,
) as mock_setup_entry, patch(
"homeassistant.components.wiz.async_setup", return_value=True
) as mock_setup:
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"],
TEST_CONNECTION,
)
await hass.async_block_till_done()
assert result3["type"] == "create_entry"
assert result3["title"] == "WiZ Dimmable White ABCABC"
assert result3["data"] == {
CONF_HOST: "1.1.1.1",
}
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize( @pytest.mark.parametrize(
"side_effect, error_base", "side_effect, error_base",
[ [