diff --git a/custom_components/easee_solar_charging/config_flow.py b/custom_components/easee_solar_charging/config_flow.py index 7707be7..66e8779 100644 --- a/custom_components/easee_solar_charging/config_flow.py +++ b/custom_components/easee_solar_charging/config_flow.py @@ -3,7 +3,7 @@ from __future__ import annotations import voluptuous as vol from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult, OptionsFlow -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import device_registry as dr, selector from .const import ( @@ -18,34 +18,60 @@ from .const import ( EASEE_DOMAIN, ) -_NOTIFY_TARGET_SELECTOR = selector.TextSelector( - selector.TextSelectorConfig(type=selector.TextSelectorType.TEXT) +_STOP_GRACE_SELECTOR = selector.NumberSelector( + selector.NumberSelectorConfig( + min=1, max=60, step=1, unit_of_measurement="min", mode=selector.NumberSelectorMode.BOX + ) ) -STEP_USER_DATA_SCHEMA = vol.Schema( - { - vol.Required(CONF_SITE_ID): str, - vol.Required(CONF_SOLAR_EXCESS_SENSOR): selector.EntitySelector( - selector.EntitySelectorConfig(domain="sensor") - ), - vol.Required(CONF_DEVICE_ID): selector.DeviceSelector( - selector.DeviceSelectorConfig(integration="easee") - ), - vol.Optional(CONF_NOTIFY_TARGET): _NOTIFY_TARGET_SELECTOR, - } -) - -OPTIONS_SCHEMA = vol.Schema( - { - vol.Required(CONF_STOP_GRACE_MINUTES, default=DEFAULT_STOP_GRACE_MINUTES): selector.NumberSelector( - selector.NumberSelectorConfig(min=1, max=60, step=1, unit_of_measurement="min", mode=selector.NumberSelectorMode.BOX) - ), - vol.Optional(CONF_NOTIFY_TARGET): _NOTIFY_TARGET_SELECTOR, - } -) +_STATIC_USER_FIELDS = { + vol.Required(CONF_SITE_ID): str, + vol.Required(CONF_SOLAR_EXCESS_SENSOR): selector.EntitySelector( + selector.EntitySelectorConfig(domain="sensor") + ), + vol.Required(CONF_DEVICE_ID): selector.DeviceSelector( + selector.DeviceSelectorConfig(integration="easee") + ), +} -def _charger_serial_from_device(hass, device_id: str) -> str | None: +def _notify_services(hass: HomeAssistant) -> list[str]: + """Return sorted list of notify service names, excluding internal ones.""" + return sorted( + svc + for svc in hass.services.async_services().get("notify", {}) + if svc not in ("notify", "send_message", "reload") + ) + + +def _notify_selector(options: list[str]) -> selector.SelectSelector: + return selector.SelectSelector( + selector.SelectSelectorConfig( + options=options, + mode=selector.SelectSelectorMode.DROPDOWN, + custom_value=True, # allow typing a target not yet loaded + ) + ) + + +def _user_schema(hass: HomeAssistant) -> vol.Schema: + return vol.Schema({ + **_STATIC_USER_FIELDS, + vol.Optional(CONF_NOTIFY_TARGET): _notify_selector(_notify_services(hass)), + }) + + +def _options_schema(hass: HomeAssistant, current: dict) -> vol.Schema: + return vol.Schema({ + vol.Required( + CONF_STOP_GRACE_MINUTES, + default=current.get(CONF_STOP_GRACE_MINUTES, DEFAULT_STOP_GRACE_MINUTES), + ): _STOP_GRACE_SELECTOR, + vol.Optional(CONF_NOTIFY_TARGET): _notify_selector(_notify_services(hass)), + }) + + +def _charger_serial_from_device(hass: HomeAssistant, device_id: str) -> str | None: """Extract the Easee charger serial number from the device registry entry.""" registry = dr.async_get(hass) device = registry.async_get(device_id) @@ -89,7 +115,7 @@ class EaseeSolarChargingConfigFlow(ConfigFlow, domain=DOMAIN): return self.async_show_form( step_id="user", - data_schema=STEP_USER_DATA_SCHEMA, + data_schema=_user_schema(self.hass), errors=errors, ) @@ -102,7 +128,7 @@ class EaseeSolarChargingOptionsFlow(OptionsFlow): return self.async_show_form( step_id="init", data_schema=self.add_suggested_values_to_schema( - OPTIONS_SCHEMA, + _options_schema(self.hass, self.config_entry.options), self.config_entry.options, ), )