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 CURRENT_LEVEL = 0
REPORT_CONFIG = ({"attr": "current_level", "config": REPORT_CONFIG_ASAP},) 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 @callback
def cluster_command(self, tsn, command_id, args): def cluster_command(self, tsn, command_id, args):
"""Handle commands received to this cluster.""" """Handle commands received to this cluster."""
@ -248,6 +253,11 @@ class OnOffChannel(ZigbeeChannel):
self._state = None self._state = None
self._off_listener = 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 @callback
def cluster_command(self, tsn, command_id, args): def cluster_command(self, tsn, command_id, args):
"""Handle commands received to this cluster.""" """Handle commands received to this cluster."""

View File

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

View File

@ -328,6 +328,7 @@ class Light(BaseLight, ZhaEntity):
"""Initialize the ZHA light.""" """Initialize the ZHA light."""
super().__init__(unique_id, zha_device, channels, **kwargs) super().__init__(unique_id, zha_device, channels, **kwargs)
self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF) 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._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)
self._identify_channel = self.zha_device.channels.identify_ch self._identify_channel = self.zha_device.channels.identify_ch
@ -340,20 +341,30 @@ class Light(BaseLight, ZhaEntity):
if self._level_channel: if self._level_channel:
self._supported_features |= light.SUPPORT_BRIGHTNESS self._supported_features |= light.SUPPORT_BRIGHTNESS
self._supported_features |= light.SUPPORT_TRANSITION self._supported_features |= light.SUPPORT_TRANSITION
self._brightness = 0 self._brightness = self._level_channel.current_level
if self._color_channel: if self._color_channel:
color_capabilities = self._color_channel.get_color_capabilities() color_capabilities = self._color_channel.get_color_capabilities()
if color_capabilities & CAPABILITIES_COLOR_TEMP: if color_capabilities & CAPABILITIES_COLOR_TEMP:
self._supported_features |= light.SUPPORT_COLOR_TEMP self._supported_features |= light.SUPPORT_COLOR_TEMP
self._color_temp = self._color_channel.color_temperature
if color_capabilities & CAPABILITIES_COLOR_XY: if color_capabilities & CAPABILITIES_COLOR_XY:
self._supported_features |= light.SUPPORT_COLOR 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: if color_capabilities & CAPABILITIES_COLOR_LOOP:
self._supported_features |= light.SUPPORT_EFFECT self._supported_features |= light.SUPPORT_EFFECT
effect_list.append(light.EFFECT_COLORLOOP) effect_list.append(light.EFFECT_COLORLOOP)
if self._color_channel.color_loop_active == 1:
self._effect = light.EFFECT_COLORLOOP
if self._identify_channel: if self._identify_channel:
self._supported_features |= light.SUPPORT_FLASH self._supported_features |= light.SUPPORT_FLASH