Compare commits

..

4 Commits

Author SHA1 Message Date
FigurinePanda43 732ff47036
Merge 58b9da9b80 into 5a1d04944e 2026-02-28 12:44:46 -05:00
SchiZzA 5a1d04944e
Bump version. 2026-02-28 18:43:18 +01:00
SchiZzA 30b88a0f13
Fix options flow and route switching after config updates
- Keep OptionsFlow state in sync by building defaults from entry data + options
- Store the config entry on the coordinator for consistent access
- Make route registry method-aware and switch handlers by url_path with
  awarness of POST/GET method.
- Fixed an issue, when on config update needs restart of HomeAssistant
  to reload integration.
2026-02-28 18:37:19 +01:00
SchiZzA 048bd6bd4c
Fix Windy credential validation for None/blank options
Normalize Windy station ID and password from config options and require both values before enabling Windy resend.
2026-02-26 19:33:36 +01:00
5 changed files with 37 additions and 40 deletions

View File

@ -52,6 +52,7 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
"""Init global updater."""
self.hass = hass
self.config = config
self.config_entry = config
self.windy = WindyPush(hass, config)
self.pocasi: PocasiPush = PocasiPush(hass, config)
super().__init__(hass, _LOGGER, name=DOMAIN)

View File

@ -40,9 +40,10 @@ class InvalidAuth(HomeAssistantError):
class ConfigOptionsFlowHandler(OptionsFlow):
"""Handle WeatherStation ConfigFlow."""
def __init__(self) -> None:
def __init__(self, config_entry) -> None:
"""Initialize flow."""
super().__init__()
self.config_entry = config_entry
self.windy_data: dict[str, Any] = {}
self.windy_data_schema = {}
@ -53,18 +54,15 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.pocasi_cz: dict[str, Any] = {}
self.pocasi_cz_schema = {}
@property
def config_entry(self):
return self.hass.config_entries.async_get_entry(self.handler)
async def _get_entry_data(self):
"""Get entry data."""
entry_data = {**self.config_entry.data, **self.config_entry.options}
self.user_data = {
API_ID: self.config_entry.options.get(API_ID),
API_KEY: self.config_entry.options.get(API_KEY),
WSLINK: self.config_entry.options.get(WSLINK, False),
DEV_DBG: self.config_entry.options.get(DEV_DBG, False),
API_ID: entry_data.get(API_ID),
API_KEY: entry_data.get(API_KEY),
WSLINK: entry_data.get(WSLINK, False),
DEV_DBG: entry_data.get(DEV_DBG, False),
}
self.user_data_schema = {
@ -76,19 +74,17 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.sensors = {
SENSORS_TO_LOAD: (
self.config_entry.options.get(SENSORS_TO_LOAD)
if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list)
entry_data.get(SENSORS_TO_LOAD)
if isinstance(entry_data.get(SENSORS_TO_LOAD), list)
else []
)
}
self.windy_data = {
WINDY_STATION_ID: self.config_entry.options.get(WINDY_STATION_ID),
WINDY_STATION_PW: self.config_entry.options.get(WINDY_STATION_PW),
WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED, False),
WINDY_LOGGER_ENABLED: self.config_entry.options.get(
WINDY_LOGGER_ENABLED, False
),
WINDY_STATION_ID: entry_data.get(WINDY_STATION_ID),
WINDY_STATION_PW: entry_data.get(WINDY_STATION_PW),
WINDY_ENABLED: entry_data.get(WINDY_ENABLED, False),
WINDY_LOGGER_ENABLED: entry_data.get(WINDY_LOGGER_ENABLED, False),
}
self.windy_data_schema = {
@ -107,15 +103,11 @@ class ConfigOptionsFlowHandler(OptionsFlow):
}
self.pocasi_cz = {
POCASI_CZ_API_ID: self.config_entry.options.get(POCASI_CZ_API_ID, ""),
POCASI_CZ_API_KEY: self.config_entry.options.get(POCASI_CZ_API_KEY, ""),
POCASI_CZ_ENABLED: self.config_entry.options.get(POCASI_CZ_ENABLED, False),
POCASI_CZ_LOGGER_ENABLED: self.config_entry.options.get(
POCASI_CZ_LOGGER_ENABLED, False
),
POCASI_CZ_SEND_INTERVAL: self.config_entry.options.get(
POCASI_CZ_SEND_INTERVAL, 30
),
POCASI_CZ_API_ID: entry_data.get(POCASI_CZ_API_ID, ""),
POCASI_CZ_API_KEY: entry_data.get(POCASI_CZ_API_KEY, ""),
POCASI_CZ_ENABLED: entry_data.get(POCASI_CZ_ENABLED, False),
POCASI_CZ_LOGGER_ENABLED: entry_data.get(POCASI_CZ_LOGGER_ENABLED, False),
POCASI_CZ_SEND_INTERVAL: entry_data.get(POCASI_CZ_SEND_INTERVAL, 30),
}
self.pocasi_cz_schema = {
@ -310,4 +302,4 @@ class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
@callback
def async_get_options_flow(config_entry) -> ConfigOptionsFlowHandler:
"""Get the options flow for this handler."""
return ConfigOptionsFlowHandler()
return ConfigOptionsFlowHandler(config_entry)

View File

@ -14,6 +14,6 @@
"issue_tracker": "https://github.com/schizza/SWS-12500-custom-component/issues",
"requirements": [],
"ssdp": [],
"version": "1.8.1",
"version": "1.8.3",
"zeroconf": []
}

View File

@ -33,8 +33,8 @@ class Routes:
def switch_route(self, coordinator: Callable, url_path: str):
"""Switch route."""
for url, route in self.routes.items():
if url == url_path:
for route in self.routes.values():
if route.url_path == url_path:
_LOGGER.info("New coordinator to route: %s", route.url_path)
route.enabled = True
route.handler = coordinator
@ -52,18 +52,20 @@ class Routes:
enabled: bool = False,
):
"""Add route."""
self.routes[url_path] = Route(url_path, route, handler, enabled)
key = f"{route.method}:{url_path}"
self.routes[key] = Route(url_path, route, handler, enabled)
def get_route(self, url_path: str) -> Route:
def get_route(self, url_path: str) -> Route | None:
"""Get route."""
return self.routes.get(url_path, Route)
for route in self.routes.values():
if route.url_path == url_path:
return route
return None
def get_enabled(self) -> str:
"""Get enabled routes."""
enabled_routes = [
route.url_path for route in self.routes.values() if route.enabled
]
return "".join(enabled_routes) if enabled_routes else "None"
enabled_routes = {route.url_path for route in self.routes.values() if route.enabled}
return ", ".join(sorted(enabled_routes)) if enabled_routes else "None"
def __str__(self):
"""Return string representation."""

View File

@ -139,10 +139,12 @@ class WindyPush:
if "t1solrad" in purged_data:
purged_data["solarradiation"] = purged_data.pop("t1solrad")
windy_station_id = self.config.options.get(WINDY_STATION_ID, "")
windy_station_pw = self.config.options.get(WINDY_STATION_PW, "")
windy_station_id = (self.config.options.get(WINDY_STATION_ID) or "").strip()
windy_station_pw = (self.config.options.get(WINDY_STATION_PW) or "").strip()
if windy_station_id == "" or windy_station_pw == "":
# Both values are required. Options can sometimes be None, so normalize to
# empty string and strip whitespace before validating.
if not windy_station_id or not windy_station_pw:
_LOGGER.error(
"Windy ID or PASSWORD is not set correctly. Please reconfigure your WINDY resend credentials. Disabling WINDY resend for now!"
)