mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-08-09 20:24:02 +00:00
Fix changing brightness when effect is active (#1019)
This PR changes the behavior of `brightness` module if an effect is active. Currently, changing the brightness disables the effect when the brightness is changed, this fixes that. This will also improve the `set_effect` interface to use the current brightness when an effect is activated. * light_strip_effect: passing `bAdjusted` with the changed properties changes the brightness. * light_effect: the brightness is stored only in the rule, so we modify it when adjusting the brightness. This is also done during the initial effect activation. --------- Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
@@ -3,14 +3,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
import contextlib
|
||||
import copy
|
||||
from typing import Any
|
||||
|
||||
from ...interfaces.lighteffect import LightEffect as LightEffectInterface
|
||||
from ..smartmodule import SmartModule
|
||||
from ..effects import SmartLightEffect
|
||||
from ..smartmodule import Module, SmartModule
|
||||
|
||||
|
||||
class LightEffect(SmartModule, LightEffectInterface):
|
||||
class LightEffect(SmartModule, SmartLightEffect):
|
||||
"""Implementation of dynamic light effects."""
|
||||
|
||||
REQUIRED_COMPONENT = "light_effect"
|
||||
@@ -36,8 +38,11 @@ class LightEffect(SmartModule, LightEffectInterface):
|
||||
# If the name has not been edited scene_name will be an empty string
|
||||
effect["scene_name"] = self.AVAILABLE_BULB_EFFECTS[effect["id"]]
|
||||
else:
|
||||
# Otherwise it will be b64 encoded
|
||||
effect["scene_name"] = base64.b64decode(effect["scene_name"]).decode()
|
||||
# Otherwise it might be b64 encoded or raw string
|
||||
with contextlib.suppress(binascii.Error):
|
||||
effect["scene_name"] = base64.b64decode(
|
||||
effect["scene_name"]
|
||||
).decode()
|
||||
|
||||
self._effect_state_list = effects
|
||||
self._effect_list = [self.LIGHT_EFFECTS_OFF]
|
||||
@@ -77,6 +82,8 @@ class LightEffect(SmartModule, LightEffectInterface):
|
||||
) -> None:
|
||||
"""Set an effect for the device.
|
||||
|
||||
Calling this will modify the brightness of the effect on the device.
|
||||
|
||||
The device doesn't store an active effect while not enabled so store locally.
|
||||
"""
|
||||
if effect != self.LIGHT_EFFECTS_OFF and effect not in self._scenes_names_to_id:
|
||||
@@ -90,7 +97,64 @@ class LightEffect(SmartModule, LightEffectInterface):
|
||||
if enable:
|
||||
effect_id = self._scenes_names_to_id[effect]
|
||||
params["id"] = effect_id
|
||||
return await self.call("set_dynamic_light_effect_rule_enable", params)
|
||||
|
||||
# We set the wanted brightness before activating the effect
|
||||
brightness_module = self._device.modules[Module.Brightness]
|
||||
brightness = (
|
||||
brightness if brightness is not None else brightness_module.brightness
|
||||
)
|
||||
await self.set_brightness(brightness, effect_id=effect_id)
|
||||
|
||||
await self.call("set_dynamic_light_effect_rule_enable", params)
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
"""Return True if effect is active."""
|
||||
return bool(self._device._info["dynamic_light_effect_enable"])
|
||||
|
||||
def _get_effect_data(self, effect_id: str | None = None) -> dict[str, Any]:
|
||||
"""Return effect data for the *effect_id*.
|
||||
|
||||
If *effect_id* is None, return the data for active effect.
|
||||
"""
|
||||
if effect_id is None:
|
||||
effect_id = self.data["current_rule_id"]
|
||||
|
||||
return self._effect_state_list[effect_id]
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Return effect brightness."""
|
||||
first_color_status = self._get_effect_data()["color_status_list"][0]
|
||||
brightness = first_color_status[0]
|
||||
|
||||
return brightness
|
||||
|
||||
async def set_brightness(
|
||||
self,
|
||||
brightness: int,
|
||||
*,
|
||||
transition: int | None = None,
|
||||
effect_id: str | None = None,
|
||||
):
|
||||
"""Set effect brightness."""
|
||||
new_effect = self._get_effect_data(effect_id=effect_id).copy()
|
||||
|
||||
def _replace_brightness(data, new_brightness):
|
||||
"""Replace brightness.
|
||||
|
||||
The first element is the brightness, the rest are unknown.
|
||||
[[33, 0, 0, 2700], [33, 321, 99, 0], [33, 196, 99, 0], .. ]
|
||||
"""
|
||||
return [new_brightness, data[1], data[2], data[3]]
|
||||
|
||||
new_color_status_list = [
|
||||
_replace_brightness(state, brightness)
|
||||
for state in new_effect["color_status_list"]
|
||||
]
|
||||
new_effect["color_status_list"] = new_color_status_list
|
||||
|
||||
return await self.call("edit_dynamic_light_effect_rule", new_effect)
|
||||
|
||||
async def set_custom_effect(
|
||||
self,
|
||||
|
Reference in New Issue
Block a user