Compare commits
2 commits
dev
...
deprecate-
Author | SHA1 | Date | |
---|---|---|---|
|
bfc03b633a | ||
|
896b2c8779 |
4 changed files with 126 additions and 44 deletions
|
@ -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] = {}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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%]",
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue