mirror of
https://github.com/home-assistant/core.git
synced 2026-04-28 18:12:37 +02:00
Add Re-Configure workflow to the Elk M1 Integration (#146368)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
@@ -120,6 +120,14 @@ def _make_url_from_data(data: dict[str, str]) -> str:
|
||||
return f"{protocol}{address}"
|
||||
|
||||
|
||||
def _get_protocol_from_url(url: str) -> str:
|
||||
"""Get protocol from URL. Returns the configured protocol from URL or the default secure protocol."""
|
||||
return next(
|
||||
(k for k, v in PROTOCOL_MAP.items() if url.startswith(v)),
|
||||
DEFAULT_SECURE_PROTOCOL,
|
||||
)
|
||||
|
||||
|
||||
def _placeholders_from_device(device: ElkSystem) -> dict[str, str]:
|
||||
return {
|
||||
"mac_address": _short_mac(device.mac_address),
|
||||
@@ -205,6 +213,78 @@ class Elkm1ConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
)
|
||||
return await self.async_step_discovered_connection()
|
||||
|
||||
async def async_step_reconfigure(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle reconfiguration of the integration."""
|
||||
errors: dict[str, str] = {}
|
||||
reconfigure_entry = self._get_reconfigure_entry()
|
||||
existing_data = reconfigure_entry.data
|
||||
|
||||
if user_input is not None:
|
||||
validate_input_data = dict(user_input)
|
||||
validate_input_data[CONF_PREFIX] = existing_data.get(CONF_PREFIX, "")
|
||||
|
||||
try:
|
||||
info = await validate_input(
|
||||
validate_input_data, reconfigure_entry.unique_id
|
||||
)
|
||||
except TimeoutError:
|
||||
errors["base"] = "cannot_connect"
|
||||
except InvalidAuth:
|
||||
errors[CONF_PASSWORD] = "invalid_auth"
|
||||
except Exception:
|
||||
_LOGGER.exception("Unexpected exception during reconfiguration")
|
||||
errors["base"] = "unknown"
|
||||
else:
|
||||
# Discover the device at the provided address to obtain its MAC (unique_id)
|
||||
device = await async_discover_device(
|
||||
self.hass, validate_input_data[CONF_ADDRESS]
|
||||
)
|
||||
if device is not None and device.mac_address:
|
||||
await self.async_set_unique_id(dr.format_mac(device.mac_address))
|
||||
self._abort_if_unique_id_mismatch() # aborts if user tried to switch devices
|
||||
else:
|
||||
# If we cannot confirm identity, keep existing behavior (don't block reconfigure)
|
||||
await self.async_set_unique_id(reconfigure_entry.unique_id)
|
||||
|
||||
return self.async_update_reload_and_abort(
|
||||
reconfigure_entry,
|
||||
data_updates={
|
||||
**reconfigure_entry.data,
|
||||
CONF_HOST: info[CONF_HOST],
|
||||
CONF_USERNAME: validate_input_data[CONF_USERNAME],
|
||||
CONF_PASSWORD: validate_input_data[CONF_PASSWORD],
|
||||
CONF_PREFIX: info[CONF_PREFIX],
|
||||
},
|
||||
reason="reconfigure_successful",
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="reconfigure",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_USERNAME,
|
||||
default=existing_data.get(CONF_USERNAME, ""),
|
||||
): str,
|
||||
vol.Optional(
|
||||
CONF_PASSWORD,
|
||||
default="",
|
||||
): str,
|
||||
vol.Required(
|
||||
CONF_ADDRESS,
|
||||
default=hostname_from_url(existing_data[CONF_HOST]),
|
||||
): str,
|
||||
vol.Required(
|
||||
CONF_PROTOCOL,
|
||||
default=_get_protocol_from_url(existing_data[CONF_HOST]),
|
||||
): vol.In(ALL_PROTOCOLS),
|
||||
}
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@@ -249,12 +329,14 @@ class Elkm1ConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
try:
|
||||
info = await validate_input(user_input, self.unique_id)
|
||||
except TimeoutError:
|
||||
except TimeoutError as ex:
|
||||
_LOGGER.debug("Connection timed out: %s", ex)
|
||||
return {"base": "cannot_connect"}, None
|
||||
except InvalidAuth:
|
||||
except InvalidAuth as ex:
|
||||
_LOGGER.debug("Invalid auth for %s: %s", user_input.get(CONF_HOST), ex)
|
||||
return {CONF_PASSWORD: "invalid_auth"}, None
|
||||
except Exception:
|
||||
_LOGGER.exception("Unexpected exception")
|
||||
_LOGGER.exception("Unexpected error validating input")
|
||||
return {"base": "unknown"}, None
|
||||
|
||||
if importing:
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
"address": "The IP address or domain or serial port if connecting via serial.",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]",
|
||||
"prefix": "A unique prefix (leave blank if you only have one ElkM1).",
|
||||
"temperature_unit": "The temperature unit ElkM1 uses."
|
||||
"prefix": "A unique prefix (leave blank if you only have one Elk-M1).",
|
||||
"temperature_unit": "The temperature unit Elk-M1 uses."
|
||||
}
|
||||
},
|
||||
"discovered_connection": {
|
||||
@@ -30,6 +30,16 @@
|
||||
"password": "[%key:common::config_flow::data::password%]",
|
||||
"temperature_unit": "[%key:component::elkm1::config::step::manual_connection::data::temperature_unit%]"
|
||||
}
|
||||
},
|
||||
"reconfigure": {
|
||||
"title": "Reconfigure Elk-M1 Control",
|
||||
"description": "[%key:component::elkm1::config::step::manual_connection::description%]",
|
||||
"data": {
|
||||
"protocol": "[%key:component::elkm1::config::step::manual_connection::data::protocol%]",
|
||||
"address": "[%key:component::elkm1::config::step::manual_connection::data::address%]",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
@@ -42,8 +52,10 @@
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"already_configured": "An ElkM1 with this prefix is already configured",
|
||||
"address_already_configured": "An ElkM1 with this address is already configured"
|
||||
"already_configured": "An Elk-M1 with this prefix is already configured",
|
||||
"address_already_configured": "An Elk-M1 with this address is already configured",
|
||||
"reconfigure_successful": "Successfully reconfigured Elk-M1 integration",
|
||||
"unique_id_mismatch": "Reconfigure should be used for the same device not a new one"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
@@ -69,7 +81,7 @@
|
||||
},
|
||||
"alarm_arm_home_instant": {
|
||||
"name": "Alarm arm home instant",
|
||||
"description": "Arms the ElkM1 in home instant mode.",
|
||||
"description": "Arms the Elk-M1 in home instant mode.",
|
||||
"fields": {
|
||||
"code": {
|
||||
"name": "Code",
|
||||
@@ -79,7 +91,7 @@
|
||||
},
|
||||
"alarm_arm_night_instant": {
|
||||
"name": "Alarm arm night instant",
|
||||
"description": "Arms the ElkM1 in night instant mode.",
|
||||
"description": "Arms the Elk-M1 in night instant mode.",
|
||||
"fields": {
|
||||
"code": {
|
||||
"name": "Code",
|
||||
@@ -89,7 +101,7 @@
|
||||
},
|
||||
"alarm_arm_vacation": {
|
||||
"name": "Alarm arm vacation",
|
||||
"description": "Arms the ElkM1 in vacation mode.",
|
||||
"description": "Arms the Elk-M1 in vacation mode.",
|
||||
"fields": {
|
||||
"code": {
|
||||
"name": "Code",
|
||||
@@ -99,7 +111,7 @@
|
||||
},
|
||||
"alarm_display_message": {
|
||||
"name": "Alarm display message",
|
||||
"description": "Displays a message on all of the ElkM1 keypads for an area.",
|
||||
"description": "Displays a message on all of the Elk-M1 keypads for an area.",
|
||||
"fields": {
|
||||
"clear": {
|
||||
"name": "Clear",
|
||||
@@ -135,7 +147,7 @@
|
||||
},
|
||||
"speak_phrase": {
|
||||
"name": "Speak phrase",
|
||||
"description": "Speaks a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.",
|
||||
"description": "Speaks a phrase. See list of phrases in Elk-M1 ASCII Protocol documentation.",
|
||||
"fields": {
|
||||
"number": {
|
||||
"name": "Phrase number",
|
||||
@@ -149,7 +161,7 @@
|
||||
},
|
||||
"speak_word": {
|
||||
"name": "Speak word",
|
||||
"description": "Speaks a word. See list of words in ElkM1 ASCII Protocol documentation.",
|
||||
"description": "Speaks a word. See list of words in Elk-M1 ASCII Protocol documentation.",
|
||||
"fields": {
|
||||
"number": {
|
||||
"name": "Word number",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user