Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
G Johansson
bfc03b633a min_max config flow 2024-01-03 19:43:39 +00:00
G Johansson
896b2c8779 Start deprecation min_max 2024-01-03 19:31:07 +00:00
4 changed files with 126 additions and 44 deletions

View file

@ -1,6 +1,7 @@
"""Config flow for Group integration.""" """Config flow for Group integration."""
from __future__ import annotations from __future__ import annotations
from collections import ChainMap
from collections.abc import Callable, Coroutine, Mapping from collections.abc import Callable, Coroutine, Mapping
from functools import partial from functools import partial
from typing import Any, cast from typing import Any, cast
@ -15,6 +16,7 @@ from homeassistant.helpers import entity_registry as er, selector
from homeassistant.helpers.schema_config_entry_flow import ( from homeassistant.helpers.schema_config_entry_flow import (
SchemaCommonFlowHandler, SchemaCommonFlowHandler,
SchemaConfigFlowHandler, SchemaConfigFlowHandler,
SchemaFlowError,
SchemaFlowFormStep, SchemaFlowFormStep,
SchemaFlowMenuStep, SchemaFlowMenuStep,
SchemaOptionsFlowHandler, SchemaOptionsFlowHandler,
@ -45,6 +47,38 @@ _STATISTIC_MEASURES = [
] ]
def import_sensor() -> (
Callable[
[SchemaCommonFlowHandler, dict[str, Any]], Coroutine[Any, Any, dict[str, Any]]
]
):
"""Import sensor."""
# Missing Make sure the new group config entry adopts the existing min_max entities by changing the config entry and unique_id
# Missing Remove the min_max config entry
async def _set_group_type(
handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
) -> dict[str, Any]:
"""Add group type to user input and test not imported."""
hass = handler.parent_handler.hass
entries = hass.config_entries.async_entries(DOMAIN)
match_dict = {"group_type": "sensor", **user_input}
for entry in entries:
if all(
item
in ChainMap(
entry.options, # type: ignore[arg-type]
entry.data, # type: ignore[arg-type]
).items()
for item in match_dict.items()
):
raise SchemaFlowError("already_configured")
return {"group_type": "sensor", **user_input}
return _set_group_type
async def basic_group_options_schema( async def basic_group_options_schema(
domain: str | list[str], handler: SchemaCommonFlowHandler | None domain: str | list[str], handler: SchemaCommonFlowHandler | None
) -> vol.Schema: ) -> vol.Schema:
@ -263,6 +297,10 @@ OPTIONS_FLOW = {
partial(light_switch_options_schema, "switch"), partial(light_switch_options_schema, "switch"),
preview="group", preview="group",
), ),
"import": SchemaFlowFormStep(
SENSOR_CONFIG_SCHEMA,
validate_user_input=import_sensor(),
),
} }
PREVIEW_OPTIONS_SCHEMA: dict[str, vol.Schema] = {} PREVIEW_OPTIONS_SCHEMA: dict[str, vol.Schema] = {}

View file

@ -6,62 +6,24 @@ from typing import Any, cast
import voluptuous as vol import voluptuous as vol
from homeassistant.components.input_number import DOMAIN as INPUT_NUMBER_DOMAIN from homeassistant.core import callback
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN from homeassistant.data_entry_flow import AbortFlow
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import CONF_TYPE
from homeassistant.helpers import selector from homeassistant.helpers import selector
from homeassistant.helpers.schema_config_entry_flow import ( from homeassistant.helpers.schema_config_entry_flow import (
SchemaConfigFlowHandler, SchemaConfigFlowHandler,
SchemaFlowFormStep, SchemaFlowFormStep,
) )
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN from .const import DOMAIN
_STATISTIC_MEASURES = [
"min",
"max",
"mean",
"median",
"last",
"range",
"sum",
]
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
),
),
}
)
CONFIG_SCHEMA = vol.Schema( CONFIG_SCHEMA = vol.Schema(
{ {
vol.Required("name"): selector.TextSelector(), vol.Required("name"): selector.TextSelector(),
} }
).extend(OPTIONS_SCHEMA.schema) )
CONFIG_FLOW = { CONFIG_FLOW = {
"user": SchemaFlowFormStep(CONFIG_SCHEMA), "user": SchemaFlowFormStep(vol.Schema({})),
}
OPTIONS_FLOW = {
"init": SchemaFlowFormStep(OPTIONS_SCHEMA),
} }
@ -69,8 +31,12 @@ class ConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
"""Handle a config or options flow for Min/Max.""" """Handle a config or options flow for Min/Max."""
config_flow = CONFIG_FLOW config_flow = CONFIG_FLOW
options_flow = OPTIONS_FLOW
def async_config_entry_title(self, options: Mapping[str, Any]) -> str: def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
"""Return config entry title.""" """Return config entry title."""
return cast(str, options["name"]) if "name" in options else "" return cast(str, options["name"]) if "name" in options else ""
@callback
def async_config_flow_finished(self, options: Mapping[str, Any]) -> None:
"""Abort the flow as it should not be setup."""
raise AbortFlow(reason="being_removed")

View file

@ -1,6 +1,9 @@
{ {
"title": "Combine the state of several sensors", "title": "Combine the state of several sensors",
"config": { "config": {
"abort": {
"being_removed": "Combine the state of several sensors ss being removed. Please configure a Group Sensor instead which provides this functionality."
},
"step": { "step": {
"user": { "user": {
"title": "[%key:component::min_max::title%]", "title": "[%key:component::min_max::title%]",

View file

@ -700,3 +700,78 @@ async def test_option_flow_sensor_preview_config_entry_removed(
msg = await client.receive_json() msg = await client.receive_json()
assert not msg["success"] assert not msg["success"]
assert msg["error"] == {"code": "home_assistant_error", "message": "Unknown error"} assert msg["error"] == {"code": "home_assistant_error", "message": "Unknown error"}
async def test_import(hass: HomeAssistant) -> None:
"""Test import config flow."""
members = ["sensor.one", "sensor.two"]
for member in members:
hass.states.async_set(member, "on", {})
with patch(
"homeassistant.components.group.async_setup_entry", wraps=async_setup_entry
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={
"ignore_non_numeric": False,
"entities": ["sensor.one", "sensor.two"],
"hide_members": False,
"type": "sum",
"name": "Sensor Group sum",
},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["title"] == "Sensor Group sum"
assert result["data"] == {}
assert result["options"] == {
"entities": members,
"group_type": "sensor",
"hide_members": False,
"name": "Sensor Group sum",
"ignore_non_numeric": False,
"type": "sum",
}
async def test_import_already_exist(hass: HomeAssistant) -> None:
"""Test import config flow."""
members = ["sensor.one", "sensor.two"]
for member in members:
hass.states.async_set(member, "on", {})
group_config_entry = MockConfigEntry(
data={},
domain=DOMAIN,
options={
"entities": members,
"group_type": "sensor",
"hide_members": False,
"ignore_non_numeric": False,
"type": "sum",
"name": "Sensor Group sum",
},
title="Sensor Group sum",
)
group_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={
"ignore_non_numeric": False,
"entities": members,
"hide_members": False,
"type": "sum",
"name": "Sensor Group sum",
},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "already_configured"}