Rename profiles to automations across backend and frontend

Rename the "profiles" entity to "automations" throughout the entire
codebase for clarity. Updates Python models, storage, API routes/schemas,
engine, frontend JS modules, HTML templates, CSS classes, i18n keys
(en/ru/zh), dashboard, tutorials, and command palette.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 18:01:39 +03:00
parent da3e53e1f1
commit 21248e2dc9
39 changed files with 1180 additions and 1179 deletions
@@ -1,6 +1,6 @@
"""Reusable scene activation and snapshot capture logic.
These functions are used by both the scene-presets API route and the profile engine.
These functions are used by both the scene-presets API route and the automation engine.
"""
from typing import List, Optional, Tuple
@@ -8,10 +8,10 @@ from typing import List, Optional, Tuple
from wled_controller.core.processing.processor_manager import ProcessorManager
from wled_controller.storage import DeviceStore
from wled_controller.storage.picture_target_store import PictureTargetStore
from wled_controller.storage.profile_store import ProfileStore
from wled_controller.storage.automation_store import AutomationStore
from wled_controller.storage.scene_preset import (
AutomationSnapshot,
DeviceBrightnessSnapshot,
ProfileSnapshot,
ScenePreset,
TargetSnapshot,
)
@@ -23,12 +23,12 @@ logger = get_logger(__name__)
def capture_current_snapshot(
target_store: PictureTargetStore,
device_store: DeviceStore,
profile_store: ProfileStore,
automation_store: AutomationStore,
processor_manager: ProcessorManager,
) -> Tuple[List[TargetSnapshot], List[DeviceBrightnessSnapshot], List[ProfileSnapshot]]:
) -> Tuple[List[TargetSnapshot], List[DeviceBrightnessSnapshot], List[AutomationSnapshot]]:
"""Capture current system state as snapshot lists.
Returns (targets, devices, profiles) snapshot tuples.
Returns (targets, devices, automations) snapshot tuples.
"""
targets = []
for t in target_store.get_all_targets():
@@ -50,25 +50,25 @@ def capture_current_snapshot(
software_brightness=getattr(d, "software_brightness", 255),
))
profiles = []
for p in profile_store.get_all_profiles():
profiles.append(ProfileSnapshot(
profile_id=p.id,
enabled=p.enabled,
automations = []
for a in automation_store.get_all_automations():
automations.append(AutomationSnapshot(
automation_id=a.id,
enabled=a.enabled,
))
return targets, devices, profiles
return targets, devices, automations
async def apply_scene_state(
preset: ScenePreset,
target_store: PictureTargetStore,
device_store: DeviceStore,
profile_store: ProfileStore,
profile_engine,
automation_store: AutomationStore,
automation_engine,
processor_manager: ProcessorManager,
*,
skip_profiles: bool = False,
skip_automations: bool = False,
) -> Tuple[str, List[str]]:
"""Apply a scene preset's state to the system.
@@ -76,11 +76,11 @@ async def apply_scene_state(
preset: The scene preset to activate.
target_store: Target store for reading/updating targets.
device_store: Device store for reading/updating devices.
profile_store: Profile store for reading/updating profiles.
profile_engine: Profile engine for deactivation and re-evaluation.
automation_store: Automation store for reading/updating automations.
automation_engine: Automation engine for deactivation and re-evaluation.
processor_manager: Processor manager for starting/stopping targets.
skip_profiles: If True, skip toggling profile enable states (used when
called from the profile engine itself to avoid recursion).
skip_automations: If True, skip toggling automation enable states (used when
called from the automation engine itself to avoid recursion).
Returns:
(status, errors) where status is "activated" or "partial" and
@@ -88,19 +88,19 @@ async def apply_scene_state(
"""
errors: List[str] = []
# 1. Toggle profile enable states
if not skip_profiles:
for ps in preset.profiles:
# 1. Toggle automation enable states
if not skip_automations:
for auto_snap in preset.automations:
try:
p = profile_store.get_profile(ps.profile_id)
if p.enabled != ps.enabled:
if not ps.enabled:
await profile_engine.deactivate_if_active(ps.profile_id)
profile_store.update_profile(ps.profile_id, enabled=ps.enabled)
a = automation_store.get_automation(auto_snap.automation_id)
if a.enabled != auto_snap.enabled:
if not auto_snap.enabled:
await automation_engine.deactivate_if_active(auto_snap.automation_id)
automation_store.update_automation(auto_snap.automation_id, enabled=auto_snap.enabled)
except ValueError:
errors.append(f"Profile {ps.profile_id} not found (skipped)")
errors.append(f"Automation {auto_snap.automation_id} not found (skipped)")
except Exception as e:
errors.append(f"Profile {ps.profile_id}: {e}")
errors.append(f"Automation {auto_snap.automation_id}: {e}")
# 2. Stop targets that should be stopped
for ts in preset.targets:
@@ -172,12 +172,12 @@ async def apply_scene_state(
except Exception as e:
errors.append(f"Device {ds.device_id} brightness: {e}")
# Trigger profile re-evaluation after all changes
if not skip_profiles:
# Trigger automation re-evaluation after all changes
if not skip_automations:
try:
await profile_engine.trigger_evaluate()
await automation_engine.trigger_evaluate()
except Exception as e:
errors.append(f"Profile re-evaluation: {e}")
errors.append(f"Automation re-evaluation: {e}")
status = "activated" if not errors else "partial"
if errors: