Refactor ZHA light state restoration after a restart (#42726)

* Restore ZHA light state and level

* Restore state and color temp from zigpy cache
This commit is contained in:
Alexei Chetroi 2020-11-01 17:19:36 -05:00 committed by GitHub
parent 3f12648212
commit 9ccc49411a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 9 deletions

View File

@ -167,6 +167,11 @@ class LevelControlChannel(ZigbeeChannel):
CURRENT_LEVEL = 0
REPORT_CONFIG = ({"attr": "current_level", "config": REPORT_CONFIG_ASAP},)
@property
def current_level(self) -> Optional[int]:
"""Return cached value of the current_level attribute."""
return self.cluster.get("current_level")
@callback
def cluster_command(self, tsn, command_id, args):
"""Handle commands received to this cluster."""
@ -248,6 +253,11 @@ class OnOffChannel(ZigbeeChannel):
self._state = None
self._off_listener = None
@property
def on_off(self) -> Optional[bool]:
"""Return cached value of on/off attribute."""
return self.cluster.get("on_off")
@callback
def cluster_command(self, tsn, command_id, args):
"""Handle commands received to this cluster."""

View File

@ -1,4 +1,6 @@
"""Lighting channels module for Zigbee Home Automation."""
from typing import Optional
import zigpy.zcl.clusters.lighting as lighting
from .. import registries, typing as zha_typing
@ -41,14 +43,34 @@ class ColorChannel(ZigbeeChannel):
self._max_mireds = 500
@property
def min_mireds(self):
"""Return the coldest color_temp that this channel supports."""
return self._min_mireds
def color_loop_active(self) -> Optional[int]:
"""Return cached value of the color_loop_active attribute."""
return self.cluster.get("color_loop_active")
@property
def max_mireds(self):
def color_temperature(self) -> Optional[int]:
"""Return cached value of color temperature."""
return self.cluster.get("color_temperature")
@property
def current_x(self) -> Optional[int]:
"""Return cached value of the current_x attribute."""
return self.cluster.get("current_x")
@property
def current_y(self) -> Optional[int]:
"""Return cached value of the current_y attribute."""
return self.cluster.get("current_y")
@property
def min_mireds(self) -> int:
"""Return the coldest color_temp that this channel supports."""
return self.cluster.get("color_temp_physical_min", self._min_mireds)
@property
def max_mireds(self) -> int:
"""Return the warmest color_temp that this channel supports."""
return self._max_mireds
return self.cluster.get("color_temp_physical_max", self._max_mireds)
def get_color_capabilities(self):
"""Return the color capabilities."""
@ -74,8 +96,6 @@ class ColorChannel(ZigbeeChannel):
]
results = await self.get_attributes(attributes, from_cache=from_cache)
capabilities = results.get("color_capabilities")
self._min_mireds = results.get("color_temp_physical_min", 153)
self._max_mireds = results.get("color_temp_physical_max", 500)
if capabilities is None:
# ZCL Version 4 devices don't support the color_capabilities

View File

@ -328,6 +328,7 @@ class Light(BaseLight, ZhaEntity):
"""Initialize the ZHA light."""
super().__init__(unique_id, zha_device, channels, **kwargs)
self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF)
self._state = bool(self._on_off_channel.on_off)
self._level_channel = self.cluster_channels.get(CHANNEL_LEVEL)
self._color_channel = self.cluster_channels.get(CHANNEL_COLOR)
self._identify_channel = self.zha_device.channels.identify_ch
@ -340,20 +341,30 @@ class Light(BaseLight, ZhaEntity):
if self._level_channel:
self._supported_features |= light.SUPPORT_BRIGHTNESS
self._supported_features |= light.SUPPORT_TRANSITION
self._brightness = 0
self._brightness = self._level_channel.current_level
if self._color_channel:
color_capabilities = self._color_channel.get_color_capabilities()
if color_capabilities & CAPABILITIES_COLOR_TEMP:
self._supported_features |= light.SUPPORT_COLOR_TEMP
self._color_temp = self._color_channel.color_temperature
if color_capabilities & CAPABILITIES_COLOR_XY:
self._supported_features |= light.SUPPORT_COLOR
self._hs_color = (0, 0)
curr_x = self._color_channel.current_x
curr_y = self._color_channel.current_y
if curr_x is not None and curr_y is not None:
self._hs_color = color_util.color_xy_to_hs(
float(curr_x / 65535), float(curr_y / 65535)
)
else:
self._hs_color = (0, 0)
if color_capabilities & CAPABILITIES_COLOR_LOOP:
self._supported_features |= light.SUPPORT_EFFECT
effect_list.append(light.EFFECT_COLORLOOP)
if self._color_channel.color_loop_active == 1:
self._effect = light.EFFECT_COLORLOOP
if self._identify_channel:
self._supported_features |= light.SUPPORT_FLASH