feat: add weather source entity and weather-reactive CSS source type
Lint & Test / test (push) Failing after 34s

New standalone WeatherSource entity with pluggable provider architecture
(Open-Meteo v1, free, no API key). Full CRUD, test endpoint, browser
geolocation, IconSelect provider picker, CardSection with test/clone/edit.

WeatherColorStripStream maps WMO weather codes to ambient color palettes
with temperature hue shifting and thunderstorm flash effects. Ref-counted
WeatherManager polls API and caches data per source.

CSS editor integration: weather type with EntitySelect source picker,
speed and temperature influence sliders. Backup/restore support.

i18n for en/ru/zh.
This commit is contained in:
2026-03-24 18:52:46 +03:00
parent 0723c5c68c
commit ef33935188
31 changed files with 1868 additions and 11 deletions
@@ -22,7 +22,9 @@ from wled_controller.storage.scene_preset_store import ScenePresetStore
from wled_controller.storage.sync_clock_store import SyncClockStore
from wled_controller.storage.color_strip_processing_template_store import ColorStripProcessingTemplateStore
from wled_controller.storage.gradient_store import GradientStore
from wled_controller.storage.weather_source_store import WeatherSourceStore
from wled_controller.core.automations.automation_engine import AutomationEngine
from wled_controller.core.weather.weather_manager import WeatherManager
from wled_controller.core.backup.auto_backup import AutoBackupEngine
from wled_controller.core.processing.sync_clock_manager import SyncClockManager
@@ -119,6 +121,14 @@ def get_gradient_store() -> GradientStore:
return _get("gradient_store", "Gradient store")
def get_weather_source_store() -> WeatherSourceStore:
return _get("weather_source_store", "Weather source store")
def get_weather_manager() -> WeatherManager:
return _get("weather_manager", "Weather manager")
# ── Event helper ────────────────────────────────────────────────────────
@@ -163,6 +173,8 @@ def init_dependencies(
sync_clock_manager: SyncClockManager | None = None,
cspt_store: ColorStripProcessingTemplateStore | None = None,
gradient_store: GradientStore | None = None,
weather_source_store: WeatherSourceStore | None = None,
weather_manager: WeatherManager | None = None,
):
"""Initialize global dependencies."""
_deps.update({
@@ -185,4 +197,6 @@ def init_dependencies(
"sync_clock_manager": sync_clock_manager,
"cspt_store": cspt_store,
"gradient_store": gradient_store,
"weather_source_store": weather_source_store,
"weather_manager": weather_manager,
})