Add Počasí Meteo CZ integration to options flow and constants

Introduce new config step for Počasí Meteo CZ with validation and UI
schema. Define related constants and translation keys for setting up
data forwarding.
feature/pocasi_cz
SchiZzA 2025-11-16 15:37:13 +01:00
parent 92eadbb4e2
commit 0d47e14834
No known key found for this signature in database
3 changed files with 104 additions and 15 deletions

View File

@ -4,7 +4,7 @@ from typing import Any
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, OptionsFlow from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
@ -14,6 +14,12 @@ from .const import (
DEV_DBG, DEV_DBG,
DOMAIN, DOMAIN,
INVALID_CREDENTIALS, INVALID_CREDENTIALS,
POCASI_CZ_API_ID,
POCASI_CZ_API_KEY,
POCASI_CZ_ENABLED,
POCASI_CZ_LOGGER_ENABLED,
POCASI_CZ_SEND_INTERVAL,
POCASI_CZ_SEND_MINIMUM,
SENSORS_TO_LOAD, SENSORS_TO_LOAD,
WINDY_API_KEY, WINDY_API_KEY,
WINDY_ENABLED, WINDY_ENABLED,
@ -43,6 +49,8 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.user_data_schema = {} self.user_data_schema = {}
self.sensors: dict[str, Any] = {} self.sensors: dict[str, Any] = {}
self.migrate_schema = {} self.migrate_schema = {}
self.pocasi_cz: dict[str, Any] = {}
self.pocasi_cz_schema = {}
@property @property
def config_entry(self): def config_entry(self):
@ -51,7 +59,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
async def _get_entry_data(self): async def _get_entry_data(self):
"""Get entry data.""" """Get entry data."""
self.user_data: dict[str, Any] = { self.user_data = {
API_ID: self.config_entry.options.get(API_ID), API_ID: self.config_entry.options.get(API_ID),
API_KEY: self.config_entry.options.get(API_KEY), API_KEY: self.config_entry.options.get(API_KEY),
WSLINK: self.config_entry.options.get(WSLINK, False), WSLINK: self.config_entry.options.get(WSLINK, False),
@ -65,7 +73,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
vol.Optional(DEV_DBG, default=self.user_data.get(DEV_DBG, False)): bool, vol.Optional(DEV_DBG, default=self.user_data.get(DEV_DBG, False)): bool,
} }
self.sensors: dict[str, Any] = { self.sensors = {
SENSORS_TO_LOAD: ( SENSORS_TO_LOAD: (
self.config_entry.options.get(SENSORS_TO_LOAD) self.config_entry.options.get(SENSORS_TO_LOAD)
if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list) if isinstance(self.config_entry.options.get(SENSORS_TO_LOAD), list)
@ -73,7 +81,7 @@ class ConfigOptionsFlowHandler(OptionsFlow):
) )
} }
self.windy_data: dict[str, Any] = { self.windy_data = {
WINDY_API_KEY: self.config_entry.options.get(WINDY_API_KEY), WINDY_API_KEY: self.config_entry.options.get(WINDY_API_KEY),
WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED, False), WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED, False),
WINDY_LOGGER_ENABLED: self.config_entry.options.get( WINDY_LOGGER_ENABLED: self.config_entry.options.get(
@ -90,13 +98,46 @@ class ConfigOptionsFlowHandler(OptionsFlow):
vol.Optional( vol.Optional(
WINDY_LOGGER_ENABLED, WINDY_LOGGER_ENABLED,
default=self.windy_data[WINDY_LOGGER_ENABLED], default=self.windy_data[WINDY_LOGGER_ENABLED],
): bool ): bool or False,
or False, }
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
),
}
self.pocasi_cz_schema = {
vol.Required(
POCASI_CZ_API_ID, default=self.pocasi_cz.get(POCASI_CZ_API_ID)
): str,
vol.Required(
POCASI_CZ_API_KEY, default=self.pocasi_cz.get(POCASI_CZ_API_KEY)
): str,
vol.Required(
POCASI_CZ_SEND_INTERVAL,
default=self.pocasi_cz.get(POCASI_CZ_SEND_INTERVAL),
): int,
vol.Optional(
POCASI_CZ_ENABLED, default=self.pocasi_cz.get(POCASI_CZ_ENABLED)
): bool,
vol.Optional(
POCASI_CZ_LOGGER_ENABLED,
default=self.pocasi_cz.get(POCASI_CZ_LOGGER_ENABLED),
): bool,
} }
async def async_step_init(self, user_input=None): async def async_step_init(self, user_input=None):
"""Manage the options - show menu first.""" """Manage the options - show menu first."""
return self.async_show_menu(step_id="init", menu_options=["basic", "windy"]) return self.async_show_menu(
step_id="init", menu_options=["basic", "windy", "pocasi"]
)
async def async_step_basic(self, user_input=None): async def async_step_basic(self, user_input=None):
"""Manage basic options - credentials.""" """Manage basic options - credentials."""
@ -124,6 +165,9 @@ class ConfigOptionsFlowHandler(OptionsFlow):
# retain sensors # retain sensors
user_input.update(self.sensors) user_input.update(self.sensors)
# retain pocasi data
user_input.update(self.pocasi_cz)
return self.async_create_entry(title=DOMAIN, data=user_input) return self.async_create_entry(title=DOMAIN, data=user_input)
self.user_data = user_input self.user_data = user_input
@ -164,6 +208,38 @@ class ConfigOptionsFlowHandler(OptionsFlow):
return self.async_create_entry(title=DOMAIN, data=user_input) return self.async_create_entry(title=DOMAIN, data=user_input)
async def async_step_pocasi(self, user_input: Any = None) -> ConfigFlowResult:
"""Handle the pocasi step."""
errors = {}
await self._get_entry_data()
if user_input is None:
return self.async_show_form(
step_id="pocasi",
data_schema=vol.Schema(self.pocasi_cz_schema),
errors=errors,
)
if user_input.get(POCASI_CZ_SEND_INTERVAL, 0) < POCASI_CZ_SEND_MINIMUM:
errors[POCASI_CZ_SEND_INTERVAL] = "pocasi_send_minimum"
if user_input.get(POCASI_CZ_ENABLED):
if user_input.get(POCASI_CZ_API_ID) == "":
errors[POCASI_CZ_API_ID] = "pocasi_id_required"
if user_input.get(POCASI_CZ_API_KEY) == "":
errors[POCASI_CZ_API_KEY] = "pocasi_key_required"
if len(errors) > 0:
return self.async_show_form(
step_id="pocasi",
data_schema=vol.Schema(self.pocasi_cz_schema),
errors=errors,
)
return self.async_create_entry(title=DOMAIN, data=user_input)
class ConfigFlow(ConfigFlow, domain=DOMAIN): class ConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Sencor SWS 12500 Weather Station.""" """Handle a config flow for Sencor SWS 12500 Weather Station."""

View File

@ -10,8 +10,7 @@ WINDY_URL = "https://stations.windy.com/pws/update/"
DATABASE_PATH = "/config/home-assistant_v2.db" DATABASE_PATH = "/config/home-assistant_v2.db"
POCASI_CZ_URL: Final = "http://ms.pocasimeteo.cz" POCASI_CZ_URL: Final = "http://ms.pocasimeteo.cz"
POCASI_CZ_SEND_INTERVAL = 30 # default time to resend data POCASI_CZ_SEND_MINIMUM: Final = 12 # minimal time to resend data
POCASTI_CZ_SEND_MINIMUM: Final = 12 # minimal time to resend data
ICON = "mdi:weather" ICON = "mdi:weather"
@ -24,6 +23,19 @@ SENSOR_TO_MIGRATE: Final = "sensor_to_migrate"
DEV_DBG: Final = "dev_debug_checkbox" DEV_DBG: Final = "dev_debug_checkbox"
WSLINK: Final = "wslink" WSLINK: Final = "wslink"
POCASI_CZ_API_KEY = "POCASI_CZ_API_KEY"
POCASI_CZ_API_ID = "POCASI_CZ_API_ID"
POCASI_CZ_SEND_INTERVAL = "POCASI_SEND_INTERVAL"
POCASI_CZ_ENABLED = "pocasi_enabled_chcekbox"
POCASI_CZ_LOGGER_ENABLED = "pocasi_logger_checkbox"
POCASI_INVALID_KEY: Final = (
"Pocasi Meteo refused to accept data. Invalid ID/Key combination?"
)
POCASI_CZ_SUCCESS: Final = "Successfully sent data to Pocasi Meteo"
POCASI_CZ_UNEXPECTED: Final = (
"Pocasti Meteo responded unexpectedly 3 times in row. Resendig is now disabled!"
)
WINDY_API_KEY = "WINDY_API_KEY" WINDY_API_KEY = "WINDY_API_KEY"
WINDY_ENABLED: Final = "windy_enabled_checkbox" WINDY_ENABLED: Final = "windy_enabled_checkbox"
WINDY_LOGGER_ENABLED: Final = "windy_logger_checkbox" WINDY_LOGGER_ENABLED: Final = "windy_logger_checkbox"

View File

@ -31,7 +31,8 @@
"valid_credentials_match": "API ID a API KEY nesmějí být stejné!", "valid_credentials_match": "API ID a API KEY nesmějí být stejné!",
"windy_key_required": "Je vyžadován Windy API key, pokud chcete aktivovat přeposílání dat na Windy", "windy_key_required": "Je vyžadován Windy API key, pokud chcete aktivovat přeposílání dat na Windy",
"pocasi_id_required": "Je vyžadován Počasí ID, pokud chcete aktivovat přeposílání dat na Počasí Meteo CZ", "pocasi_id_required": "Je vyžadován Počasí ID, pokud chcete aktivovat přeposílání dat na Počasí Meteo CZ",
"pocasi_key_required": "Klíč k účtu Počasí Meteo je povinný." "pocasi_key_required": "Klíč k účtu Počasí Meteo je povinný.",
"pocasi_send_minimum": "Minimální interval pro přeposílání je 12 sekund."
}, },
"step": { "step": {
"init": { "init": {
@ -40,7 +41,7 @@
"menu_options": { "menu_options": {
"basic": "Základní - přístupové údaje (přihlášení)", "basic": "Základní - přístupové údaje (přihlášení)",
"windy": "Nastavení pro přeposílání dat na Windy", "windy": "Nastavení pro přeposílání dat na Windy",
"pocasi": "Nastavení pro přeposlání dat na Pošasí Meteo CZ", "pocasi": "Nastavení pro přeposlání dat na Počasí Meteo CZ",
"migration": "Migrace statistiky senzoru" "migration": "Migrace statistiky senzoru"
} }
}, },
@ -77,10 +78,10 @@
"description": "Přeposílání dat do aplikace Počasí Meteo", "description": "Přeposílání dat do aplikace Počasí Meteo",
"title": "Konfigurace Počasí Meteo", "title": "Konfigurace Počasí Meteo",
"data": { "data": {
"POCASI_API_ID": "ID účtu na Počasí Meteo", "POCASI_CZ_API_ID": "ID účtu na Počasí Meteo",
"POCASI_API_KEY": "Klíč (Key) k účtu Počasí Meteo", "POCASI_CZ_API_KEY": "Klíč (Key) k účtu Počasí Meteo",
"POCASI_SEND_INTERVAL": "Interval v sekundách", "POCASI_CZ_SEND_INTERVAL": "Interval v sekundách",
"pocasi_enabled_checkbox": "Povolit přeposílání dat na server Počasí Meteo", "pocasi_enabled_chcekbox": "Povolit přeposílání dat na server Počasí Meteo",
"pocasi_logger_checkbox": "Logovat data a odpovědi z Počasí Meteo" "pocasi_logger_checkbox": "Logovat data a odpovědi z Počasí Meteo"
}, },
"data_description": { "data_description": {