Fix issues with bosch alarm dhcp discovery (#145034)

* fix issues with checking mac address for panels added manually

* add test

* don't allow discovery to pick up a host twice

* make sure we validate tests without a mac address

* check entry is loaded

* Update config_flow.py

* apply changes from review

* assert unique id

* assert unique id
This commit is contained in:
Sanjay Govind 2025-05-20 22:26:41 +12:00 committed by GitHub
parent f3f5fca0b9
commit 1ff5dd8ef5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 103 additions and 11 deletions

View File

@ -15,6 +15,7 @@ from homeassistant.config_entries import (
SOURCE_DHCP,
SOURCE_RECONFIGURE,
SOURCE_USER,
ConfigEntryState,
ConfigFlow,
ConfigFlowResult,
)
@ -152,7 +153,7 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
return self.async_abort(reason="already_in_progress")
for entry in self.hass.config_entries.async_entries(DOMAIN):
if entry.data[CONF_MAC] == self.mac:
if entry.data.get(CONF_MAC) == self.mac:
result = self.hass.config_entries.async_update_entry(
entry,
data={
@ -163,6 +164,21 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
if result:
self.hass.config_entries.async_schedule_reload(entry.entry_id)
return self.async_abort(reason="already_configured")
if entry.data[CONF_HOST] == discovery_info.ip:
if (
not entry.data.get(CONF_MAC)
and entry.state is ConfigEntryState.LOADED
):
result = self.hass.config_entries.async_update_entry(
entry,
data={
**entry.data,
CONF_MAC: self.mac,
},
)
if result:
self.hass.config_entries.async_schedule_reload(entry.entry_id)
return self.async_abort(reason="already_configured")
try:
# Use load_selector = 0 to fetch the panel model without authentication.
(model, _) = await try_connect(

View File

@ -201,15 +201,16 @@ def mock_config_entry(
mac_address: str | None,
) -> MockConfigEntry:
"""Mock config entry for bosch alarm."""
data = {
CONF_HOST: "0.0.0.0",
CONF_PORT: 7700,
CONF_MODEL: "bosch_alarm_test_data.model",
}
if mac_address:
data[CONF_MAC] = format_mac(mac_address)
return MockConfigEntry(
domain=DOMAIN,
unique_id=serial_number,
entry_id="01JQ917ACKQ33HHM7YCFXYZX51",
data={
CONF_HOST: "0.0.0.0",
CONF_PORT: 7700,
CONF_MODEL: "bosch_alarm_test_data.model",
CONF_MAC: mac_address and format_mac(mac_address),
}
| extra_config_entry_data,
data=data | extra_config_entry_data,
)

View File

@ -89,7 +89,6 @@
'entry_data': dict({
'host': '0.0.0.0',
'installer_code': '**REDACTED**',
'mac': None,
'model': 'AMAX 3000',
'password': '**REDACTED**',
'port': 7700,
@ -185,7 +184,6 @@
}),
'entry_data': dict({
'host': '0.0.0.0',
'mac': None,
'model': 'B5512 (US1B)',
'password': '**REDACTED**',
'port': 7700,
@ -281,7 +279,6 @@
}),
'entry_data': dict({
'host': '0.0.0.0',
'mac': None,
'model': 'Solution 3000',
'port': 7700,
'user_code': '**REDACTED**',

View File

@ -309,6 +309,55 @@ async def test_dhcp_updates_host(
assert mock_config_entry.data[CONF_HOST] == "4.5.6.7"
@pytest.mark.parametrize("serial_number", ["12345678"])
async def test_dhcp_discovery_if_panel_setup_config_flow(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
mock_panel: AsyncMock,
serial_number: str,
model_name: str,
config_flow_data: dict[str, Any],
) -> None:
"""Test DHCP discovery doesn't fail if a different panel was set up via config flow."""
await setup_integration(hass, mock_config_entry)
# change out the serial number so we can test discovery for a different panel
mock_panel.serial_number = "789101112"
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_DHCP},
data=DhcpServiceInfo(
hostname="test",
ip="4.5.6.7",
macaddress="34ea34b43b5a",
),
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "auth"
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
config_flow_data,
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"Bosch {model_name}"
assert result["data"] == {
CONF_HOST: "4.5.6.7",
CONF_MAC: "34:ea:34:b4:3b:5a",
CONF_PORT: 7700,
CONF_MODEL: model_name,
**config_flow_data,
}
assert mock_config_entry.unique_id == serial_number
assert result["result"].unique_id == "789101112"
@pytest.mark.parametrize("model", ["solution_3000", "amax_3000"])
async def test_dhcp_abort_ongoing_flow(
hass: HomeAssistant,
@ -341,6 +390,35 @@ async def test_dhcp_abort_ongoing_flow(
assert result["reason"] == "already_in_progress"
async def test_dhcp_updates_mac(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
mock_panel: AsyncMock,
model_name: str,
serial_number: str,
config_flow_data: dict[str, Any],
) -> None:
"""Test DHCP discovery flow updates mac if the previous entry did not have a mac address."""
await setup_integration(hass, mock_config_entry)
assert CONF_MAC not in mock_config_entry.data
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_DHCP},
data=DhcpServiceInfo(
hostname="test",
ip="0.0.0.0",
macaddress="34ea34b43b5a",
),
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert mock_config_entry.data[CONF_MAC] == "34:ea:34:b4:3b:5a"
async def test_reauth_flow_success(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,