From fc70614b63da5abacf855dbed2eed69adacde7d6 Mon Sep 17 00:00:00 2001 From: Bryan <185078974@qq.com> Date: Tue, 28 Jul 2026 18:59:53 +0800 Subject: [PATCH] Discover aidot wifi lights over dhcp (#177437) Co-authored-by: s1eedz Co-authored-by: Josef Zweck --- homeassistant/components/aidot/manifest.json | 5 ++ .../components/aidot/quality_scale.yaml | 2 +- homeassistant/components/aidot/strings.json | 3 +- homeassistant/generated/dhcp.py | 4 ++ tests/components/aidot/test_config_flow.py | 59 ++++++++++++++++++- 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/aidot/manifest.json b/homeassistant/components/aidot/manifest.json index d3eb75f855d0..84e765b8720c 100644 --- a/homeassistant/components/aidot/manifest.json +++ b/homeassistant/components/aidot/manifest.json @@ -3,6 +3,11 @@ "name": "AiDot", "codeowners": ["@s1eedz", "@HongBryan"], "config_flow": true, + "dhcp": [ + { + "hostname": "aidot" + } + ], "documentation": "https://www.home-assistant.io/integrations/aidot", "integration_type": "hub", "iot_class": "local_polling", diff --git a/homeassistant/components/aidot/quality_scale.yaml b/homeassistant/components/aidot/quality_scale.yaml index 28995a3411c2..be8004c76eb0 100644 --- a/homeassistant/components/aidot/quality_scale.yaml +++ b/homeassistant/components/aidot/quality_scale.yaml @@ -49,7 +49,7 @@ rules: devices: done diagnostics: todo discovery-update-info: todo - discovery: todo + discovery: done docs-data-update: todo docs-examples: todo docs-known-limitations: todo diff --git a/homeassistant/components/aidot/strings.json b/homeassistant/components/aidot/strings.json index 1d27987383a7..942762478453 100644 --- a/homeassistant/components/aidot/strings.json +++ b/homeassistant/components/aidot/strings.json @@ -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%]", diff --git a/homeassistant/generated/dhcp.py b/homeassistant/generated/dhcp.py index 2c7dba6202db..279f49ddda7e 100644 --- a/homeassistant/generated/dhcp.py +++ b/homeassistant/generated/dhcp.py @@ -11,6 +11,10 @@ DHCP: Final[list[dict[str, str | bool]]] = [ "hostname": "neo-*", "macaddress": "FC0FE7*", }, + { + "domain": "aidot", + "hostname": "aidot", + }, { "domain": "airobot", "hostname": "airobot-thermostat-*", diff --git a/tests/components/aidot/test_config_flow.py b/tests/components/aidot/test_config_flow.py index c1712bc8227f..84a794d9563b 100644 --- a/tests/components/aidot/test_config_flow.py +++ b/tests/components/aidot/test_config_flow.py @@ -7,15 +7,22 @@ from aiohttp import ClientError import pytest from homeassistant.components.aidot.const import DOMAIN -from homeassistant.config_entries import SOURCE_USER +from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER from homeassistant.const import CONF_COUNTRY_CODE, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType +from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo from .const import TEST_COUNTRY, TEST_EMAIL, TEST_LOGIN_RESP, TEST_PASSWORD from tests.common import MockConfigEntry +DHCP_SERVICE_INFO = DhcpServiceInfo( + hostname="aidot", + ip="192.168.1.100", + macaddress="001122334455", +) + async def test_config_flow_cloud_login_success( hass: HomeAssistant, mock_setup_entry: AsyncMock @@ -44,6 +51,56 @@ async def test_config_flow_cloud_login_success( assert result["result"].unique_id == TEST_LOGIN_RESP["id"] +async def test_dhcp_discovery(hass: HomeAssistant) -> None: + """Test DHCP discovery shows the user form.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_DHCP}, + data=DHCP_SERVICE_INFO, + ) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "user" + assert result["errors"] == {} + + +async def test_dhcp_discovery_aborts_if_already_configured( + hass: HomeAssistant, mock_config_entry: MockConfigEntry +) -> None: + """Test DHCP discovery aborts when the integration is configured.""" + mock_config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_DHCP}, + data=DHCP_SERVICE_INFO, + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + + +async def test_dhcp_discovery_aborts_if_already_in_progress( + hass: HomeAssistant, +) -> None: + """Test a duplicate DHCP discovery flow aborts.""" + first_result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_DHCP}, + data=DHCP_SERVICE_INFO, + ) + assert first_result["type"] is FlowResultType.FORM + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_DHCP}, + data=DHCP_SERVICE_INFO, + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_in_progress" + + @pytest.mark.parametrize( ("exception", "error"), [