Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2022.7.6 #75528

Merged
merged 24 commits into from
Jul 20, 2022
Merged

2022.7.6 #75528

Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fdaaed6
Fix ZHA light turn on issues (#75220)
dmulcahey Jul 18, 2022
1b61d72
Fix aruba ssh host key algorithm (#75224)
apaperclip Jul 15, 2022
8b4cf28
Force `_attr_native_value` to metric in bmw_connected_drive (#75225)
rikroe Jul 16, 2022
bccdb29
Bump venstarcolortouch to 0.18 (#75237)
craftyguy Jul 15, 2022
3a2beb2
Improve UniFi Protect unauth handling (#75269)
AngellusMortis Jul 16, 2022
75aea68
Update pyotgw to 2.0.0 (#75285)
mvn23 Jul 16, 2022
34c30f5
Add fixes for hive light (#75286)
Jul 15, 2022
8232a78
Bump bimmer_connected to 0.10.1 (#75287)
rikroe Jul 16, 2022
8b270cb
Bump simplisafe-python to 2022.07.0 (#75294)
bachya Jul 16, 2022
97b6912
Upgrade ness_alarm dependencies (#75298)
nickw444 Jul 18, 2022
7f43064
Use the orjson equivalent default encoder when save_json is passed th…
bdraco Jul 4, 2022
340da78
Use default encoder when saving storage (#75319)
bdraco Jul 17, 2022
75641b6
Apply filter to libav.hls logging namespace (#75330)
uvjustin Jul 16, 2022
219d1a8
Handle (and better log) more AirVisual cloud API errors (#75332)
bachya Jul 16, 2022
630f731
Fix HKC device triggers (#75371)
bdraco Jul 17, 2022
5c2ef50
Bump AIOAladdinConnect to 0.1.27 (#75400)
mkmer Jul 18, 2022
55ef33a
Bump pytomorrowio to 0.3.4 (#75478)
raman325 Jul 20, 2022
0a11a62
Bump pySwitchbot to 0.14.1 (#75487)
pascalwinters Jul 20, 2022
787f55e
Fix Netgear update entity (#75496)
starkillerOG Jul 20, 2022
e53a072
Fix - Forcast.solar issue on saving settings in options flow without …
klaasnicolaas Jul 20, 2022
4ac7d68
Fix failure to raise on bad YAML syntax from include files (#75510)
bdraco Jul 20, 2022
e692d2e
Fix incorrect Ambient PWS lightning strike sensor state classes (#75520)
bachya Jul 20, 2022
67fc1ac
Bump aioshelly to 2.0.1 (#75523)
thecode Jul 20, 2022
7402dc8
Bumped version to 2022.7.6
frenck Jul 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix ZHA light turn on issues (#75220)
* rename variable

* default transition is for color commands not level

* no extra command for groups

* don't transition color change when light off -> on

* clean up

* update condition

* fix condition again...

* simplify

* simplify

* missed one

* rename

* simplify

* rename

* tests

* color_provided_while_off with no changes

* fix missing flag clear

* more tests for transition scenarios

* add to comment

* fix comment

* don't transition when force on is set

* stale comment

* dont transition when colors don't change

* remove extra line

* remove debug print :)

* fix colors

* restore color to 65535 until investigated
  • Loading branch information
dmulcahey authored and frenck committed Jul 20, 2022
commit fdaaed652384c43a0e8f17f630fa82fe20bc59cb
98 changes: 61 additions & 37 deletions homeassistant/components/zha/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
CAPABILITIES_COLOR_XY = 0x08
CAPABILITIES_COLOR_TEMP = 0x10

DEFAULT_TRANSITION = 1
DEFAULT_MIN_BRIGHTNESS = 2

UPDATE_COLORLOOP_ACTION = 0x1
Expand Down Expand Up @@ -119,7 +118,7 @@ class BaseLight(LogMixin, light.LightEntity):
"""Operations common to all light entities."""

_FORCE_ON = False
_DEFAULT_COLOR_FROM_OFF_TRANSITION = 0
_DEFAULT_MIN_TRANSITION_TIME = 0

def __init__(self, *args, **kwargs):
"""Initialize the light."""
Expand All @@ -140,7 +139,7 @@ def __init__(self, *args, **kwargs):
self._level_channel = None
self._color_channel = None
self._identify_channel = None
self._default_transition = None
self._zha_config_transition = self._DEFAULT_MIN_TRANSITION_TIME
self._attr_color_mode = ColorMode.UNKNOWN # Set by sub classes

@property
Expand Down Expand Up @@ -216,33 +215,49 @@ async def async_turn_on(self, **kwargs):
transition = kwargs.get(light.ATTR_TRANSITION)
duration = (
transition * 10
if transition
else self._default_transition * 10
if self._default_transition
else DEFAULT_TRANSITION
)
if transition is not None
else self._zha_config_transition * 10
) or self._DEFAULT_MIN_TRANSITION_TIME # if 0 is passed in some devices still need the minimum default
brightness = kwargs.get(light.ATTR_BRIGHTNESS)
effect = kwargs.get(light.ATTR_EFFECT)
flash = kwargs.get(light.ATTR_FLASH)
temperature = kwargs.get(light.ATTR_COLOR_TEMP)
hs_color = kwargs.get(light.ATTR_HS_COLOR)

# If the light is currently off but a turn_on call with a color/temperature is sent,
# the light needs to be turned on first at a low brightness level where the light is immediately transitioned
# to the correct color. Afterwards, the transition is only from the low brightness to the new brightness.
# Otherwise, the transition is from the color the light had before being turned on to the new color.
# This can look especially bad with transitions longer than a second.
color_provided_from_off = (
not self._state
# This can look especially bad with transitions longer than a second. We do not want to do this for
# devices that need to be forced to use the on command because we would end up with 4 commands sent:
# move to level, on, color, move to level... We also will not set this if the bulb is already in the
# desired color mode with the desired color or color temperature.
new_color_provided_while_off = (
not isinstance(self, LightGroup)
and not self._FORCE_ON
and not self._state
and (
(
temperature is not None
and (
self._color_temp != temperature
or self._attr_color_mode != ColorMode.COLOR_TEMP
)
)
or (
hs_color is not None
and (
self.hs_color != hs_color
or self._attr_color_mode != ColorMode.HS
)
)
)
and brightness_supported(self._attr_supported_color_modes)
and (light.ATTR_COLOR_TEMP in kwargs or light.ATTR_HS_COLOR in kwargs)
)
final_duration = duration
if color_provided_from_off:
# Set the duration for the color changing commands to 0.
duration = 0

if (
brightness is None
and (self._off_with_transition or color_provided_from_off)
and (self._off_with_transition or new_color_provided_while_off)
and self._off_brightness is not None
):
brightness = self._off_brightness
Expand All @@ -254,11 +269,11 @@ async def async_turn_on(self, **kwargs):

t_log = {}

if color_provided_from_off:
if new_color_provided_while_off:
# If the light is currently off, we first need to turn it on at a low brightness level with no transition.
# After that, we set it to the desired color/temperature with no transition.
result = await self._level_channel.move_to_level_with_on_off(
DEFAULT_MIN_BRIGHTNESS, self._DEFAULT_COLOR_FROM_OFF_TRANSITION
DEFAULT_MIN_BRIGHTNESS, self._DEFAULT_MIN_TRANSITION_TIME
)
t_log["move_to_level_with_on_off"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
Expand All @@ -269,7 +284,7 @@ async def async_turn_on(self, **kwargs):

if (
(brightness is not None or transition)
and not color_provided_from_off
and not new_color_provided_while_off
and brightness_supported(self._attr_supported_color_modes)
):
result = await self._level_channel.move_to_level_with_on_off(
Expand All @@ -285,7 +300,7 @@ async def async_turn_on(self, **kwargs):

if (
brightness is None
and not color_provided_from_off
and not new_color_provided_while_off
or (self._FORCE_ON and brightness)
):
# since some lights don't always turn on with move_to_level_with_on_off,
Expand All @@ -297,9 +312,13 @@ async def async_turn_on(self, **kwargs):
return
self._state = True

if light.ATTR_COLOR_TEMP in kwargs:
temperature = kwargs[light.ATTR_COLOR_TEMP]
result = await self._color_channel.move_to_color_temp(temperature, duration)
if temperature is not None:
result = await self._color_channel.move_to_color_temp(
temperature,
self._DEFAULT_MIN_TRANSITION_TIME
if new_color_provided_while_off
else duration,
)
t_log["move_to_color_temp"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
self.debug("turned on: %s", t_log)
Expand All @@ -308,11 +327,14 @@ async def async_turn_on(self, **kwargs):
self._color_temp = temperature
self._hs_color = None

if light.ATTR_HS_COLOR in kwargs:
hs_color = kwargs[light.ATTR_HS_COLOR]
if hs_color is not None:
xy_color = color_util.color_hs_to_xy(*hs_color)
result = await self._color_channel.move_to_color(
int(xy_color[0] * 65535), int(xy_color[1] * 65535), duration
int(xy_color[0] * 65535),
int(xy_color[1] * 65535),
self._DEFAULT_MIN_TRANSITION_TIME
if new_color_provided_while_off
else duration,
)
t_log["move_to_color"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
Expand All @@ -322,9 +344,9 @@ async def async_turn_on(self, **kwargs):
self._hs_color = hs_color
self._color_temp = None

if color_provided_from_off:
if new_color_provided_while_off:
# The light is has the correct color, so we can now transition it to the correct brightness level.
result = await self._level_channel.move_to_level(level, final_duration)
result = await self._level_channel.move_to_level(level, duration)
t_log["move_to_level_if_color"] = result
if isinstance(result, Exception) or result[1] is not Status.SUCCESS:
self.debug("turned on: %s", t_log)
Expand Down Expand Up @@ -371,12 +393,13 @@ async def async_turn_on(self, **kwargs):

async def async_turn_off(self, **kwargs):
"""Turn the entity off."""
duration = kwargs.get(light.ATTR_TRANSITION)
transition = kwargs.get(light.ATTR_TRANSITION)
supports_level = brightness_supported(self._attr_supported_color_modes)

if duration and supports_level:
# is not none looks odd here but it will override built in bulb transition times if we pass 0 in here
if transition is not None and supports_level:
result = await self._level_channel.move_to_level_with_on_off(
0, duration * 10
0, transition * 10
)
else:
result = await self._on_off_channel.off()
Expand All @@ -387,7 +410,7 @@ async def async_turn_off(self, **kwargs):

if supports_level:
# store current brightness so that the next turn_on uses it.
self._off_with_transition = bool(duration)
self._off_with_transition = transition is not None
self._off_brightness = self._brightness

self.async_write_ha_state()
Expand Down Expand Up @@ -460,7 +483,7 @@ def __init__(self, unique_id, zha_device: ZHADevice, channels, **kwargs):
if effect_list:
self._effect_list = effect_list

self._default_transition = async_get_zha_config_value(
self._zha_config_transition = async_get_zha_config_value(
zha_device.gateway.config_entry,
ZHA_OPTIONS,
CONF_DEFAULT_LIGHT_TRANSITION,
Expand All @@ -472,6 +495,7 @@ def async_set_state(self, attr_id, attr_name, value):
"""Set the state."""
self._state = bool(value)
if value:
self._off_with_transition = False
self._off_brightness = None
self.async_write_ha_state()

Expand Down Expand Up @@ -605,7 +629,7 @@ class HueLight(Light):
@STRICT_MATCH(
channel_names=CHANNEL_ON_OFF,
aux_channels={CHANNEL_COLOR, CHANNEL_LEVEL},
manufacturers={"Jasco", "Quotra-Vision"},
manufacturers={"Jasco", "Quotra-Vision", "eWeLight", "eWeLink"},
)
class ForceOnLight(Light):
"""Representation of a light which does not respect move_to_level_with_on_off."""
Expand All @@ -621,7 +645,7 @@ class ForceOnLight(Light):
class SengledLight(Light):
"""Representation of a Sengled light which does not react to move_to_color_temp with 0 as a transition."""

_DEFAULT_COLOR_FROM_OFF_TRANSITION = 1
_DEFAULT_MIN_TRANSITION_TIME = 1


@GROUP_MATCH()
Expand All @@ -639,7 +663,7 @@ def __init__(
self._color_channel = group.endpoint[Color.cluster_id]
self._identify_channel = group.endpoint[Identify.cluster_id]
self._debounced_member_refresh = None
self._default_transition = async_get_zha_config_value(
self._zha_config_transition = async_get_zha_config_value(
zha_device.gateway.config_entry,
ZHA_OPTIONS,
CONF_DEFAULT_LIGHT_TRANSITION,
Expand Down
Loading