Add reconfigure flow to Cambridge Audio (#131091)

* Add reconfigure flow to Cambridge Audio

* Update

* Add reconfigure flow to Cambridge Audio

* Fix

* Add helper method to reconfigure tests

* Update quality scale
This commit is contained in:
Noah Husby 2024-12-09 14:39:09 -05:00 committed by GitHub
parent d3fab7d87a
commit aa7b69afd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 90 additions and 4 deletions

View File

@ -7,12 +7,18 @@ from aiostreammagic import StreamMagicClient
import voluptuous as vol
from homeassistant.components import zeroconf
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import (
SOURCE_RECONFIGURE,
ConfigFlow,
ConfigFlowResult,
)
from homeassistant.const import CONF_HOST, CONF_NAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONNECT_TIMEOUT, DOMAIN, STREAM_MAGIC_EXCEPTIONS
DATA_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str})
class CambridgeAudioConfigFlow(ConfigFlow, domain=DOMAIN):
"""Cambridge Audio configuration flow."""
@ -64,6 +70,17 @@ class CambridgeAudioConfigFlow(ConfigFlow, domain=DOMAIN):
},
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle reconfiguration of the integration."""
if not user_input:
return self.async_show_form(
step_id="reconfigure",
data_schema=DATA_SCHEMA,
)
return await self.async_step_user(user_input)
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
@ -82,6 +99,12 @@ class CambridgeAudioConfigFlow(ConfigFlow, domain=DOMAIN):
await self.async_set_unique_id(
client.info.unit_id, raise_on_progress=False
)
if self.source == SOURCE_RECONFIGURE:
self._abort_if_unique_id_mismatch(reason="wrong_device")
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data_updates={CONF_HOST: user_input[CONF_HOST]},
)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=client.info.name,
@ -91,6 +114,6 @@ class CambridgeAudioConfigFlow(ConfigFlow, domain=DOMAIN):
await client.disconnect()
return self.async_show_form(
step_id="user",
data_schema=vol.Schema({vol.Required(CONF_HOST): str}),
data_schema=DATA_SCHEMA,
errors=errors,
)

View File

@ -56,7 +56,7 @@ rules:
diagnostics: done
exception-translations: done
icon-translations: done
reconfiguration-flow: todo
reconfiguration-flow: done
dynamic-devices:
status: exempt
comment: |

View File

@ -13,12 +13,23 @@
},
"discovery_confirm": {
"description": "Do you want to setup {name}?"
},
"reconfigure": {
"description": "Reconfigure your Cambridge Audio Streamer.",
"data": {
"host": "[%key:common::config_flow::data::host%]"
},
"data_description": {
"host": "[%key:component::cambridge_audio::config::step::user::data_description::host%]"
}
}
},
"error": {
"cannot_connect": "Failed to connect to Cambridge Audio device. Please make sure the device is powered up and connected to the network. Try power-cycling the device if it does not connect."
},
"abort": {
"wrong_device": "This Cambridge Audio device does not match the existing device id. Please make sure you entered the correct IP address.",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}

View File

@ -7,7 +7,7 @@ from aiostreammagic import StreamMagicError
from homeassistant.components.cambridge_audio.const import DOMAIN
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF, ConfigFlowResult
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
@ -192,3 +192,55 @@ async def test_zeroconf_duplicate(
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def _start_reconfigure_flow(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> ConfigFlowResult:
"""Initialize a reconfigure flow."""
mock_config_entry.add_to_hass(hass)
reconfigure_result = await mock_config_entry.start_reconfigure_flow(hass)
assert reconfigure_result["type"] is FlowResultType.FORM
assert reconfigure_result["step_id"] == "reconfigure"
return await hass.config_entries.flow.async_configure(
reconfigure_result["flow_id"],
{CONF_HOST: "192.168.20.219"},
)
async def test_reconfigure_flow(
hass: HomeAssistant,
mock_stream_magic_client: AsyncMock,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test reconfigure flow."""
result = await _start_reconfigure_flow(hass, mock_config_entry)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
entry = hass.config_entries.async_get_entry(mock_config_entry.entry_id)
assert entry
assert entry.data == {
CONF_HOST: "192.168.20.219",
}
async def test_reconfigure_unique_id_mismatch(
hass: HomeAssistant,
mock_stream_magic_client: AsyncMock,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Ensure reconfigure flow aborts when the bride changes."""
mock_stream_magic_client.info.unit_id = "different_udn"
result = await _start_reconfigure_flow(hass, mock_config_entry)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "wrong_device"