diff --git a/homeassistant/components/yale_smart_alarm/__init__.py b/homeassistant/components/yale_smart_alarm/__init__.py index 763742cce70..830d8d9f69e 100644 --- a/homeassistant/components/yale_smart_alarm/__init__.py +++ b/homeassistant/components/yale_smart_alarm/__init__.py @@ -1,11 +1,14 @@ """The yale_smart_alarm component.""" from __future__ import annotations +from homeassistant.components.lock import CONF_DEFAULT_CODE, DOMAIN as LOCK_DOMAIN from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_CODE from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers import entity_registry as er -from .const import COORDINATOR, DOMAIN, PLATFORMS +from .const import COORDINATOR, DOMAIN, LOGGER, PLATFORMS from .coordinator import YaleDataUpdateCoordinator @@ -39,3 +42,30 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data[DOMAIN].pop(entry.entry_id) return True return False + + +async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Migrate old entry.""" + LOGGER.debug("Migrating from version %s", entry.version) + + if entry.version == 1: + if config_entry_default_code := entry.options.get(CONF_CODE): + entity_reg = er.async_get(hass) + entries = er.async_entries_for_config_entry(entity_reg, entry.entry_id) + for entity in entries: + if entity.entity_id.startswith("lock"): + entity_reg.async_update_entity_options( + entity.entity_id, + LOCK_DOMAIN, + {CONF_DEFAULT_CODE: config_entry_default_code}, + ) + new_options = entry.options.copy() + del new_options[CONF_CODE] + + hass.config_entries.async_update_entry(entry, options=new_options) + + entry.version = 2 + + LOGGER.info("Migration to version %s successful", entry.version) + + return True diff --git a/homeassistant/components/yale_smart_alarm/config_flow.py b/homeassistant/components/yale_smart_alarm/config_flow.py index a2462df41cb..ff813d43d78 100644 --- a/homeassistant/components/yale_smart_alarm/config_flow.py +++ b/homeassistant/components/yale_smart_alarm/config_flow.py @@ -9,7 +9,7 @@ from yalesmartalarmclient.client import YaleSmartAlarmClient from yalesmartalarmclient.exceptions import AuthenticationError from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow -from homeassistant.const import CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME +from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult import homeassistant.helpers.config_validation as cv @@ -44,7 +44,7 @@ DATA_SCHEMA_AUTH = vol.Schema( class YaleConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for Yale integration.""" - VERSION = 1 + VERSION = 2 entry: ConfigEntry | None @@ -155,32 +155,22 @@ class YaleOptionsFlowHandler(OptionsFlow): self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Manage Yale options.""" - errors = {} + errors: dict[str, Any] = {} if user_input: - if len(user_input.get(CONF_CODE, "")) not in [ - 0, - user_input[CONF_LOCK_CODE_DIGITS], - ]: - errors["base"] = "code_format_mismatch" - else: - return self.async_create_entry(title="", data=user_input) + return self.async_create_entry(data=user_input) return self.async_show_form( step_id="init", data_schema=vol.Schema( { - vol.Optional( - CONF_CODE, - description={ - "suggested_value": self.entry.options.get(CONF_CODE) - }, - ): str, vol.Optional( CONF_LOCK_CODE_DIGITS, - default=self.entry.options.get( - CONF_LOCK_CODE_DIGITS, DEFAULT_LOCK_CODE_DIGITS - ), + description={ + "suggested_value": self.entry.options.get( + CONF_LOCK_CODE_DIGITS, DEFAULT_LOCK_CODE_DIGITS + ) + }, ): int, } ), diff --git a/homeassistant/components/yale_smart_alarm/lock.py b/homeassistant/components/yale_smart_alarm/lock.py index 397a9cc8db1..50d7b28c52b 100644 --- a/homeassistant/components/yale_smart_alarm/lock.py +++ b/homeassistant/components/yale_smart_alarm/lock.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any from homeassistant.components.lock import LockEntity from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ATTR_CODE, CONF_CODE +from homeassistant.const import ATTR_CODE from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -52,9 +52,7 @@ class YaleDoorlock(YaleEntity, LockEntity): async def async_unlock(self, **kwargs: Any) -> None: """Send unlock command.""" - code: str | None = kwargs.get( - ATTR_CODE, self.coordinator.entry.options.get(CONF_CODE) - ) + code: str | None = kwargs.get(ATTR_CODE) return await self.async_set_lock("unlocked", code) async def async_lock(self, **kwargs: Any) -> None: diff --git a/homeassistant/components/yale_smart_alarm/strings.json b/homeassistant/components/yale_smart_alarm/strings.json index ec0c5d0702a..a51d151d7d9 100644 --- a/homeassistant/components/yale_smart_alarm/strings.json +++ b/homeassistant/components/yale_smart_alarm/strings.json @@ -31,13 +31,9 @@ "step": { "init": { "data": { - "code": "Default code for locks, used if none is given", "lock_code_digits": "Number of digits in PIN code for locks" } } - }, - "error": { - "code_format_mismatch": "The code does not match the required number of digits" } }, "entity": { diff --git a/tests/components/yale_smart_alarm/test_config_flow.py b/tests/components/yale_smart_alarm/test_config_flow.py index 4553a120060..90c0b78baf5 100644 --- a/tests/components/yale_smart_alarm/test_config_flow.py +++ b/tests/components/yale_smart_alarm/test_config_flow.py @@ -121,6 +121,7 @@ async def test_reauth_flow(hass: HomeAssistant) -> None: "name": "Yale Smart Alarm", "area_id": "1", }, + version=2, ) entry.add_to_hass(hass) @@ -187,6 +188,7 @@ async def test_reauth_flow_error( "name": "Yale Smart Alarm", "area_id": "1", }, + version=2, ) entry.add_to_hass(hass) @@ -248,11 +250,20 @@ async def test_options_flow(hass: HomeAssistant) -> None: entry = MockConfigEntry( domain=DOMAIN, unique_id="test-username", - data={}, + data={ + "username": "test-username", + "password": "test-password", + "name": "Yale Smart Alarm", + "area_id": "1", + }, + version=2, ) entry.add_to_hass(hass) with patch( + "homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient", + return_value=True, + ), patch( "homeassistant.components.yale_smart_alarm.async_setup_entry", return_value=True, ): @@ -266,48 +277,8 @@ async def test_options_flow(hass: HomeAssistant) -> None: result = await hass.config_entries.options.async_configure( result["flow_id"], - user_input={"code": "123456", "lock_code_digits": 6}, + user_input={"lock_code_digits": 6}, ) assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["data"] == {"code": "123456", "lock_code_digits": 6} - - -async def test_options_flow_format_mismatch(hass: HomeAssistant) -> None: - """Test options config flow with a code format mismatch error.""" - entry = MockConfigEntry( - domain=DOMAIN, - unique_id="test-username", - data={}, - ) - entry.add_to_hass(hass) - - with patch( - "homeassistant.components.yale_smart_alarm.async_setup_entry", - return_value=True, - ): - assert await hass.config_entries.async_setup(entry.entry_id) - await hass.async_block_till_done() - - result = await hass.config_entries.options.async_init(entry.entry_id) - - assert result["type"] == FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"] == {} - - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={"code": "123", "lock_code_digits": 6}, - ) - - assert result["type"] == FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"] == {"base": "code_format_mismatch"} - - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={"code": "123456", "lock_code_digits": 6}, - ) - - assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["data"] == {"code": "123456", "lock_code_digits": 6} + assert result["data"] == {"lock_code_digits": 6}