mirror of
https://github.com/home-assistant/core.git
synced 2026-10-06 06:15:47 -04:00
Deprecate min_max and migrate to group sensor
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user