mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 23:41:48 -05:00
Add DHCP discovery to the Imou integration (#180083)
This commit is contained in:
@@ -3,6 +3,19 @@
|
||||
"name": "Imou",
|
||||
"codeowners": ["@Imou-OpenPlatform"],
|
||||
"config_flow": true,
|
||||
"dhcp": [
|
||||
{ "macaddress": "1C4D89*" },
|
||||
{ "macaddress": "302450*" },
|
||||
{ "macaddress": "38AF29*" },
|
||||
{ "macaddress": "3CE36B*" },
|
||||
{ "macaddress": "3CEF8C*" },
|
||||
{ "macaddress": "906A94*" },
|
||||
{ "macaddress": "A0BD1D*" },
|
||||
{ "macaddress": "A83162*" },
|
||||
{ "macaddress": "AC3DFA*" },
|
||||
{ "macaddress": "B44C3B*" },
|
||||
{ "macaddress": "FCB69D*" }
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/imou",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
|
||||
@@ -48,13 +48,10 @@ rules:
|
||||
diagnostics: todo
|
||||
discovery-update-info:
|
||||
status: exempt
|
||||
comment: Cloud service integration, does not support discovery.
|
||||
comment: Cloud hub; DHCP only surfaces the integration. Device IP is not stored or updated.
|
||||
discovery:
|
||||
status: exempt
|
||||
comment: >-
|
||||
Devices are reached via Imou Open Platform cloud APIs (App ID / secret). No
|
||||
supported local discovery flow today; example cues if investigated later:
|
||||
hostname `IPC-ABCD.imou.local`, MAC `aa:bb:cc:dd:ee:ff`.
|
||||
status: done
|
||||
comment: DHCP matches known Imou / Lechange MAC OUI prefixes. Setup still uses Open Platform App ID and secret.
|
||||
docs-data-update: todo
|
||||
docs-examples: todo
|
||||
docs-known-limitations: todo
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]"
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
|
||||
Generated
+44
@@ -504,6 +504,50 @@ DHCP: Final[list[dict[str, str | bool]]] = [
|
||||
"domain": "iaqualink",
|
||||
"hostname": "iaqualink-*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "1C4D89*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "302450*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "38AF29*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "3CE36B*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "3CEF8C*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "906A94*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "A0BD1D*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "A83162*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "AC3DFA*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "B44C3B*",
|
||||
},
|
||||
{
|
||||
"domain": "imou",
|
||||
"macaddress": "FCB69D*",
|
||||
},
|
||||
{
|
||||
"domain": "incomfort",
|
||||
"hostname": "rfgateway",
|
||||
|
||||
@@ -16,14 +16,21 @@ from homeassistant.components.imou.const import (
|
||||
CONF_APP_SECRET,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
|
||||
from .const import TEST_APP_ID, TEST_APP_SECRET, USER_INPUT
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
DHCP_DISCOVERY = DhcpServiceInfo(
|
||||
ip="127.0.0.1",
|
||||
hostname="imou",
|
||||
macaddress="1c4d895f7a29",
|
||||
)
|
||||
|
||||
|
||||
async def test_user_flow_success(
|
||||
hass: HomeAssistant,
|
||||
@@ -150,3 +157,108 @@ async def test_user_flow_success_per_region(
|
||||
assert result["title"] == "Imou"
|
||||
assert result["data"] == user_input
|
||||
assert result["result"].unique_id == user_input[CONF_APP_ID]
|
||||
|
||||
|
||||
async def test_dhcp_discovery_success(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_imou_openapi_client: AsyncMock,
|
||||
) -> None:
|
||||
"""DHCP discovery opens the existing user login form and creates an entry."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DHCP},
|
||||
data=DHCP_DISCOVERY,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=USER_INPUT,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Imou"
|
||||
assert result["data"] == USER_INPUT
|
||||
assert result["result"].unique_id == USER_INPUT[CONF_APP_ID]
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_dhcp_discovery_aborts_when_already_configured(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Any existing Imou entry suppresses further DHCP discovery."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DHCP},
|
||||
data=DHCP_DISCOVERY,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_dhcp_discovery_aborts_when_user_flow_in_progress(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""DHCP discovery does not sit beside an unfinished manual setup."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DHCP},
|
||||
data=DHCP_DISCOVERY,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_in_progress"
|
||||
|
||||
|
||||
async def test_dhcp_discovery_invalid_auth(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_imou_openapi_client: AsyncMock,
|
||||
) -> None:
|
||||
"""Bad credentials stay on the user step, then recover to CREATE_ENTRY."""
|
||||
mock_imou_openapi_client.async_get_token.side_effect = (
|
||||
InvalidAppIdOrSecretException("fail")
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DHCP},
|
||||
data=DHCP_DISCOVERY,
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=USER_INPUT,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"]["base"] == "invalid_auth"
|
||||
|
||||
mock_imou_openapi_client.async_get_token.reset_mock(side_effect=True)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=USER_INPUT,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Imou"
|
||||
assert result["data"] == USER_INPUT
|
||||
assert result["result"].unique_id == USER_INPUT[CONF_APP_ID]
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
Reference in New Issue
Block a user