Skip to content

Commit 3d27c0c

Browse files
authored
SMA add DHCP strictness (home-assistant#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
1 parent b7496be commit 3d27c0c

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

homeassistant/components/sma/config_flow.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,36 @@ async def async_step_dhcp(
184184
self._data[CONF_HOST] = discovery_info.ip
185185
self._data[CONF_MAC] = format_mac(self._discovery_data[CONF_MAC])
186186

187-
await self.async_set_unique_id(discovery_info.hostname.replace("SMA", ""))
187+
_LOGGER.debug(
188+
"DHCP discovery detected SMA device: %s, IP: %s, MAC: %s",
189+
self._discovery_data[CONF_NAME],
190+
self._discovery_data[CONF_HOST],
191+
self._discovery_data[CONF_MAC],
192+
)
193+
194+
existing_entries_with_host = [
195+
entry
196+
for entry in self._async_current_entries(include_ignore=False)
197+
if entry.data.get(CONF_HOST) == self._data[CONF_HOST]
198+
and not entry.data.get(CONF_MAC)
199+
]
200+
201+
# If we have an existing entry with the same host but no MAC address,
202+
# we update the entry with the MAC address and reload it.
203+
if existing_entries_with_host:
204+
entry = existing_entries_with_host[0]
205+
self.async_update_reload_and_abort(
206+
entry, data_updates={CONF_MAC: self._data[CONF_MAC]}
207+
)
208+
209+
# Finally, check if the hostname (which represents the SMA serial number) is unique
210+
serial_number = discovery_info.hostname.lower()
211+
# Example hostname: sma12345678-01
212+
# Remove 'sma' prefix and strip everything after the dash (including the dash)
213+
if serial_number.startswith("sma"):
214+
serial_number = serial_number.removeprefix("sma")
215+
serial_number = serial_number.split("-", 1)[0]
216+
await self.async_set_unique_id(serial_number)
188217
self._abort_if_unique_id_configured()
189218

190219
return await self.async_step_discovery_confirm()

tests/components/sma/test_config_flow.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

1212
from homeassistant.components.sma.const import DOMAIN
1313
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER
14+
from homeassistant.const import CONF_MAC
1415
from homeassistant.core import HomeAssistant
1516
from homeassistant.data_entry_flow import FlowResultType
17+
from homeassistant.helpers.device_registry import format_mac
1618
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
1719

1820
from . import (
@@ -37,6 +39,12 @@
3739
macaddress="0015bb00abcd",
3840
)
3941

42+
DHCP_DISCOVERY_DUPLICATE_001 = DhcpServiceInfo(
43+
ip="1.1.1.1",
44+
hostname="SMA123456789-001",
45+
macaddress="0015bb00abcd",
46+
)
47+
4048

4149
async def test_form(
4250
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_sma_client: AsyncMock
@@ -154,6 +162,31 @@ async def test_dhcp_already_configured(
154162
assert result["reason"] == "already_configured"
155163

156164

165+
async def test_dhcp_already_configured_duplicate(
166+
hass: HomeAssistant, mock_config_entry: MockConfigEntry
167+
) -> None:
168+
"""Test starting a flow by DHCP when already configured and MAC is added."""
169+
mock_config_entry.add_to_hass(hass)
170+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
171+
await hass.async_block_till_done()
172+
173+
assert CONF_MAC not in mock_config_entry.data
174+
175+
result = await hass.config_entries.flow.async_init(
176+
DOMAIN,
177+
context={"source": SOURCE_DHCP},
178+
data=DHCP_DISCOVERY_DUPLICATE_001,
179+
)
180+
181+
assert result["type"] == FlowResultType.ABORT
182+
assert result["reason"] == "already_configured"
183+
await hass.async_block_till_done()
184+
185+
assert mock_config_entry.data.get(CONF_MAC) == format_mac(
186+
DHCP_DISCOVERY_DUPLICATE_001.macaddress
187+
)
188+
189+
157190
@pytest.mark.parametrize(
158191
("exception", "error"),
159192
[

0 commit comments

Comments
 (0)