SMA add DHCP strictness (#145753)

* Add DHCP strictness (needs beta check)

* Update to check on CONF_MAC

* Update to check on CONF_HOST

* Update hostname

* Polish it a bit

* Update to CONF_HOST, again

* Add split

* Add CONF_MAC add upon detection

* epenet feedback

* epenet round II
This commit is contained in:
Erwin Douna 2025-07-02 14:48:21 +02:00 committed by GitHub
parent b7496be61f
commit 3d27c0ce52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 63 additions and 1 deletions

View File

@ -184,7 +184,36 @@ class SmaConfigFlow(ConfigFlow, domain=DOMAIN):
self._data[CONF_HOST] = discovery_info.ip
self._data[CONF_MAC] = format_mac(self._discovery_data[CONF_MAC])
await self.async_set_unique_id(discovery_info.hostname.replace("SMA", ""))
_LOGGER.debug(
"DHCP discovery detected SMA device: %s, IP: %s, MAC: %s",
self._discovery_data[CONF_NAME],
self._discovery_data[CONF_HOST],
self._discovery_data[CONF_MAC],
)
existing_entries_with_host = [
entry
for entry in self._async_current_entries(include_ignore=False)
if entry.data.get(CONF_HOST) == self._data[CONF_HOST]
and not entry.data.get(CONF_MAC)
]
# If we have an existing entry with the same host but no MAC address,
# we update the entry with the MAC address and reload it.
if existing_entries_with_host:
entry = existing_entries_with_host[0]
self.async_update_reload_and_abort(
entry, data_updates={CONF_MAC: self._data[CONF_MAC]}
)
# Finally, check if the hostname (which represents the SMA serial number) is unique
serial_number = discovery_info.hostname.lower()
# Example hostname: sma12345678-01
# Remove 'sma' prefix and strip everything after the dash (including the dash)
if serial_number.startswith("sma"):
serial_number = serial_number.removeprefix("sma")
serial_number = serial_number.split("-", 1)[0]
await self.async_set_unique_id(serial_number)
self._abort_if_unique_id_configured()
return await self.async_step_discovery_confirm()

View File

@ -11,8 +11,10 @@ import pytest
from homeassistant.components.sma.const import DOMAIN
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER
from homeassistant.const import CONF_MAC
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
from . import (
@ -37,6 +39,12 @@ DHCP_DISCOVERY_DUPLICATE = DhcpServiceInfo(
macaddress="0015bb00abcd",
)
DHCP_DISCOVERY_DUPLICATE_001 = DhcpServiceInfo(
ip="1.1.1.1",
hostname="SMA123456789-001",
macaddress="0015bb00abcd",
)
async def test_form(
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_sma_client: AsyncMock
@ -154,6 +162,31 @@ async def test_dhcp_already_configured(
assert result["reason"] == "already_configured"
async def test_dhcp_already_configured_duplicate(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None:
"""Test starting a flow by DHCP when already configured and MAC is added."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert CONF_MAC not in mock_config_entry.data
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_DHCP},
data=DHCP_DISCOVERY_DUPLICATE_001,
)
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "already_configured"
await hass.async_block_till_done()
assert mock_config_entry.data.get(CONF_MAC) == format_mac(
DHCP_DISCOVERY_DUPLICATE_001.macaddress
)
@pytest.mark.parametrize(
("exception", "error"),
[