10000 SMA add DHCP strictness by erwindouna · Pull Request #145753 · home-assistant/core · GitHub
[go: up one dir, main page]

Skip to content

SMA add DHCP strictness #145753

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion homeassistant/components/sma/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,36 @@ async def async_step_dhcp(
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a migration needed for all the existing entries that may have a dash in their unique ID?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first glance it doesn't look like it. The manual setup entries have been configured without the "sma" prefix and the dash.
I am not 100% familiar with the exact range of serial numbers, nor can I find the proper information - it's as bit on reverse engineering and what I can find in pyama.

self._abort_if_unique_id_configured()

return await self.async_step_discovery_confirm()
Expand Down
33 changes: 33 additions & 0 deletions tests/components/sma/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

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 (
Expand All @@ -37,6 +39,12 @@
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
Expand Down Expand Up @@ -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"),
[
Expand Down
0