Insteon HUB DHCP discovery (#70685)

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
pull/70699/head
Tom Harris 2022-04-25 12:01:56 -04:00 committed by GitHub
parent 28ba572d9d
commit 6363c67398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 6 deletions

View File

@ -7,7 +7,7 @@ from pyinsteon import async_connect
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import usb
from homeassistant.components import dhcp, usb
from homeassistant.const import (
CONF_ADDRESS,
CONF_DEVICE,
@ -19,6 +19,7 @@ from homeassistant.const import (
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import (
@ -114,6 +115,7 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
_device_path: str | None = None
_device_name: str | None = None
discovered_conf: dict[str, str] = {}
@staticmethod
@callback
@ -170,7 +172,7 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return self.async_create_entry(title="", data=user_input)
user_input.pop(CONF_HUB_VERSION)
errors["base"] = "cannot_connect"
schema_defaults = user_input if user_input is not None else {}
schema_defaults = user_input if user_input is not None else self.discovered_conf
data_schema = build_hub_schema(hub_version=hub_version, **schema_defaults)
step_id = STEP_HUB_V2 if hub_version == 2 else STEP_HUB_V1
return self.async_show_form(
@ -203,12 +205,14 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
discovery_info.pid,
)
self._set_confirm_only()
self.context["title_placeholders"] = {CONF_NAME: self._device_name}
self.context["title_placeholders"] = {
CONF_NAME: f"Insteon PLM {self._device_name}"
}
await self.async_set_unique_id(config_entries.DEFAULT_DISCOVERY_UNIQUE_ID)
return await self.async_step_confirm_usb()
async def async_step_confirm_usb(self, user_input=None):
"""Confirm a discovery."""
"""Confirm a USB discovery."""
if user_input is not None:
return await self.async_step_plm({CONF_DEVICE: self._device_path})
@ -217,6 +221,15 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
description_placeholders={CONF_NAME: self._device_name},
)
async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowResult:
"""Handle a DHCP discovery."""
self.discovered_conf = {CONF_HOST: discovery_info.ip}
self.context["title_placeholders"] = {
CONF_NAME: f"Insteon Hub {discovery_info.ip}"
}
await self.async_set_unique_id(format_mac(discovery_info.macaddress))
return await self.async_step_user()
class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle an Insteon options flow."""

View File

@ -4,6 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/insteon",
"requirements": ["pyinsteon==1.0.13"],
"codeowners": ["@teharris1"],
"dhcp": [{ "macaddress": "000EF3*" }, { "registered_devices": true }],
"config_flow": true,
"iot_class": "local_push",
"loggers": ["pyinsteon", "pypubsub"],

View File

@ -43,7 +43,8 @@
},
"abort": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
"not_insteon_device": "Discovered device not an Insteon device"
}
},
"options": {

View File

@ -49,6 +49,8 @@ DHCP: list[dict[str, str | bool]] = [
{'domain': 'hunterdouglas_powerview',
'hostname': 'hunter*',
'macaddress': '002674*'},
{'domain': 'insteon', 'macaddress': '000EF3*'},
{'domain': 'insteon', 'registered_devices': True},
{'domain': 'intellifire', 'hostname': 'zentrios-*'},
{'domain': 'isy994', 'registered_devices': True},
{'domain': 'isy994', 'hostname': 'isy*', 'macaddress': '0021B9*'},

View File

@ -2,8 +2,10 @@
from unittest.mock import patch
import voluptuous_serialize
from homeassistant import config_entries, data_entry_flow
from homeassistant.components import usb
from homeassistant.components import dhcp, usb
from homeassistant.components.insteon.config_flow import (
HUB1,
HUB2,
@ -37,6 +39,7 @@ from homeassistant.const import (
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from .const import (
MOCK_HOSTNAME,
@ -648,3 +651,48 @@ async def test_discovery_via_usb_already_setup(hass):
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "single_instance_allowed"
async def test_discovery_via_dhcp_hubv1(hass):
"""Test usb flow."""
await _test_dhcp(hass, HUB1)
async def test_discovery_via_dhcp_hubv2(hass):
"""Test usb flow."""
await _test_dhcp(hass, HUB2)
async def _test_dhcp(hass, modem_type):
"""Test the dhcp discovery for a moddem type."""
discovery_info = dhcp.DhcpServiceInfo(
ip="11.22.33.44", hostname="", macaddress="00:0e:f3:aa:bb:cc"
)
result = await hass.config_entries.flow.async_init(
"insteon",
context={"source": config_entries.SOURCE_DHCP},
data=discovery_info,
)
await hass.async_block_till_done()
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
with patch("homeassistant.components.insteon.config_flow.async_connect"), patch(
"homeassistant.components.insteon.async_setup_entry", return_value=True
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={"modem_type": modem_type}
)
await hass.async_block_till_done()
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
schema = voluptuous_serialize.convert(
result2["data_schema"],
custom_serializer=cv.custom_serializer,
)
for field in schema:
if field["name"] == "host":
assert field.get("default") == "11.22.33.44"
break