This commit is contained in:
G Johansson
2026-07-06 12:30:01 +00:00
parent a3e5c9070b
commit 7e3103cbe7
5 changed files with 69 additions and 41 deletions
+26 -1
View File
@@ -3,7 +3,7 @@
import asyncio
from collections.abc import Collection
import logging
from typing import Any
from typing import TYPE_CHECKING, Any
import voluptuous as vol
@@ -136,6 +136,31 @@ def groups_with_entity(hass: HomeAssistant, entity_id: str) -> list[str]:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry."""
if "old_entity_id" in entry.options:
# This means we are migrating from a Min/Max helper to a Group sensor
old_entity = entry.options["old_entity_id"]
entity_reg = er.async_get(hass)
old_entity_entry = entity_reg.async_get(old_entity)
if not old_entity_entry:
# User has manually removed it before we came here
# Skip the migration and just continue with setting up the group sensor
_LOGGER.warning(
"Old entity %s has been manually removed before migration", old_entity
)
else:
if TYPE_CHECKING:
assert old_entity_entry.config_entry_id
await hass.config_entries.async_unload(old_entity_entry.config_entry_id)
entity_reg.async_update_entity_platform(
old_entity,
DOMAIN,
new_config_entry_id=entry.entry_id,
new_unique_id=entry.entry_id,
)
new_options = dict(entry.options)
new_options.pop("old_entity_id")
hass.config_entries.async_update_entry(entry, options=new_options)
await hass.config_entries.async_remove(old_entity_entry.config_entry_id)
await hass.config_entries.async_forward_entry_setups(
entry, (entry.options["group_type"],)
)
@@ -134,6 +134,12 @@ SENSOR_CONFIG_SCHEMA = basic_group_config_schema(
["sensor", "number", "input_number"]
).extend(SENSOR_CONFIG_EXTENDS)
SENSOR_IMPORT_SCHEMA = vol.Schema(
{
vol.Required("old_entity_id"): selector.TextSelector(),
}
).extend(SENSOR_CONFIG_SCHEMA.schema)
async def light_switch_options_schema(
domain: str, handler: SchemaCommonFlowHandler | None
@@ -197,8 +203,30 @@ def set_group_type(
return _set_group_type
def validate_import() -> Callable[
[SchemaCommonFlowHandler, dict[str, Any]], Coroutine[Any, Any, dict[str, Any]]
]:
"""Validate import from Min/Max integration.
Should be removed when deprecation of Min/Max integration has ended.
"""
async def _validate_and_set_type(
handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
) -> dict[str, Any]:
"""Add group type to user input."""
validated_input = SENSOR_IMPORT_SCHEMA(user_input)
return {CONF_GROUP_TYPE: "sensor", **validated_input}
return _validate_and_set_type
CONFIG_FLOW = {
"user": SchemaFlowMenuStep(GROUP_TYPES),
"import": SchemaFlowFormStep(
None,
validate_user_input=validate_import(),
),
"binary_sensor": SchemaFlowFormStep(
BINARY_SENSOR_CONFIG_SCHEMA,
preview="group",
+13 -38
View File
@@ -1,22 +1,19 @@
"""Repairs platform for the Min/Max integration."""
from types import MappingProxyType
from typing import TYPE_CHECKING, Any, cast
import voluptuous as vol
from homeassistant import data_entry_flow
from homeassistant.components.group import (
CONF_ENTITIES,
CONF_GROUP_TYPE,
CONF_HIDE_MEMBERS,
CONF_IGNORE_NON_NUMERIC,
DOMAIN as GROUP_DOMAIN,
)
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import SOURCE_USER, ConfigEntry, ConfigEntryDisabler
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult, FlowResultType
from homeassistant.helpers import entity_registry as er
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
@@ -32,13 +29,13 @@ class MigrateToGroupSensorFlow(RepairsFlow):
async def async_step_init(
self, user_input: dict[str, str] | None = None
) -> data_entry_flow.FlowResult:
) -> FlowResult:
"""Handle the first step of a fix flow."""
return await self.async_step_migrate()
async def async_step_migrate(
self, user_input: dict[str, Any] | None = None
) -> data_entry_flow.FlowResult:
) -> FlowResult:
"""Handle the migration step of a fix flow."""
entity_reg = er.async_get(self.hass)
old_entity = entity_reg.async_get_entity_id(
@@ -53,40 +50,18 @@ class MigrateToGroupSensorFlow(RepairsFlow):
config.pop(CONF_ROUND_DIGITS)
# Set group sensor defaults
config[CONF_HIDE_MEMBERS] = False
config[CONF_IGNORE_NON_NUMERIC] = False
config[CONF_GROUP_TYPE] = SENSOR_DOMAIN
# config[CONF_IGNORE_NON_NUMERIC] = False
# config[CONF_GROUP_TYPE] = SENSOR_DOMAIN
config["old_entity_id"] = old_entity
new_config_entry = ConfigEntry(
data={},
discovery_keys=MappingProxyType({}),
domain=GROUP_DOMAIN,
minor_version=1,
options=config,
source=SOURCE_USER,
subentries_data=[],
title=self.entry.title,
unique_id=None,
version=1,
disabled_by=ConfigEntryDisabler.USER,
import_result = await self.hass.config_entries.flow.async_init(
GROUP_DOMAIN,
context={"source": SOURCE_IMPORT},
data=config,
)
if not await self.hass.config_entries.async_unload(self.entry.entry_id):
return self.async_abort(reason="unload_failed")
await self.hass.config_entries.async_add(new_config_entry)
try:
entity_reg.async_update_entity_platform(
old_entity,
GROUP_DOMAIN,
new_config_entry_id=new_config_entry.entry_id,
new_unique_id=new_config_entry.entry_id,
)
except ValueError:
return self.async_abort(reason="entity_update_failed")
await self.hass.config_entries.async_set_disabled_by(
entry_id=new_config_entry.entry_id, disabled_by=None
)
await self.hass.config_entries.async_remove(self.entry.entry_id)
if import_result["type"] != FlowResultType.CREATE_ENTRY:
return self.async_abort(reason="could_not_import")
return self.async_create_entry(data={})
entity_info = entity_reg.async_get(old_entity)
@@ -14,6 +14,7 @@
"migrate_to_group_sensor": {
"fix_flow": {
"abort": {
"could_not_import": "Failed to import the config entry for the Group helper, please manually remove the Min/Max helper and create your new Group helper.",
"entity_not_found": "Entity could not be found as it has been removed, aborting the repair.",
"entity_update_failed": "Failed to update the entity to a Group sensor, please manually remove the obsolete entity.",
"unload_failed": "Failed to unload the Min/Max helper, please restart repairing the issue."
@@ -15,13 +15,12 @@
]),
'group_type': 'sensor',
'hide_members': False,
'ignore_non_numeric': False,
'name': 'My min_max',
'type': 'max',
}),
'pref_disable_new_entities': False,
'pref_disable_polling': False,
'source': 'user',
'source': 'import',
'subentries': list([
]),
'title': 'My min_max',