Initil after Upgrade
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.config_entries import ConfigFlowResult
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers import selector, translation
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -31,10 +30,23 @@ from custom_components.powercalc.discovery import (
|
||||
)
|
||||
from custom_components.powercalc.flow_helper.common import FlowType, PowercalcFormStep, Step
|
||||
from custom_components.powercalc.flow_helper.dynamic_field_builder import build_dynamic_field_schema
|
||||
from custom_components.powercalc.flow_helper.schema import SCHEMA_ENERGY_SENSOR_TOGGLE, SCHEMA_UTILITY_METER_TOGGLE, build_sub_profile_schema
|
||||
from custom_components.powercalc.helpers import collect_placeholders, iter_related_entity_placeholders, resolve_related_entity_placeholder
|
||||
from custom_components.powercalc.flow_helper.schema import (
|
||||
SCHEMA_ENERGY_SENSOR_TOGGLE,
|
||||
SCHEMA_UTILITY_METER_TOGGLE,
|
||||
build_sub_profile_schema,
|
||||
)
|
||||
from custom_components.powercalc.helpers import (
|
||||
collect_placeholders,
|
||||
iter_related_entity_placeholders,
|
||||
resolve_related_entity_placeholder,
|
||||
)
|
||||
from custom_components.powercalc.power_profile.library import ModelInfo, ProfileLibrary
|
||||
from custom_components.powercalc.power_profile.power_profile import DEVICE_TYPE_DOMAIN, DOMAIN_DEVICE_TYPE_MAPPING, DiscoveryBy, PowerProfile
|
||||
from custom_components.powercalc.power_profile.power_profile import (
|
||||
DEVICE_TYPE_DOMAIN,
|
||||
DOMAIN_DEVICE_TYPE_MAPPING,
|
||||
DiscoveryBy,
|
||||
PowerProfile,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from custom_components.powercalc.config_flow import PowercalcCommonFlow, PowercalcConfigFlow, PowercalcOptionsFlow
|
||||
@@ -67,7 +79,7 @@ class LibraryFlow:
|
||||
async def async_step_manufacturer(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
"""Ask the user to select the manufacturer."""
|
||||
|
||||
async def _create_schema() -> vol.Schema:
|
||||
@@ -82,7 +94,10 @@ class LibraryFlow:
|
||||
]
|
||||
return vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_MANUFACTURER, default=self.flow.sensor_config.get(CONF_MANUFACTURER)): selector.SelectSelector(
|
||||
vol.Required(
|
||||
CONF_MANUFACTURER,
|
||||
default=self.flow.sensor_config.get(CONF_MANUFACTURER),
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=manufacturers,
|
||||
mode=selector.SelectSelectorMode.DROPDOWN,
|
||||
@@ -104,7 +119,7 @@ class LibraryFlow:
|
||||
async def async_step_model(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
"""Ask the user to select the model."""
|
||||
|
||||
def _build_model_label(model_id: str, model_name: str) -> str:
|
||||
@@ -139,10 +154,18 @@ class LibraryFlow:
|
||||
self._get_library_discovery_by(),
|
||||
)
|
||||
]
|
||||
model = self.flow.selected_profile.model if self.flow.selected_profile else self.flow.sensor_config.get(CONF_MODEL)
|
||||
model = (
|
||||
self.flow.selected_profile.model
|
||||
if self.flow.selected_profile
|
||||
else self.flow.sensor_config.get(CONF_MODEL)
|
||||
)
|
||||
return vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_MODEL, description={"suggested_value": model}, default=model): selector.SelectSelector(
|
||||
vol.Required(
|
||||
CONF_MODEL,
|
||||
description={"suggested_value": model},
|
||||
default=model,
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=models,
|
||||
mode=selector.SelectSelectorMode.DROPDOWN,
|
||||
@@ -162,26 +185,29 @@ class LibraryFlow:
|
||||
user_input,
|
||||
)
|
||||
|
||||
async def async_step_post_library(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
async def async_step_post_library(self, _: dict[str, Any] | None = None) -> ConfigFlowResult:
|
||||
"""
|
||||
Handles the logic after the user either selected manufacturer/model himself or confirmed autodiscovered.
|
||||
Forwards to the next step in the flow.
|
||||
"""
|
||||
if not self.flow.selected_profile:
|
||||
return self.flow.async_abort(reason="model_not_supported") # type:ignore # pragma: no cover
|
||||
return self.flow.async_abort(reason="model_not_supported") # pragma: no cover
|
||||
|
||||
if Step.LIBRARY_CUSTOM_FIELDS not in self.flow.handled_steps and self.flow.selected_profile.has_custom_fields:
|
||||
return await self.async_step_library_custom_fields()
|
||||
|
||||
if Step.AVAILABILITY_ENTITY not in self.flow.handled_steps and self.flow.selected_profile.discovery_by == DiscoveryBy.DEVICE:
|
||||
if (
|
||||
Step.AVAILABILITY_ENTITY not in self.flow.handled_steps
|
||||
and self.flow.selected_profile.discovery_by == DiscoveryBy.DEVICE
|
||||
):
|
||||
result = await self.async_step_availability_entity()
|
||||
if result:
|
||||
return result
|
||||
|
||||
if Step.SUB_PROFILE not in self.flow.handled_steps and await self.flow.selected_profile.requires_manual_sub_profile_selection:
|
||||
if (
|
||||
Step.SUB_PROFILE not in self.flow.handled_steps
|
||||
and await self.flow.selected_profile.requires_manual_sub_profile_selection
|
||||
):
|
||||
return await self.async_step_sub_profile()
|
||||
|
||||
if (
|
||||
@@ -191,21 +217,26 @@ class LibraryFlow:
|
||||
):
|
||||
return await self.async_step_smart_switch()
|
||||
|
||||
if Step.FIXED not in self.flow.handled_steps and self.flow.selected_profile.needs_fixed_config: # pragma: no cover
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_fixed() # type:ignore
|
||||
if (
|
||||
Step.FIXED not in self.flow.handled_steps and self.flow.selected_profile.needs_fixed_config
|
||||
): # pragma: no cover
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_fixed() # type: ignore[no-any-return]
|
||||
|
||||
if Step.LINEAR not in self.flow.handled_steps and self.flow.selected_profile.needs_linear_config:
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_linear() # type:ignore
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_linear() # type: ignore[no-any-return]
|
||||
|
||||
if Step.MULTI_SWITCH not in self.flow.handled_steps and self.flow.selected_profile.calculation_strategy == CalculationStrategy.MULTI_SWITCH:
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_multi_switch() # type:ignore
|
||||
if (
|
||||
Step.MULTI_SWITCH not in self.flow.handled_steps
|
||||
and self.flow.selected_profile.calculation_strategy == CalculationStrategy.MULTI_SWITCH
|
||||
):
|
||||
return await self.flow.flow_handlers[FlowType.VIRTUAL_POWER].async_step_multi_switch() # type: ignore[no-any-return]
|
||||
|
||||
return await self.flow.flow_handlers[FlowType.GROUP].async_step_assign_groups() # type:ignore
|
||||
return await self.flow.flow_handlers[FlowType.GROUP].async_step_assign_groups() # type: ignore[no-any-return]
|
||||
|
||||
async def async_step_library_custom_fields(self, user_input: dict[str, Any] | None = None) -> FlowResult:
|
||||
async def async_step_library_custom_fields(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
|
||||
"""Handle the flow for custom fields."""
|
||||
|
||||
async def _process_user_input(user_input: dict[str, Any]) -> dict[str, Any]:
|
||||
def _process_user_input(user_input: dict[str, Any]) -> dict[str, Any]:
|
||||
return {CONF_VARIABLES: user_input}
|
||||
|
||||
form_kwarg: dict[str, Any] | None = None
|
||||
@@ -234,11 +265,11 @@ class LibraryFlow:
|
||||
async def async_step_sub_profile(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the flow for sub profile selection."""
|
||||
assert self.flow.selected_profile is not None
|
||||
|
||||
async def _validate(user_input: dict[str, Any]) -> dict[str, str]:
|
||||
def _validate(user_input: dict[str, Any]) -> dict[str, str]:
|
||||
return {CONF_MODEL: f"{self.flow.sensor_config.get(CONF_MODEL)}/{user_input.get(CONF_SUB_PROFILE)}"}
|
||||
|
||||
library = await ProfileLibrary.factory(self.flow.hass)
|
||||
@@ -254,7 +285,11 @@ class LibraryFlow:
|
||||
if remarks:
|
||||
remarks = "\n\n" + remarks
|
||||
|
||||
step = Step.SUB_PROFILE_PER_DEVICE if self.flow.selected_profile.discovery_by == DiscoveryBy.DEVICE else Step.SUB_PROFILE
|
||||
step = (
|
||||
Step.SUB_PROFILE_PER_DEVICE
|
||||
if self.flow.selected_profile.discovery_by == DiscoveryBy.DEVICE
|
||||
else Step.SUB_PROFILE
|
||||
)
|
||||
|
||||
return await self.flow.handle_form_step(
|
||||
PowercalcFormStep(
|
||||
@@ -275,16 +310,16 @@ class LibraryFlow:
|
||||
async def async_step_sub_profile_per_device(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
return await self.async_step_sub_profile(user_input)
|
||||
|
||||
async def async_step_smart_switch(self, user_input: dict[str, Any] | None = None) -> FlowResult:
|
||||
async def async_step_smart_switch(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
|
||||
"""Asks the user for the power of connect appliance for the smart switch."""
|
||||
|
||||
if self.flow.selected_profile and not self.flow.selected_profile.needs_fixed_config:
|
||||
return self.flow.persist_config_entry()
|
||||
|
||||
async def _validate(user_input: dict[str, Any]) -> dict[str, Any]:
|
||||
def _validate(user_input: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
CONF_SELF_USAGE_INCLUDED: user_input.get(CONF_SELF_USAGE_INCLUDED),
|
||||
CONF_MODE: CalculationStrategy.FIXED,
|
||||
@@ -303,7 +338,7 @@ class LibraryFlow:
|
||||
user_input,
|
||||
)
|
||||
|
||||
async def async_step_availability_entity(self, user_input: dict[str, Any] | None = None) -> FlowResult | None:
|
||||
async def async_step_availability_entity(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult | None:
|
||||
"""Handle the flow for availability entity."""
|
||||
# Auto-resolve availability entity from profile placeholders
|
||||
auto_entity = self._resolve_availability_entity()
|
||||
@@ -377,7 +412,7 @@ class LibraryConfigFlow(LibraryFlow):
|
||||
async def async_step_library_multi_profile(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult | ConfigFlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
"""This step gets executed when multiple profiles are found for the source entity."""
|
||||
if user_input is not None:
|
||||
selected_model: str = user_input.get(CONF_MODEL) # type: ignore
|
||||
@@ -426,7 +461,7 @@ class LibraryConfigFlow(LibraryFlow):
|
||||
async def async_step_library(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> FlowResult:
|
||||
) -> ConfigFlowResult:
|
||||
"""Try to autodiscover manufacturer/model first.
|
||||
Ask the user to confirm this or forward to manual library selection.
|
||||
"""
|
||||
@@ -439,7 +474,7 @@ class LibraryConfigFlow(LibraryFlow):
|
||||
|
||||
return self._show_autodiscovered_profile_form()
|
||||
|
||||
async def _handle_library_confirmation(self, user_input: dict[str, Any]) -> FlowResult:
|
||||
async def _handle_library_confirmation(self, user_input: dict[str, Any]) -> ConfigFlowResult:
|
||||
"""Handle the user's response to an autodiscovered library profile."""
|
||||
if not user_input.get(CONF_CONFIRM_AUTODISCOVERED_MODEL) or not self.flow.selected_profile:
|
||||
return await self.async_step_manufacturer()
|
||||
@@ -454,27 +489,31 @@ class LibraryConfigFlow(LibraryFlow):
|
||||
|
||||
async def _async_autodiscover_profile(self) -> None:
|
||||
"""Populate the selected profile from the source entity when possible."""
|
||||
if not self.flow.source_entity or not self.flow.source_entity.entity_entry or self.flow.selected_profile is not None:
|
||||
if (
|
||||
not self.flow.source_entity
|
||||
or not self.flow.source_entity.entity_entry
|
||||
or self.flow.selected_profile is not None
|
||||
):
|
||||
return
|
||||
|
||||
self.flow.selected_profile = await get_power_profile_by_source_entity(self.flow.hass, self.flow.source_entity)
|
||||
if self.flow.selected_profile is None and self.flow.source_entity.device_entry:
|
||||
self.flow.selected_profile = await get_power_profile_by_source_device(self.flow.hass, self.flow.source_entity)
|
||||
self.flow.selected_profile = await get_power_profile_by_source_device(
|
||||
self.flow.hass,
|
||||
self.flow.source_entity,
|
||||
)
|
||||
|
||||
def _show_autodiscovered_profile_form(self) -> FlowResult:
|
||||
def _show_autodiscovered_profile_form(self) -> ConfigFlowResult:
|
||||
"""Show the confirmation form for an autodiscovered library profile."""
|
||||
profile = self.flow.selected_profile
|
||||
assert profile is not None
|
||||
|
||||
return cast(
|
||||
FlowResult,
|
||||
self.flow.async_show_form(
|
||||
step_id=Step.LIBRARY,
|
||||
description_placeholders=self._build_library_description_placeholders(profile),
|
||||
data_schema=SCHEMA_POWER_AUTODISCOVERED,
|
||||
errors={},
|
||||
last_step=False,
|
||||
),
|
||||
return self.flow.async_show_form(
|
||||
step_id=Step.LIBRARY,
|
||||
description_placeholders=self._build_library_description_placeholders(profile),
|
||||
data_schema=SCHEMA_POWER_AUTODISCOVERED,
|
||||
errors={},
|
||||
last_step=False,
|
||||
)
|
||||
|
||||
def _build_library_description_placeholders(self, profile: PowerProfile) -> dict[str, Any]:
|
||||
@@ -499,9 +538,19 @@ class LibraryConfigFlow(LibraryFlow):
|
||||
|
||||
def _get_profile_source(self, profile: PowerProfile) -> str:
|
||||
"""Build the autodiscovery source description."""
|
||||
translations = translation.async_get_cached_translations(self.flow.hass, self.flow.hass.config.language, "common", DOMAIN)
|
||||
if profile.discovery_by == DiscoveryBy.DEVICE and self.flow.source_entity and self.flow.source_entity.device_entry:
|
||||
return f"{translations.get(f'component.{DOMAIN}.common.source_device')}: {self.flow.source_entity.device_entry.name}"
|
||||
translations = translation.async_get_cached_translations(
|
||||
self.flow.hass,
|
||||
self.flow.hass.config.language,
|
||||
"common",
|
||||
DOMAIN,
|
||||
)
|
||||
if (
|
||||
profile.discovery_by == DiscoveryBy.DEVICE
|
||||
and self.flow.source_entity
|
||||
and self.flow.source_entity.device_entry
|
||||
):
|
||||
label = translations.get(f"component.{DOMAIN}.common.source_device")
|
||||
return f"{label}: {self.flow.source_entity.device_entry.name}"
|
||||
|
||||
return f"{translations.get(f'component.{DOMAIN}.common.source_entity')}: {self.flow.source_entity_id}"
|
||||
|
||||
@@ -537,7 +586,7 @@ class LibraryOptionsFlow(LibraryFlow):
|
||||
super().__init__(flow)
|
||||
self.flow: PowercalcOptionsFlow = flow
|
||||
|
||||
async def async_step_library_options(self, user_input: dict[str, Any] | None = None) -> FlowResult:
|
||||
async def async_step_library_options(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
|
||||
"""Handle the basic options flow."""
|
||||
self.flow.is_library_flow = True
|
||||
self.flow.selected_sub_profile = self.flow.selected_profile.sub_profile # type: ignore
|
||||
|
||||
Reference in New Issue
Block a user