Replace profile targets with scene activation and searchable scene selector
Profiles now activate scene presets instead of individual targets, with configurable deactivation behavior (none/revert/fallback scene). The target checklist UI is replaced by a searchable combobox for scene selection that scales well with many scenes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -160,14 +160,16 @@ class MQTTCondition(Condition):
|
||||
|
||||
@dataclass
|
||||
class Profile:
|
||||
"""Automation profile that activates targets based on conditions."""
|
||||
"""Automation profile that activates a scene preset based on conditions."""
|
||||
|
||||
id: str
|
||||
name: str
|
||||
enabled: bool
|
||||
condition_logic: str # "or" | "and"
|
||||
conditions: List[Condition]
|
||||
target_ids: List[str]
|
||||
scene_preset_id: Optional[str] # scene to activate when conditions are met
|
||||
deactivation_mode: str # "none" | "revert" | "fallback_scene"
|
||||
deactivation_scene_preset_id: Optional[str] # scene for fallback_scene mode
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@@ -178,7 +180,9 @@ class Profile:
|
||||
"enabled": self.enabled,
|
||||
"condition_logic": self.condition_logic,
|
||||
"conditions": [c.to_dict() for c in self.conditions],
|
||||
"target_ids": list(self.target_ids),
|
||||
"scene_preset_id": self.scene_preset_id,
|
||||
"deactivation_mode": self.deactivation_mode,
|
||||
"deactivation_scene_preset_id": self.deactivation_scene_preset_id,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"updated_at": self.updated_at.isoformat(),
|
||||
}
|
||||
@@ -198,7 +202,9 @@ class Profile:
|
||||
enabled=data.get("enabled", True),
|
||||
condition_logic=data.get("condition_logic", "or"),
|
||||
conditions=conditions,
|
||||
target_ids=data.get("target_ids", []),
|
||||
scene_preset_id=data.get("scene_preset_id"),
|
||||
deactivation_mode=data.get("deactivation_mode", "none"),
|
||||
deactivation_scene_preset_id=data.get("deactivation_scene_preset_id"),
|
||||
created_at=datetime.fromisoformat(data.get("created_at", datetime.utcnow().isoformat())),
|
||||
updated_at=datetime.fromisoformat(data.get("updated_at", datetime.utcnow().isoformat())),
|
||||
)
|
||||
|
||||
@@ -74,7 +74,9 @@ class ProfileStore:
|
||||
enabled: bool = True,
|
||||
condition_logic: str = "or",
|
||||
conditions: Optional[List[Condition]] = None,
|
||||
target_ids: Optional[List[str]] = None,
|
||||
scene_preset_id: Optional[str] = None,
|
||||
deactivation_mode: str = "none",
|
||||
deactivation_scene_preset_id: Optional[str] = None,
|
||||
) -> Profile:
|
||||
for p in self._profiles.values():
|
||||
if p.name == name:
|
||||
@@ -89,7 +91,9 @@ class ProfileStore:
|
||||
enabled=enabled,
|
||||
condition_logic=condition_logic,
|
||||
conditions=conditions or [],
|
||||
target_ids=target_ids or [],
|
||||
scene_preset_id=scene_preset_id,
|
||||
deactivation_mode=deactivation_mode,
|
||||
deactivation_scene_preset_id=deactivation_scene_preset_id,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
@@ -107,7 +111,9 @@ class ProfileStore:
|
||||
enabled: Optional[bool] = None,
|
||||
condition_logic: Optional[str] = None,
|
||||
conditions: Optional[List[Condition]] = None,
|
||||
target_ids: Optional[List[str]] = None,
|
||||
scene_preset_id: str = "__unset__",
|
||||
deactivation_mode: Optional[str] = None,
|
||||
deactivation_scene_preset_id: str = "__unset__",
|
||||
) -> Profile:
|
||||
if profile_id not in self._profiles:
|
||||
raise ValueError(f"Profile not found: {profile_id}")
|
||||
@@ -125,8 +131,12 @@ class ProfileStore:
|
||||
profile.condition_logic = condition_logic
|
||||
if conditions is not None:
|
||||
profile.conditions = conditions
|
||||
if target_ids is not None:
|
||||
profile.target_ids = target_ids
|
||||
if scene_preset_id != "__unset__":
|
||||
profile.scene_preset_id = scene_preset_id
|
||||
if deactivation_mode is not None:
|
||||
profile.deactivation_mode = deactivation_mode
|
||||
if deactivation_scene_preset_id != "__unset__":
|
||||
profile.deactivation_scene_preset_id = deactivation_scene_preset_id
|
||||
|
||||
profile.updated_at = datetime.utcnow()
|
||||
self._save()
|
||||
|
||||
Reference in New Issue
Block a user