Store ZHA light brightness when fading off to turn on at the correct brightness (#26680)
* Use light's on_level in ZHA to turn on at the correct brightness Previously, if the light is turned off with a time transition, the brightness level stored in the light will be 1. The next time the light is turned on with no explicit brightness, it will be at 1. This is solved by storing the current brightness in on_level before turning off, and then using that when turning on (by calling the onOff cluster 'on' command). * store off light level locally to avoid wearing device's flash memory * store off brightness in HA attributes * improve set/clear of off_brightness * fix device_state_attributes; clear off_brightness when light goes on * fix testspull/31598/head
parent
2c80ce3195
commit
61634d0a64
homeassistant/components/zha
tests/components/zha
|
@ -25,8 +25,6 @@ from .entity import ZhaEntity
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_DURATION = 5
|
||||
|
||||
CAPABILITIES_COLOR_LOOP = 0x4
|
||||
CAPABILITIES_COLOR_XY = 0x08
|
||||
CAPABILITIES_COLOR_TEMP = 0x10
|
||||
|
@ -91,6 +89,7 @@ class Light(ZhaEntity, light.Light):
|
|||
self._color_temp = None
|
||||
self._hs_color = None
|
||||
self._brightness = None
|
||||
self._off_brightness = None
|
||||
self._effect_list = []
|
||||
self._effect = None
|
||||
self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF)
|
||||
|
@ -130,7 +129,8 @@ class Light(ZhaEntity, light.Light):
|
|||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return state attributes."""
|
||||
return self.state_attributes
|
||||
attributes = {"off_brightness": self._off_brightness}
|
||||
return attributes
|
||||
|
||||
def set_level(self, value):
|
||||
"""Set the brightness of this light between 0..254.
|
||||
|
@ -171,6 +171,8 @@ class Light(ZhaEntity, light.Light):
|
|||
def async_set_state(self, state):
|
||||
"""Set the state."""
|
||||
self._state = bool(state)
|
||||
if state:
|
||||
self._off_brightness = None
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
|
@ -191,6 +193,8 @@ class Light(ZhaEntity, light.Light):
|
|||
self._state = last_state.state == STATE_ON
|
||||
if "brightness" in last_state.attributes:
|
||||
self._brightness = last_state.attributes["brightness"]
|
||||
if "off_brightness" in last_state.attributes:
|
||||
self._off_brightness = last_state.attributes["off_brightness"]
|
||||
if "color_temp" in last_state.attributes:
|
||||
self._color_temp = last_state.attributes["color_temp"]
|
||||
if "hs_color" in last_state.attributes:
|
||||
|
@ -201,10 +205,13 @@ class Light(ZhaEntity, light.Light):
|
|||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the entity on."""
|
||||
transition = kwargs.get(light.ATTR_TRANSITION)
|
||||
duration = transition * 10 if transition is not None else DEFAULT_DURATION
|
||||
duration = transition * 10 if transition else 0
|
||||
brightness = kwargs.get(light.ATTR_BRIGHTNESS)
|
||||
effect = kwargs.get(light.ATTR_EFFECT)
|
||||
|
||||
if brightness is None and self._off_brightness is not None:
|
||||
brightness = self._off_brightness
|
||||
|
||||
t_log = {}
|
||||
if (
|
||||
brightness is not None or transition
|
||||
|
@ -225,13 +232,14 @@ class Light(ZhaEntity, light.Light):
|
|||
self._brightness = level
|
||||
|
||||
if brightness is None or brightness:
|
||||
# since some lights don't always turn on with move_to_level_with_on_off,
|
||||
# we should call the on command on the on_off cluster if brightness is not 0.
|
||||
result = await self._on_off_channel.on()
|
||||
t_log["on_off"] = result
|
||||
if not isinstance(result, list) or result[1] is not Status.SUCCESS:
|
||||
self.debug("turned on: %s", t_log)
|
||||
return
|
||||
self._state = True
|
||||
|
||||
if (
|
||||
light.ATTR_COLOR_TEMP in kwargs
|
||||
and self.supported_features & light.SUPPORT_COLOR_TEMP
|
||||
|
@ -289,6 +297,7 @@ class Light(ZhaEntity, light.Light):
|
|||
t_log["color_loop_set"] = result
|
||||
self._effect = None
|
||||
|
||||
self._off_brightness = None
|
||||
self.debug("turned on: %s", t_log)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -296,6 +305,7 @@ class Light(ZhaEntity, light.Light):
|
|||
"""Turn the entity off."""
|
||||
duration = kwargs.get(light.ATTR_TRANSITION)
|
||||
supports_level = self.supported_features & light.SUPPORT_BRIGHTNESS
|
||||
|
||||
if duration and supports_level:
|
||||
result = await self._level_channel.move_to_level_with_on_off(
|
||||
0, duration * 10
|
||||
|
@ -306,6 +316,11 @@ class Light(ZhaEntity, light.Light):
|
|||
if not isinstance(result, list) or result[1] is not Status.SUCCESS:
|
||||
return
|
||||
self._state = False
|
||||
|
||||
if duration and supports_level:
|
||||
# store current brightness so that the next turn_on uses it.
|
||||
self._off_brightness = self._brightness
|
||||
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def async_update(self):
|
||||
|
|
|
@ -230,7 +230,7 @@ async def async_test_level_on_off_from_hass(
|
|||
4,
|
||||
(types.uint8_t, types.uint16_t),
|
||||
10,
|
||||
5.0,
|
||||
0,
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue