Deprecate min_max and migrate to group sensor

This commit is contained in:
G Johansson
2026-07-06 12:28:32 +00:00
parent 229e009dfd
commit 524dc4b2b2
5 changed files with 107 additions and 99 deletions
+32 -1
View File
@@ -1,10 +1,15 @@
"""The min_max component."""
from homeassistant.config_entries import ConfigEntry
import logging
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from .const import DOMAIN
PLATFORMS = [Platform.SENSOR]
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
@@ -17,3 +22,29 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Migrate old entry."""
_LOGGER.debug("Migrating from version %s.%s", entry.version, entry.minor_version)
if entry.version > 2:
# This means the user has downgraded from a future version
return False
if entry.version == 1:
# Migration to group sensor and remove config entry
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=entry.options
)
)
hass.config_entries.async_update_entry(entry, version=2)
_LOGGER.debug(
"Migration to version %s.%s successful",
entry.version,
entry.minor_version,
)
return True
+11 -69
View File
@@ -1,77 +1,19 @@
"""Config flow for Min/Max integration."""
from collections.abc import Mapping
from typing import Any, cast, override
from typing import Any
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.components.input_number import DOMAIN as INPUT_NUMBER_DOMAIN
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import CONF_TYPE
from homeassistant.helpers import selector
from homeassistant.helpers.schema_config_entry_flow import (
SchemaConfigFlowHandler,
SchemaFlowFormStep,
)
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
_STATISTIC_MEASURES = [
"min",
"max",
"mean",
"median",
"last",
"range",
"sum",
]
from .const import DOMAIN
OPTIONS_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_IDS): selector.EntitySelector(
selector.EntitySelectorConfig(
domain=[SENSOR_DOMAIN, NUMBER_DOMAIN, INPUT_NUMBER_DOMAIN],
multiple=True,
),
),
vol.Required(CONF_TYPE): selector.SelectSelector(
selector.SelectSelectorConfig(
options=_STATISTIC_MEASURES, translation_key=CONF_TYPE
),
),
vol.Required(CONF_ROUND_DIGITS, default=2): selector.NumberSelector(
selector.NumberSelectorConfig(
min=0, max=6, mode=selector.NumberSelectorMode.BOX
),
),
}
)
class MinMaxConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for min_max integration."""
CONFIG_SCHEMA = vol.Schema(
{
vol.Required("name"): selector.TextSelector(),
}
).extend(OPTIONS_SCHEMA.schema)
VERSION = 2
CONFIG_FLOW = {
"user": SchemaFlowFormStep(CONFIG_SCHEMA),
}
OPTIONS_FLOW = {
"init": SchemaFlowFormStep(OPTIONS_SCHEMA),
}
class ConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
"""Handle a config or options flow for Min/Max."""
config_flow = CONFIG_FLOW
options_flow = OPTIONS_FLOW
options_flow_reloads = True
@override
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
"""Return config entry title."""
return cast(str, options["name"]) if "name" in options else ""
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the user step."""
return self.async_abort(reason="migrated_to_groups")
+29 -29
View File
@@ -6,6 +6,7 @@ import statistics
from typing import Any, override
import voluptuous as vol
import yaml
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
@@ -13,11 +14,11 @@ from homeassistant.components.sensor import (
SensorEntity,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_UNIT_OF_MEASUREMENT,
CONF_NAME,
CONF_PLATFORM,
CONF_TYPE,
CONF_UNIQUE_ID,
STATE_UNAVAILABLE,
@@ -25,13 +26,11 @@ from homeassistant.const import (
)
from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import get_device_class
from homeassistant.helpers.entity_platform import (
AddConfigEntryEntitiesCallback,
AddEntitiesCallback,
)
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
@@ -51,6 +50,8 @@ ATTR_LAST_ENTITY_ID = "last_entity_id"
ATTR_RANGE = "range"
ATTR_SUM = "sum"
CONF_ENTITIES = "entities"
ICON = "mdi:calculator"
SENSOR_TYPES = {
@@ -77,29 +78,27 @@ PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Initialize min/max/mean config entry."""
registry = er.async_get(hass)
entity_ids = er.async_validate_entity_ids(
registry, config_entry.options[CONF_ENTITY_IDS]
)
sensor_type = config_entry.options[CONF_TYPE]
round_digits = int(config_entry.options[CONF_ROUND_DIGITS])
async_add_entities(
[
MinMaxSensor(
entity_ids,
config_entry.title,
sensor_type,
round_digits,
config_entry.entry_id,
)
]
async def yaml_deprecation_notice(hass: HomeAssistant, config: ConfigType) -> None:
"""Raise repair issue for YAML configuration deprecation."""
platform_config = config.copy()
platform_config[CONF_ENTITIES] = platform_config.pop(CONF_ENTITY_IDS)
platform_config.pop(CONF_ROUND_DIGITS)
platform_config.pop(CONF_PLATFORM)
if CONF_NAME not in platform_config:
platform_config[CONF_NAME] = f"{platform_config[CONF_TYPE]} sensor".capitalize()
yaml_config = yaml.dump(platform_config)
yaml_config = yaml_config.replace("\n", "\n ")
yaml_config = "```yaml\nsensor:\n - platform: group\n " + yaml_config + "\n```"
async_create_issue(
hass,
DOMAIN,
"yaml_deprecated",
breaks_in_ha_version="2026.12.0",
is_fixable=False,
severity=IssueSeverity.WARNING,
learn_more_url="https://www.home-assistant.io/integrations/group/",
translation_key="yaml_deprecated",
translation_placeholders={"yaml_config": yaml_config},
)
@@ -117,6 +116,7 @@ async def async_setup_platform(
unique_id = config.get(CONF_UNIQUE_ID)
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await yaml_deprecation_notice(hass, config)
async_add_entities(
[MinMaxSensor(entity_ids, name, sensor_type, round_digits, unique_id)]
@@ -1,5 +1,8 @@
{
"config": {
"abort": {
"migrated_to_groups": "The min/max integration has been migrated to use groups. Please use the group integration instead."
},
"step": {
"user": {
"data": {
@@ -16,6 +19,12 @@
}
}
},
"issues": {
"yaml_deprecated": {
"description": "The min/max integration has been migrated to use group sensor.\n\nReplace your Min/MaxYAML configuration with this converted configuration:\n{yaml_config}\n\nTo use the new configuration and replace your sensor with a group sensor, restart your Home Assistant.\n\nGroup sensors have more configuration possibilities, refer to the documentation by clicking on learn more.",
"title": "Min/Max YAML configuration is deprecated"
}
},
"options": {
"step": {
"init": {
@@ -0,0 +1,26 @@
# To be removed
# min_max
sensor:
- platform: min_max
entity_ids:
- sensor.kitchen_temperature
- sensor.living_room_temperature
- sensor.office_temperature
type: max
name: Test
round_digits: 2 # Not exist in groups
unique_id: something_unique
# group
- platform: group
entities: # from entity_ids
- sensor.kitchen_temperature
- sensor.living_room_temperature
- sensor.office_temperature
type: max
name: Test
unique_id: something_unique
ignore_non_numeric: false # Not exist in min_max
unit_of_measurement: °C # Not exist in min_max
device_class: temperature # Not exist in min_max
state_class: measurement # Not exist in min_max