Add configurable optimizer area sensors

This commit is contained in:
2026-08-10 12:25:43 +02:00
parent dc6b2dc71a
commit 02bb4a831e
16 changed files with 643 additions and 21 deletions
@@ -5,10 +5,16 @@ from __future__ import annotations
from typing import Any, override
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import (
ConfigEntry,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.selector import ObjectSelector
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .api import (
@@ -18,7 +24,14 @@ from .api import (
SolarEdgeOptimizerInvalidResponseError,
normalize_base_url,
)
from .areas import (
AreaMappingError,
default_area_mapping,
parse_area_mapping,
serialize_area_mapping,
)
from .const import (
CONF_AREA_MAPPING,
CONF_SCAN_INTERVAL,
CONFIG_ENTRY_VERSION,
DEFAULT_PORT,
@@ -64,6 +77,13 @@ class SolarEdgeOptimizersConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = CONFIG_ENTRY_VERSION
@staticmethod
@callback
@override
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow:
"""Return the options flow."""
return SolarEdgeOptimizerOptionsFlow()
def __init__(self) -> None:
"""Initialize the flow."""
self._discovered_url: str | None = None
@@ -193,3 +213,59 @@ class SolarEdgeOptimizersConfigFlow(ConfigFlow, domain=DOMAIN):
except Exception: # noqa: BLE001
LOGGER.exception("Unexpected exception while validating configuration")
return {"base": "unknown"}
class SolarEdgeOptimizerOptionsFlow(OptionsFlow):
"""Configure optimizer area mappings."""
@override
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Manage area mapping options."""
coordinator = self.config_entry.runtime_data
available_optimizer_ids = {
optimizer.optimizer_id
for optimizer in coordinator.data.optimizers
if optimizer.optimizer_id is not None
}
errors: dict[str, str] = {}
if user_input is not None:
try:
mapping = parse_area_mapping(
user_input.get(CONF_AREA_MAPPING, {}),
available_optimizer_ids,
)
except AreaMappingError as err:
errors["base"] = err.translation_key
else:
return self.async_create_entry(
data={
**self.config_entry.options,
CONF_AREA_MAPPING: serialize_area_mapping(mapping),
}
)
site_id = coordinator.data.site_id
current_mapping = self.config_entry.options.get(
CONF_AREA_MAPPING, default_area_mapping(site_id)
)
if user_input is not None:
current_mapping = user_input.get(CONF_AREA_MAPPING, {})
return self.async_show_form(
step_id="init",
data_schema=vol.Schema(
{
vol.Required(
CONF_AREA_MAPPING,
default=current_mapping,
): ObjectSelector()
}
),
errors=errors,
description_placeholders={
"optimizer_ids": ", ".join(sorted(available_optimizer_ids))
},
)