mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
zha ZCL color loop effect (#26549)
* Initial implementation of ZCL color loop effect * Fix linter complaints * Use const for action * Reformat with Black * Cleanup after review. * Handle effect being None
This commit is contained in:
parent
6a9ecf0015
commit
bca7363a80
@ -27,9 +27,15 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
DEFAULT_DURATION = 5
|
DEFAULT_DURATION = 5
|
||||||
|
|
||||||
|
CAPABILITIES_COLOR_LOOP = 0x4
|
||||||
CAPABILITIES_COLOR_XY = 0x08
|
CAPABILITIES_COLOR_XY = 0x08
|
||||||
CAPABILITIES_COLOR_TEMP = 0x10
|
CAPABILITIES_COLOR_TEMP = 0x10
|
||||||
|
|
||||||
|
UPDATE_COLORLOOP_ACTION = 0x1
|
||||||
|
UPDATE_COLORLOOP_DIRECTION = 0x2
|
||||||
|
UPDATE_COLORLOOP_TIME = 0x4
|
||||||
|
UPDATE_COLORLOOP_HUE = 0x8
|
||||||
|
|
||||||
UNSUPPORTED_ATTRIBUTE = 0x86
|
UNSUPPORTED_ATTRIBUTE = 0x86
|
||||||
SCAN_INTERVAL = timedelta(minutes=60)
|
SCAN_INTERVAL = timedelta(minutes=60)
|
||||||
PARALLEL_UPDATES = 5
|
PARALLEL_UPDATES = 5
|
||||||
@ -85,6 +91,8 @@ class Light(ZhaEntity, light.Light):
|
|||||||
self._color_temp = None
|
self._color_temp = None
|
||||||
self._hs_color = None
|
self._hs_color = None
|
||||||
self._brightness = None
|
self._brightness = None
|
||||||
|
self._effect_list = []
|
||||||
|
self._effect = None
|
||||||
self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF)
|
self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF)
|
||||||
self._level_channel = self.cluster_channels.get(CHANNEL_LEVEL)
|
self._level_channel = self.cluster_channels.get(CHANNEL_LEVEL)
|
||||||
self._color_channel = self.cluster_channels.get(CHANNEL_COLOR)
|
self._color_channel = self.cluster_channels.get(CHANNEL_COLOR)
|
||||||
@ -103,6 +111,10 @@ class Light(ZhaEntity, light.Light):
|
|||||||
self._supported_features |= light.SUPPORT_COLOR
|
self._supported_features |= light.SUPPORT_COLOR
|
||||||
self._hs_color = (0, 0)
|
self._hs_color = (0, 0)
|
||||||
|
|
||||||
|
if color_capabilities & CAPABILITIES_COLOR_LOOP:
|
||||||
|
self._supported_features |= light.SUPPORT_EFFECT
|
||||||
|
self._effect_list.append(light.EFFECT_COLORLOOP)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return true if entity is on."""
|
"""Return true if entity is on."""
|
||||||
@ -141,6 +153,16 @@ class Light(ZhaEntity, light.Light):
|
|||||||
"""Return the CT color value in mireds."""
|
"""Return the CT color value in mireds."""
|
||||||
return self._color_temp
|
return self._color_temp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect_list(self):
|
||||||
|
"""Return the list of supported effects."""
|
||||||
|
return self._effect_list
|
||||||
|
|
||||||
|
@property
|
||||||
|
def effect(self):
|
||||||
|
"""Return the current effect."""
|
||||||
|
return self._effect
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Flag supported features."""
|
"""Flag supported features."""
|
||||||
@ -173,12 +195,15 @@ class Light(ZhaEntity, light.Light):
|
|||||||
self._color_temp = last_state.attributes["color_temp"]
|
self._color_temp = last_state.attributes["color_temp"]
|
||||||
if "hs_color" in last_state.attributes:
|
if "hs_color" in last_state.attributes:
|
||||||
self._hs_color = last_state.attributes["hs_color"]
|
self._hs_color = last_state.attributes["hs_color"]
|
||||||
|
if "effect" in last_state.attributes:
|
||||||
|
self._effect = last_state.attributes["effect"]
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
transition = kwargs.get(light.ATTR_TRANSITION)
|
transition = kwargs.get(light.ATTR_TRANSITION)
|
||||||
duration = transition * 10 if transition else DEFAULT_DURATION
|
duration = transition * 10 if transition else DEFAULT_DURATION
|
||||||
brightness = kwargs.get(light.ATTR_BRIGHTNESS)
|
brightness = kwargs.get(light.ATTR_BRIGHTNESS)
|
||||||
|
effect = kwargs.get(light.ATTR_EFFECT)
|
||||||
|
|
||||||
t_log = {}
|
t_log = {}
|
||||||
if (
|
if (
|
||||||
@ -234,6 +259,36 @@ class Light(ZhaEntity, light.Light):
|
|||||||
return
|
return
|
||||||
self._hs_color = hs_color
|
self._hs_color = hs_color
|
||||||
|
|
||||||
|
if (
|
||||||
|
effect == light.EFFECT_COLORLOOP
|
||||||
|
and self.supported_features & light.SUPPORT_EFFECT
|
||||||
|
):
|
||||||
|
result = await self._color_channel.color_loop_set(
|
||||||
|
UPDATE_COLORLOOP_ACTION
|
||||||
|
| UPDATE_COLORLOOP_DIRECTION
|
||||||
|
| UPDATE_COLORLOOP_TIME,
|
||||||
|
0x2, # start from current hue
|
||||||
|
0x1, # only support up
|
||||||
|
transition if transition else 7, # transition
|
||||||
|
0, # no hue
|
||||||
|
)
|
||||||
|
t_log["color_loop_set"] = result
|
||||||
|
self._effect = light.EFFECT_COLORLOOP
|
||||||
|
elif (
|
||||||
|
self._effect == light.EFFECT_COLORLOOP
|
||||||
|
and effect != light.EFFECT_COLORLOOP
|
||||||
|
and self.supported_features & light.SUPPORT_EFFECT
|
||||||
|
):
|
||||||
|
result = await self._color_channel.color_loop_set(
|
||||||
|
UPDATE_COLORLOOP_ACTION,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x0, # update action only, action off, no dir,time,hue
|
||||||
|
)
|
||||||
|
t_log["color_loop_set"] = result
|
||||||
|
self._effect = None
|
||||||
|
|
||||||
self.debug("turned on: %s", t_log)
|
self.debug("turned on: %s", t_log)
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
@ -292,6 +347,15 @@ class Light(ZhaEntity, light.Light):
|
|||||||
self._hs_color = color_util.color_xy_to_hs(
|
self._hs_color = color_util.color_xy_to_hs(
|
||||||
float(color_x / 65535), float(color_y / 65535)
|
float(color_x / 65535), float(color_y / 65535)
|
||||||
)
|
)
|
||||||
|
if (
|
||||||
|
color_capabilities is not None
|
||||||
|
and color_capabilities & CAPABILITIES_COLOR_LOOP
|
||||||
|
):
|
||||||
|
color_loop_active = await self._color_channel.get_attribute_value(
|
||||||
|
"color_loop_active", from_cache=from_cache
|
||||||
|
)
|
||||||
|
if color_loop_active is not None and color_loop_active == 1:
|
||||||
|
self._effect = light.EFFECT_COLORLOOP
|
||||||
|
|
||||||
async def refresh(self, time):
|
async def refresh(self, time):
|
||||||
"""Call async_get_state at an interval."""
|
"""Call async_get_state at an interval."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user