169 lines
5.8 KiB
Python
169 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from homeassistant.config_entries import ConfigFlowResult
|
|
from homeassistant.const import (
|
|
CONF_NAME,
|
|
CONF_UNIQUE_ID,
|
|
CONF_UNIT_OF_MEASUREMENT,
|
|
UnitOfEnergy,
|
|
UnitOfPower,
|
|
UnitOfTime,
|
|
)
|
|
from homeassistant.helpers import selector
|
|
from homeassistant.helpers.schema_config_entry_flow import SchemaFlowError
|
|
import voluptuous as vol
|
|
|
|
from custom_components.powercalc.const import (
|
|
CONF_CREATE_UTILITY_METERS,
|
|
CONF_DAILY_ENERGY_VALUE,
|
|
CONF_DAILY_FIXED_ENERGY,
|
|
CONF_GROUP,
|
|
CONF_ON_TIME,
|
|
CONF_UPDATE_FREQUENCY,
|
|
CONF_VALUE,
|
|
CONF_VALUE_TEMPLATE,
|
|
SensorType,
|
|
)
|
|
from custom_components.powercalc.flow_helper.common import (
|
|
PowercalcFormStep,
|
|
Step,
|
|
fill_schema_defaults,
|
|
unwrap_choose_selector,
|
|
wrap_choose_selector,
|
|
)
|
|
from custom_components.powercalc.flow_helper.schema import SCHEMA_UTILITY_METER_TOGGLE
|
|
from custom_components.powercalc.sensors.daily_energy import DEFAULT_DAILY_UPDATE_FREQUENCY
|
|
|
|
if TYPE_CHECKING:
|
|
from custom_components.powercalc.config_flow import PowercalcConfigFlow, PowercalcOptionsFlow
|
|
|
|
DAILY_ENERGY_VALUE_CHOICES: dict[str, list[str] | str] = {
|
|
CONF_VALUE_TEMPLATE: CONF_VALUE_TEMPLATE,
|
|
CONF_VALUE: CONF_VALUE,
|
|
}
|
|
|
|
SCHEMA_DAILY_ENERGY_OPTIONS = vol.Schema(
|
|
{
|
|
vol.Optional(CONF_DAILY_ENERGY_VALUE): selector.ChooseSelector(
|
|
selector.ChooseSelectorConfig(
|
|
choices={
|
|
CONF_VALUE: {"selector": {"number": {"mode": "box", "step": "any"}}},
|
|
CONF_VALUE_TEMPLATE: {"selector": {"template": {}}},
|
|
},
|
|
translation_key=CONF_DAILY_ENERGY_VALUE,
|
|
),
|
|
),
|
|
vol.Optional(
|
|
CONF_UNIT_OF_MEASUREMENT,
|
|
default=UnitOfEnergy.KILO_WATT_HOUR,
|
|
): vol.In(
|
|
[UnitOfEnergy.KILO_WATT_HOUR, UnitOfPower.WATT],
|
|
),
|
|
vol.Optional(CONF_ON_TIME): selector.DurationSelector(
|
|
selector.DurationSelectorConfig(enable_day=False),
|
|
),
|
|
vol.Optional(
|
|
CONF_UPDATE_FREQUENCY,
|
|
default=DEFAULT_DAILY_UPDATE_FREQUENCY,
|
|
): selector.NumberSelector(
|
|
selector.NumberSelectorConfig(
|
|
min=10,
|
|
unit_of_measurement=UnitOfTime.SECONDS,
|
|
mode=selector.NumberSelectorMode.BOX,
|
|
),
|
|
),
|
|
},
|
|
)
|
|
SCHEMA_DAILY_ENERGY = vol.Schema(
|
|
{
|
|
vol.Required(CONF_NAME): selector.TextSelector(),
|
|
**SCHEMA_UTILITY_METER_TOGGLE.schema,
|
|
},
|
|
).extend(SCHEMA_DAILY_ENERGY_OPTIONS.schema)
|
|
|
|
|
|
def daily_energy_choice_key_from_validated_value(value: object) -> str:
|
|
"""Infer the daily energy config key from a validated ChooseSelector value."""
|
|
return CONF_VALUE_TEMPLATE if isinstance(value, str) else CONF_VALUE
|
|
|
|
|
|
def build_daily_energy_config(user_input: dict[str, Any], schema: vol.Schema) -> dict[str, Any]:
|
|
"""Build the config under daily_energy: key."""
|
|
user_input = unwrap_choose_selector(
|
|
dict(user_input),
|
|
CONF_DAILY_ENERGY_VALUE,
|
|
daily_energy_choice_key_from_validated_value,
|
|
)
|
|
config: dict[str, Any] = {
|
|
CONF_DAILY_FIXED_ENERGY: {},
|
|
}
|
|
schema_keys = {key.schema if isinstance(key, vol.Marker) else key for key in schema.schema}
|
|
schema_keys.discard(CONF_DAILY_ENERGY_VALUE)
|
|
schema_keys |= {CONF_VALUE, CONF_VALUE_TEMPLATE}
|
|
for key, val in user_input.items():
|
|
if key in schema_keys and val is not None:
|
|
if key in {CONF_CREATE_UTILITY_METERS, CONF_GROUP, CONF_NAME, CONF_UNIQUE_ID}:
|
|
config[str(key)] = val
|
|
continue
|
|
|
|
config[CONF_DAILY_FIXED_ENERGY][str(key)] = val
|
|
return config
|
|
|
|
|
|
class DailyEnergyConfigFlow:
|
|
def __init__(self, flow: PowercalcConfigFlow) -> None:
|
|
self.flow: PowercalcConfigFlow = flow
|
|
|
|
async def async_step_daily_energy(
|
|
self,
|
|
user_input: dict[str, Any] | None = None,
|
|
) -> ConfigFlowResult:
|
|
"""Handle the flow for daily energy sensor."""
|
|
self.flow.selected_sensor_type = SensorType.DAILY_ENERGY
|
|
|
|
def _validate(user_input: dict[str, Any]) -> dict[str, Any]:
|
|
unwrapped = unwrap_choose_selector(
|
|
dict(user_input),
|
|
CONF_DAILY_ENERGY_VALUE,
|
|
daily_energy_choice_key_from_validated_value,
|
|
)
|
|
if CONF_VALUE not in unwrapped and CONF_VALUE_TEMPLATE not in unwrapped:
|
|
raise SchemaFlowError("daily_energy_mandatory")
|
|
return build_daily_energy_config(unwrapped, SCHEMA_DAILY_ENERGY)
|
|
|
|
return await self.flow.handle_form_step(
|
|
PowercalcFormStep(
|
|
step=Step.DAILY_ENERGY,
|
|
schema=SCHEMA_DAILY_ENERGY,
|
|
validate_user_input=_validate,
|
|
next_step=Step.ASSIGN_GROUPS,
|
|
),
|
|
user_input,
|
|
)
|
|
|
|
|
|
class DailyEnergyOptionsFlow:
|
|
def __init__(self, flow: PowercalcOptionsFlow) -> None:
|
|
self.flow: PowercalcOptionsFlow = flow
|
|
|
|
async def async_step_daily_energy(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
|
|
"""Handle the daily energy options flow."""
|
|
form_data = wrap_choose_selector(
|
|
dict(self.flow.sensor_config[CONF_DAILY_FIXED_ENERGY]),
|
|
CONF_DAILY_ENERGY_VALUE,
|
|
DAILY_ENERGY_VALUE_CHOICES,
|
|
)
|
|
schema = fill_schema_defaults(
|
|
SCHEMA_DAILY_ENERGY_OPTIONS,
|
|
form_data,
|
|
)
|
|
if user_input is not None:
|
|
user_input = unwrap_choose_selector(
|
|
dict(user_input),
|
|
CONF_DAILY_ENERGY_VALUE,
|
|
daily_energy_choice_key_from_validated_value,
|
|
)
|
|
return await self.flow.async_handle_options_step(user_input, schema, Step.DAILY_ENERGY)
|