151 lines
4.5 KiB
Python
151 lines
4.5 KiB
Python
"""Spook - Your homie."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from functools import partial
|
|
from typing import TYPE_CHECKING, Any, cast
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, Platform
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers import entity_registry as er, selector
|
|
from homeassistant.helpers.schema_config_entry_flow import (
|
|
SchemaCommonFlowHandler,
|
|
SchemaConfigFlowHandler,
|
|
SchemaFlowFormStep,
|
|
SchemaFlowMenuStep,
|
|
SchemaOptionsFlowHandler,
|
|
entity_selector_without_own_entities,
|
|
)
|
|
|
|
from .const import CONF_HIDE_SOURCE, DOMAIN, PLATFORMS
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable, Coroutine, Mapping
|
|
|
|
|
|
async def options_schema(
|
|
domain: str | list[str],
|
|
handler: SchemaCommonFlowHandler,
|
|
) -> vol.Schema:
|
|
"""Generate options schema."""
|
|
return vol.Schema(
|
|
{
|
|
vol.Required(CONF_ENTITY_ID): entity_selector_without_own_entities(
|
|
cast(SchemaOptionsFlowHandler, handler.parent_handler),
|
|
selector.EntitySelectorConfig(domain=domain),
|
|
),
|
|
vol.Required(CONF_HIDE_SOURCE, default=False): selector.BooleanSelector(),
|
|
},
|
|
)
|
|
|
|
|
|
def config_schema(domain: str | list[str]) -> vol.Schema:
|
|
"""Generate config schema."""
|
|
return vol.Schema(
|
|
{
|
|
vol.Required(CONF_NAME): selector.TextSelector(),
|
|
vol.Required(CONF_ENTITY_ID): selector.EntitySelector(
|
|
selector.EntitySelectorConfig(domain=domain),
|
|
),
|
|
vol.Required(CONF_HIDE_SOURCE, default=False): selector.BooleanSelector(),
|
|
},
|
|
)
|
|
|
|
|
|
async def choose_options_step(options: dict[str, Any]) -> str:
|
|
"""Return next step_id for options flow according to inverse_type."""
|
|
return cast(str, options["inverse_type"])
|
|
|
|
|
|
def set_inverse_type(
|
|
inverse_type: str,
|
|
) -> Callable[
|
|
[SchemaCommonFlowHandler, dict[str, Any]],
|
|
Coroutine[Any, Any, dict[str, Any]],
|
|
]:
|
|
"""Set inverse type."""
|
|
|
|
async def _set_inverse_type(
|
|
_: SchemaCommonFlowHandler,
|
|
user_input: dict[str, Any],
|
|
) -> dict[str, Any]:
|
|
"""Add inverse type to user input."""
|
|
return {"inverse_type": inverse_type, **user_input}
|
|
|
|
return _set_inverse_type
|
|
|
|
|
|
CONFIG_FLOW = {
|
|
"user": SchemaFlowMenuStep(PLATFORMS),
|
|
Platform.BINARY_SENSOR: SchemaFlowFormStep(
|
|
config_schema(Platform.BINARY_SENSOR),
|
|
validate_user_input=set_inverse_type(Platform.BINARY_SENSOR),
|
|
),
|
|
Platform.SWITCH: SchemaFlowFormStep(
|
|
config_schema(Platform.SWITCH),
|
|
validate_user_input=set_inverse_type(Platform.SWITCH),
|
|
),
|
|
}
|
|
|
|
|
|
OPTIONS_FLOW = {
|
|
"init": SchemaFlowFormStep(next_step=choose_options_step),
|
|
Platform.BINARY_SENSOR: SchemaFlowFormStep(
|
|
partial(options_schema, Platform.BINARY_SENSOR),
|
|
),
|
|
Platform.SWITCH: SchemaFlowFormStep(partial(options_schema, Platform.SWITCH)),
|
|
}
|
|
|
|
|
|
class SpookInverseConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
|
|
"""Handle config flow for Spook inverse helper."""
|
|
|
|
VERSION = 1
|
|
MINOR_VERSION = 2
|
|
|
|
config_flow = CONFIG_FLOW
|
|
options_flow = OPTIONS_FLOW
|
|
|
|
@callback
|
|
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 ""
|
|
|
|
@callback
|
|
def async_config_flow_finished(self, options: Mapping[str, Any]) -> None:
|
|
"""Hide the source entity if requested."""
|
|
if options[CONF_HIDE_SOURCE]:
|
|
_async_hide_source(
|
|
self.hass,
|
|
options[CONF_ENTITY_ID],
|
|
er.RegistryEntryHider.INTEGRATION,
|
|
)
|
|
|
|
@callback
|
|
@staticmethod
|
|
def async_options_flow_finished(
|
|
hass: HomeAssistant,
|
|
options: Mapping[str, Any],
|
|
) -> None:
|
|
"""Hide or unhide the source entity as requested."""
|
|
hidden_by = (
|
|
er.RegistryEntryHider.INTEGRATION if options[CONF_HIDE_SOURCE] else None
|
|
)
|
|
_async_hide_source(hass, options[CONF_ENTITY_ID], hidden_by)
|
|
|
|
|
|
def _async_hide_source(
|
|
hass: HomeAssistant,
|
|
source_entity_id: str,
|
|
hidden_by: er.RegistryEntryHider | None,
|
|
) -> None:
|
|
"""Hide or unhide inverse source."""
|
|
registry = er.async_get(hass)
|
|
if not (entity_id := er.async_resolve_entity_id(registry, source_entity_id)):
|
|
return
|
|
if entity_id not in registry.entities:
|
|
return
|
|
registry.async_update_entity(entity_id, hidden_by=hidden_by)
|