Add DHCP configuration update in HomeWizard (#131547)

This commit is contained in:
Duco Sebel 2024-11-26 19:17:04 +01:00 committed by GitHub
parent a5becfaff0
commit a9cab28474
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 112 additions and 6 deletions

View File

@ -12,6 +12,7 @@ from homewizard_energy.v1.models import Device
from voluptuous import Required, Schema
from homeassistant.components import onboarding, zeroconf
from homeassistant.components.dhcp import DhcpServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_IP_ADDRESS, CONF_PATH
from homeassistant.data_entry_flow import AbortFlow
@ -110,6 +111,32 @@ class HomeWizardConfigFlow(ConfigFlow, domain=DOMAIN):
return await self.async_step_discovery_confirm()
async def async_step_dhcp(
self, discovery_info: DhcpServiceInfo
) -> ConfigFlowResult:
"""Handle dhcp discovery to update existing entries.
This flow is triggered only by DHCP discovery of known devices.
"""
try:
device = await self._async_try_connect(discovery_info.ip)
except RecoverableError as ex:
_LOGGER.error(ex)
return self.async_abort(reason="unknown")
await self.async_set_unique_id(
f"{device.product_type}_{discovery_info.macaddress}"
)
self._abort_if_unique_id_configured(
updates={CONF_IP_ADDRESS: discovery_info.ip}
)
# This situation should never happen, as Home Assistant will only
# send updates for existing entries. In case it does, we'll just
# abort the flow with an unknown error.
return self.async_abort(reason="unknown")
async def async_step_discovery_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:

View File

@ -3,6 +3,11 @@
"name": "HomeWizard Energy",
"codeowners": ["@DCSBL"],
"config_flow": true,
"dhcp": [
{
"registered_devices": true
}
],
"documentation": "https://www.home-assistant.io/integrations/homewizard",
"iot_class": "local_polling",
"loggers": ["homewizard_energy"],

View File

@ -46,11 +46,7 @@ rules:
# Gold
devices: done
diagnostics: done
discovery-update-info:
status: todo
comment: |
The integration doesn't update the device info based on DHCP discovery
of known existing devices.
discovery-update-info: done
discovery: done
docs-data-update: done
docs-examples: done

View File

@ -236,6 +236,10 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"hostname": "guardian*",
"macaddress": "30AEA4*",
},
{
"domain": "homewizard",
"registered_devices": True,
},
{
"domain": "hunterdouglas_powerview",
"registered_devices": True,

View File

@ -8,7 +8,7 @@ import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant import config_entries
from homeassistant.components import zeroconf
from homeassistant.components import dhcp, zeroconf
from homeassistant.components.homewizard.const import DOMAIN
from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.core import HomeAssistant
@ -263,6 +263,80 @@ async def test_discovery_invalid_api(hass: HomeAssistant) -> None:
assert result["reason"] == "unsupported_api_version"
async def test_dhcp_discovery_updates_entry(
hass: HomeAssistant,
mock_homewizardenergy: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test DHCP discovery updates config entries."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_DHCP},
data=dhcp.DhcpServiceInfo(
ip="1.0.0.127",
hostname="HW-p1meter-aabbcc",
macaddress="5c2fafabcdef",
),
)
assert result.get("type") is FlowResultType.ABORT
assert result.get("reason") == "already_configured"
assert mock_config_entry.data[CONF_IP_ADDRESS] == "1.0.0.127"
@pytest.mark.usefixtures("mock_setup_entry")
@pytest.mark.parametrize(
("exception"),
[(DisabledError), (RequestError)],
)
async def test_dhcp_discovery_updates_entry_fails(
hass: HomeAssistant,
mock_homewizardenergy: MagicMock,
mock_config_entry: MockConfigEntry,
exception: Exception,
) -> None:
"""Test DHCP discovery updates config entries, but fails to connect."""
mock_homewizardenergy.device.side_effect = exception
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_DHCP},
data=dhcp.DhcpServiceInfo(
ip="1.0.0.127",
hostname="HW-p1meter-aabbcc",
macaddress="5c2fafabcdef",
),
)
assert result.get("type") is FlowResultType.ABORT
assert result.get("reason") == "unknown"
async def test_dhcp_discovery_ignores_unknown(
hass: HomeAssistant,
mock_homewizardenergy: MagicMock,
) -> None:
"""Test DHCP discovery is only used for updates.
Anything else will just abort the flow.
"""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_DHCP},
data=dhcp.DhcpServiceInfo(
ip="127.0.0.1",
hostname="HW-p1meter-aabbcc",
macaddress="5c2fafabcdef",
),
)
assert result.get("type") is FlowResultType.ABORT
assert result.get("reason") == "unknown"
async def test_discovery_flow_updates_new_ip(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,