Add post update hook to module and use in smart LightEffect (#921)

Adds a post update hook to modules so they can calculate values and collections once rather than on each property access
This commit is contained in:
Steven B
2024-05-19 10:18:17 +01:00
committed by GitHub
parent 3490a1ef84
commit 9989d0f6ec
5 changed files with 46 additions and 23 deletions

View File

@@ -4,14 +4,11 @@ from __future__ import annotations
import base64
import copy
from typing import TYPE_CHECKING, Any
from typing import Any
from ...interfaces.lighteffect import LightEffect as LightEffectInterface
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class LightEffect(SmartModule, LightEffectInterface):
"""Implementation of dynamic light effects."""
@@ -23,12 +20,13 @@ class LightEffect(SmartModule, LightEffectInterface):
"L2": "Relax",
}
def __init__(self, device: SmartDevice, module: str):
super().__init__(device, module)
self._scenes_names_to_id: dict[str, str] = {}
_effect: str
_effect_state_list: dict[str, dict[str, Any]]
_effect_list: list[str]
_scenes_names_to_id: dict[str, str]
def _initialize_effects(self) -> dict[str, dict[str, Any]]:
"""Return built-in effects."""
def _post_update_hook(self) -> None:
"""Update internal effect state."""
# Copy the effects so scene name updates do not update the underlying dict.
effects = copy.deepcopy(
{effect["id"]: effect for effect in self.data["rule_list"]}
@@ -40,10 +38,21 @@ class LightEffect(SmartModule, LightEffectInterface):
else:
# Otherwise it will be b64 encoded
effect["scene_name"] = base64.b64decode(effect["scene_name"]).decode()
self._effect_state_list = effects
self._effect_list = [self.LIGHT_EFFECTS_OFF]
self._effect_list.extend([effect["scene_name"] for effect in effects.values()])
self._scenes_names_to_id = {
effect["scene_name"]: effect["id"] for effect in effects.values()
}
return effects
# get_dynamic_light_effect_rules also has an enable property and current_rule_id
# property that could be used here as an alternative
if self._device._info["dynamic_light_effect_enable"]:
self._effect = self._effect_state_list[
self._device._info["dynamic_light_effect_id"]
]["scene_name"]
else:
self._effect = self.LIGHT_EFFECTS_OFF
@property
def effect_list(self) -> list[str]:
@@ -52,22 +61,12 @@ class LightEffect(SmartModule, LightEffectInterface):
Example:
['Party', 'Relax', ...]
"""
effects = [self.LIGHT_EFFECTS_OFF]
effects.extend(
[effect["scene_name"] for effect in self._initialize_effects().values()]
)
return effects
return self._effect_list
@property
def effect(self) -> str:
"""Return effect name."""
# get_dynamic_light_effect_rules also has an enable property and current_rule_id
# property that could be used here as an alternative
if self._device._info["dynamic_light_effect_enable"]:
return self._initialize_effects()[
self._device._info["dynamic_light_effect_id"]
]["scene_name"]
return self.LIGHT_EFFECTS_OFF
return self._effect
async def set_effect(
self,