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 investigatedpull/75528/head
parent
a23b427025
commit
fdaaed6523
|
@ -73,7 +73,6 @@ CAPABILITIES_COLOR_LOOP = 0x4
|
|||
CAPABILITIES_COLOR_XY = 0x08
|
||||
CAPABILITIES_COLOR_TEMP = 0x10
|
||||
|
||||
DEFAULT_TRANSITION = 1
|
||||
DEFAULT_MIN_BRIGHTNESS = 2
|
||||
|
||||
UPDATE_COLORLOOP_ACTION = 0x1
|
||||
|
@ -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."""
|
||||
|
@ -140,7 +139,7 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
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
|
||||
|
@ -216,33 +215,49 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
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
|
||||
|
@ -254,11 +269,11 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
|
||||
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:
|
||||
|
@ -269,7 +284,7 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
|
||||
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(
|
||||
|
@ -285,7 +300,7 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
|
||||
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,
|
||||
|
@ -297,9 +312,13 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
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)
|
||||
|
@ -308,11 +327,14 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
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:
|
||||
|
@ -322,9 +344,9 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
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)
|
||||
|
@ -371,12 +393,13 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
|
||||
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()
|
||||
|
@ -387,7 +410,7 @@ class BaseLight(LogMixin, light.LightEntity):
|
|||
|
||||
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()
|
||||
|
@ -460,7 +483,7 @@ class Light(BaseLight, ZhaEntity):
|
|||
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,
|
||||
|
@ -472,6 +495,7 @@ class Light(BaseLight, ZhaEntity):
|
|||
"""Set the state."""
|
||||
self._state = bool(value)
|
||||
if value:
|
||||
self._off_with_transition = False
|
||||
self._off_brightness = None
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -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."""
|
||||
|
@ -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()
|
||||
|
@ -639,7 +663,7 @@ class LightGroup(BaseLight, ZhaGroupEntity):
|
|||
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,
|
||||
|
|
|
@ -15,7 +15,11 @@ from homeassistant.components.light import (
|
|||
ColorMode,
|
||||
)
|
||||
from homeassistant.components.zha.core.group import GroupMember
|
||||
from homeassistant.components.zha.light import FLASH_EFFECTS
|
||||
from homeassistant.components.zha.light import (
|
||||
CAPABILITIES_COLOR_TEMP,
|
||||
CAPABILITIES_COLOR_XY,
|
||||
FLASH_EFFECTS,
|
||||
)
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
|
@ -142,6 +146,10 @@ async def device_light_1(hass, zigpy_device_mock, zha_device_joined):
|
|||
ieee=IEEE_GROUPABLE_DEVICE,
|
||||
nwk=0xB79D,
|
||||
)
|
||||
color_cluster = zigpy_device.endpoints[1].light_color
|
||||
color_cluster.PLUGGED_ATTR_READS = {
|
||||
"color_capabilities": CAPABILITIES_COLOR_TEMP | CAPABILITIES_COLOR_XY
|
||||
}
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.available = True
|
||||
return zha_device
|
||||
|
@ -167,8 +175,13 @@ async def device_light_2(hass, zigpy_device_mock, zha_device_joined):
|
|||
}
|
||||
},
|
||||
ieee=IEEE_GROUPABLE_DEVICE2,
|
||||
manufacturer="Sengled",
|
||||
nwk=0xC79E,
|
||||
)
|
||||
color_cluster = zigpy_device.endpoints[1].light_color
|
||||
color_cluster.PLUGGED_ATTR_READS = {
|
||||
"color_capabilities": CAPABILITIES_COLOR_TEMP | CAPABILITIES_COLOR_XY
|
||||
}
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.available = True
|
||||
return zha_device
|
||||
|
@ -201,6 +214,38 @@ async def device_light_3(hass, zigpy_device_mock, zha_device_joined):
|
|||
return zha_device
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def eWeLink_light(hass, zigpy_device_mock, zha_device_joined):
|
||||
"""Mock eWeLink light."""
|
||||
|
||||
zigpy_device = zigpy_device_mock(
|
||||
{
|
||||
1: {
|
||||
SIG_EP_INPUT: [
|
||||
general.OnOff.cluster_id,
|
||||
general.LevelControl.cluster_id,
|
||||
lighting.Color.cluster_id,
|
||||
general.Groups.cluster_id,
|
||||
general.Identify.cluster_id,
|
||||
],
|
||||
SIG_EP_OUTPUT: [],
|
||||
SIG_EP_TYPE: zha.DeviceType.COLOR_DIMMABLE_LIGHT,
|
||||
SIG_EP_PROFILE: zha.PROFILE_ID,
|
||||
}
|
||||
},
|
||||
ieee="03:2d:6f:00:0a:90:69:e3",
|
||||
manufacturer="eWeLink",
|
||||
nwk=0xB79D,
|
||||
)
|
||||
color_cluster = zigpy_device.endpoints[1].light_color
|
||||
color_cluster.PLUGGED_ATTR_READS = {
|
||||
"color_capabilities": CAPABILITIES_COLOR_TEMP | CAPABILITIES_COLOR_XY
|
||||
}
|
||||
zha_device = await zha_device_joined(zigpy_device)
|
||||
zha_device.available = True
|
||||
return zha_device
|
||||
|
||||
|
||||
async def test_light_refresh(hass, zigpy_device_mock, zha_device_joined_restored):
|
||||
"""Test zha light platform refresh."""
|
||||
|
||||
|
@ -323,6 +368,758 @@ async def test_light(
|
|||
await async_test_flash_from_hass(hass, cluster_identify, entity_id, FLASH_LONG)
|
||||
|
||||
|
||||
@patch(
|
||||
"zigpy.zcl.clusters.lighting.Color.request",
|
||||
new=AsyncMock(return_value=[sentinel.data, zcl_f.Status.SUCCESS]),
|
||||
)
|
||||
@patch(
|
||||
"zigpy.zcl.clusters.general.Identify.request",
|
||||
new=AsyncMock(return_value=[sentinel.data, zcl_f.Status.SUCCESS]),
|
||||
)
|
||||
@patch(
|
||||
"zigpy.zcl.clusters.general.LevelControl.request",
|
||||
new=AsyncMock(return_value=[sentinel.data, zcl_f.Status.SUCCESS]),
|
||||
)
|
||||
@patch(
|
||||
"zigpy.zcl.clusters.general.OnOff.request",
|
||||
new=AsyncMock(return_value=[sentinel.data, zcl_f.Status.SUCCESS]),
|
||||
)
|
||||
async def test_transitions(
|
||||
hass, device_light_1, device_light_2, eWeLink_light, coordinator
|
||||
):
|
||||
"""Test ZHA light transition code."""
|
||||
zha_gateway = get_zha_gateway(hass)
|
||||
assert zha_gateway is not None
|
||||
zha_gateway.coordinator_zha_device = coordinator
|
||||
coordinator._zha_gateway = zha_gateway
|
||||
device_light_1._zha_gateway = zha_gateway
|
||||
device_light_2._zha_gateway = zha_gateway
|
||||
member_ieee_addresses = [device_light_1.ieee, device_light_2.ieee]
|
||||
members = [GroupMember(device_light_1.ieee, 1), GroupMember(device_light_2.ieee, 1)]
|
||||
|
||||
assert coordinator.is_coordinator
|
||||
|
||||
# test creating a group with 2 members
|
||||
zha_group = await zha_gateway.async_create_zigpy_group("Test Group", members)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert zha_group is not None
|
||||
assert len(zha_group.members) == 2
|
||||
for member in zha_group.members:
|
||||
assert member.device.ieee in member_ieee_addresses
|
||||
assert member.group == zha_group
|
||||
assert member.endpoint is not None
|
||||
|
||||
device_1_entity_id = await find_entity_id(Platform.LIGHT, device_light_1, hass)
|
||||
device_2_entity_id = await find_entity_id(Platform.LIGHT, device_light_2, hass)
|
||||
eWeLink_light_entity_id = await find_entity_id(Platform.LIGHT, eWeLink_light, hass)
|
||||
assert device_1_entity_id != device_2_entity_id
|
||||
|
||||
group_entity_id = async_find_group_entity_id(hass, Platform.LIGHT, zha_group)
|
||||
assert hass.states.get(group_entity_id) is not None
|
||||
|
||||
assert device_1_entity_id in zha_group.member_entity_ids
|
||||
assert device_2_entity_id in zha_group.member_entity_ids
|
||||
|
||||
dev1_cluster_on_off = device_light_1.device.endpoints[1].on_off
|
||||
dev2_cluster_on_off = device_light_2.device.endpoints[1].on_off
|
||||
eWeLink_cluster_on_off = eWeLink_light.device.endpoints[1].on_off
|
||||
|
||||
dev1_cluster_level = device_light_1.device.endpoints[1].level
|
||||
dev2_cluster_level = device_light_2.device.endpoints[1].level
|
||||
eWeLink_cluster_level = eWeLink_light.device.endpoints[1].level
|
||||
|
||||
dev1_cluster_color = device_light_1.device.endpoints[1].light_color
|
||||
dev2_cluster_color = device_light_2.device.endpoints[1].light_color
|
||||
eWeLink_cluster_color = eWeLink_light.device.endpoints[1].light_color
|
||||
|
||||
# allow traffic to flow through the gateway and device
|
||||
await async_enable_traffic(hass, [device_light_1, device_light_2])
|
||||
await async_wait_for_updates(hass)
|
||||
|
||||
# test that the lights were created and are off
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_OFF
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_OFF
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_OFF
|
||||
|
||||
# first test 0 length transition with no color provided
|
||||
dev1_cluster_on_off.request.reset_mock()
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": device_1_entity_id, "transition": 0, "brightness": 50},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 0
|
||||
assert dev1_cluster_on_off.request.await_count == 0
|
||||
assert dev1_cluster_color.request.call_count == 0
|
||||
assert dev1_cluster_color.request.await_count == 0
|
||||
assert dev1_cluster_level.request.call_count == 1
|
||||
assert dev1_cluster_level.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
50, # brightness (level in ZCL)
|
||||
0, # transition time
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_ON
|
||||
assert light1_state.attributes["brightness"] == 50
|
||||
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
|
||||
# test non 0 length transition with color provided while light is on
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
"transition": 3,
|
||||
"brightness": 18,
|
||||
"color_temp": 432,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 0
|
||||
assert dev1_cluster_on_off.request.await_count == 0
|
||||
assert dev1_cluster_color.request.call_count == 1
|
||||
assert dev1_cluster_color.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_count == 1
|
||||
assert dev1_cluster_level.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
18, # brightness (level in ZCL)
|
||||
30, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
432, # color temp mireds
|
||||
30.0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_ON
|
||||
assert light1_state.attributes["brightness"] == 18
|
||||
assert light1_state.attributes["color_temp"] == 432
|
||||
assert light1_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
|
||||
# test 0 length transition to turn light off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
"transition": 0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 0
|
||||
assert dev1_cluster_on_off.request.await_count == 0
|
||||
assert dev1_cluster_color.request.call_count == 0
|
||||
assert dev1_cluster_color.request.await_count == 0
|
||||
assert dev1_cluster_level.request.call_count == 1
|
||||
assert dev1_cluster_level.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
0, # brightness (level in ZCL)
|
||||
0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_OFF
|
||||
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
|
||||
# test non 0 length transition and color temp while turning light on (color_provided_while_off)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
"transition": 1,
|
||||
"brightness": 25,
|
||||
"color_temp": 235,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 0
|
||||
assert dev1_cluster_on_off.request.await_count == 0
|
||||
assert dev1_cluster_color.request.call_count == 1
|
||||
assert dev1_cluster_color.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_count == 2
|
||||
assert dev1_cluster_level.request.await_count == 2
|
||||
|
||||
# first it comes on with no transition at 2 brightness
|
||||
assert dev1_cluster_level.request.call_args_list[0] == call(
|
||||
False,
|
||||
4,
|
||||
dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
2, # brightness (level in ZCL)
|
||||
0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
235, # color temp mireds
|
||||
0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_level.request.call_args_list[1] == call(
|
||||
False,
|
||||
0,
|
||||
dev1_cluster_level.commands_by_name["move_to_level"].schema,
|
||||
25, # brightness (level in ZCL)
|
||||
10.0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_ON
|
||||
assert light1_state.attributes["brightness"] == 25
|
||||
assert light1_state.attributes["color_temp"] == 235
|
||||
assert light1_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
|
||||
# turn light 1 back off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 1
|
||||
assert dev1_cluster_on_off.request.await_count == 1
|
||||
assert dev1_cluster_color.request.call_count == 0
|
||||
assert dev1_cluster_color.request.await_count == 0
|
||||
assert dev1_cluster_level.request.call_count == 0
|
||||
assert dev1_cluster_level.request.await_count == 0
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_OFF
|
||||
|
||||
dev1_cluster_on_off.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
|
||||
# test no transition provided and color temp while turning light on (color_provided_while_off)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
"brightness": 25,
|
||||
"color_temp": 236,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 0
|
||||
assert dev1_cluster_on_off.request.await_count == 0
|
||||
assert dev1_cluster_color.request.call_count == 1
|
||||
assert dev1_cluster_color.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_count == 2
|
||||
assert dev1_cluster_level.request.await_count == 2
|
||||
|
||||
# first it comes on with no transition at 2 brightness
|
||||
assert dev1_cluster_level.request.call_args_list[0] == call(
|
||||
False,
|
||||
4,
|
||||
dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
2, # brightness (level in ZCL)
|
||||
0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
236, # color temp mireds
|
||||
0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_level.request.call_args_list[1] == call(
|
||||
False,
|
||||
0,
|
||||
dev1_cluster_level.commands_by_name["move_to_level"].schema,
|
||||
25, # brightness (level in ZCL)
|
||||
0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_ON
|
||||
assert light1_state.attributes["brightness"] == 25
|
||||
assert light1_state.attributes["color_temp"] == 236
|
||||
assert light1_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
|
||||
# turn light 1 back off to setup group test
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 1
|
||||
assert dev1_cluster_on_off.request.await_count == 1
|
||||
assert dev1_cluster_color.request.call_count == 0
|
||||
assert dev1_cluster_color.request.await_count == 0
|
||||
assert dev1_cluster_level.request.call_count == 0
|
||||
assert dev1_cluster_level.request.await_count == 0
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_OFF
|
||||
|
||||
dev1_cluster_on_off.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
|
||||
# test no transition when the same color temp is provided from off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
"color_temp": 236,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 1
|
||||
assert dev1_cluster_on_off.request.await_count == 1
|
||||
assert dev1_cluster_color.request.call_count == 1
|
||||
assert dev1_cluster_color.request.await_count == 1
|
||||
assert dev1_cluster_level.request.call_count == 0
|
||||
assert dev1_cluster_level.request.await_count == 0
|
||||
|
||||
assert dev1_cluster_on_off.request.call_args == call(
|
||||
False,
|
||||
1,
|
||||
dev1_cluster_on_off.commands_by_name["on"].schema,
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
assert dev1_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
236, # color temp mireds
|
||||
0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light1_state = hass.states.get(device_1_entity_id)
|
||||
assert light1_state.state == STATE_ON
|
||||
assert light1_state.attributes["brightness"] == 25
|
||||
assert light1_state.attributes["color_temp"] == 236
|
||||
assert light1_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
dev1_cluster_on_off.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
|
||||
# turn light 1 back off to setup group test
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_1_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev1_cluster_on_off.request.call_count == 1
|
||||
assert dev1_cluster_on_off.request.await_count == 1
|
||||
assert dev1_cluster_color.request.call_count == 0
|
||||
assert dev1_cluster_color.request.await_count == 0
|
||||
assert dev1_cluster_level.request.call_count == 0
|
||||
assert dev1_cluster_level.request.await_count == 0
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_OFF
|
||||
|
||||
dev1_cluster_on_off.request.reset_mock()
|
||||
dev1_cluster_color.request.reset_mock()
|
||||
dev1_cluster_level.request.reset_mock()
|
||||
|
||||
# test sengled light uses default minimum transition time
|
||||
dev2_cluster_on_off.request.reset_mock()
|
||||
dev2_cluster_color.request.reset_mock()
|
||||
dev2_cluster_level.request.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": device_2_entity_id, "transition": 0, "brightness": 100},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 0
|
||||
assert dev2_cluster_on_off.request.await_count == 0
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 1
|
||||
assert dev2_cluster_level.request.await_count == 1
|
||||
assert dev2_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
100, # brightness (level in ZCL)
|
||||
1, # transition time - sengled light uses default minimum
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_ON
|
||||
assert light2_state.attributes["brightness"] == 100
|
||||
|
||||
dev2_cluster_level.request.reset_mock()
|
||||
|
||||
# turn the sengled light back off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_2_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 1
|
||||
assert dev2_cluster_on_off.request.await_count == 1
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 0
|
||||
assert dev2_cluster_level.request.await_count == 0
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_OFF
|
||||
|
||||
dev2_cluster_on_off.request.reset_mock()
|
||||
|
||||
# test non 0 length transition and color temp while turning light on and sengled (color_provided_while_off)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_2_entity_id,
|
||||
"transition": 1,
|
||||
"brightness": 25,
|
||||
"color_temp": 235,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 0
|
||||
assert dev2_cluster_on_off.request.await_count == 0
|
||||
assert dev2_cluster_color.request.call_count == 1
|
||||
assert dev2_cluster_color.request.await_count == 1
|
||||
assert dev2_cluster_level.request.call_count == 2
|
||||
assert dev2_cluster_level.request.await_count == 2
|
||||
|
||||
# first it comes on with no transition at 2 brightness
|
||||
assert dev2_cluster_level.request.call_args_list[0] == call(
|
||||
False,
|
||||
4,
|
||||
dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
2, # brightness (level in ZCL)
|
||||
1, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev2_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev2_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
235, # color temp mireds
|
||||
1, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when color_provided_while_off
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev2_cluster_level.request.call_args_list[1] == call(
|
||||
False,
|
||||
0,
|
||||
dev2_cluster_level.commands_by_name["move_to_level"].schema,
|
||||
25, # brightness (level in ZCL)
|
||||
10.0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_ON
|
||||
assert light2_state.attributes["brightness"] == 25
|
||||
assert light2_state.attributes["color_temp"] == 235
|
||||
assert light2_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
dev2_cluster_level.request.reset_mock()
|
||||
dev2_cluster_color.request.reset_mock()
|
||||
|
||||
# turn the sengled light back off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": device_2_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 1
|
||||
assert dev2_cluster_on_off.request.await_count == 1
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 0
|
||||
assert dev2_cluster_level.request.await_count == 0
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_OFF
|
||||
|
||||
dev2_cluster_on_off.request.reset_mock()
|
||||
|
||||
# test non 0 length transition and color temp while turning group light on (color_provided_while_off)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": group_entity_id,
|
||||
"transition": 1,
|
||||
"brightness": 25,
|
||||
"color_temp": 235,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
group_on_off_channel = zha_group.endpoint[general.OnOff.cluster_id]
|
||||
group_level_channel = zha_group.endpoint[general.LevelControl.cluster_id]
|
||||
group_color_channel = zha_group.endpoint[lighting.Color.cluster_id]
|
||||
assert group_on_off_channel.request.call_count == 0
|
||||
assert group_on_off_channel.request.await_count == 0
|
||||
assert group_color_channel.request.call_count == 1
|
||||
assert group_color_channel.request.await_count == 1
|
||||
assert group_level_channel.request.call_count == 1
|
||||
assert group_level_channel.request.await_count == 1
|
||||
|
||||
# groups are omitted from the 3 call dance for color_provided_while_off
|
||||
assert group_color_channel.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev2_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
235, # color temp mireds
|
||||
10.0, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when color_provided_while_off
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert group_level_channel.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
25, # brightness (level in ZCL)
|
||||
10.0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_ON
|
||||
assert group_state.attributes["brightness"] == 25
|
||||
assert group_state.attributes["color_temp"] == 235
|
||||
assert group_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
group_on_off_channel.request.reset_mock()
|
||||
group_color_channel.request.reset_mock()
|
||||
group_level_channel.request.reset_mock()
|
||||
|
||||
# turn the sengled light back on
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": device_2_entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 1
|
||||
assert dev2_cluster_on_off.request.await_count == 1
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 0
|
||||
assert dev2_cluster_level.request.await_count == 0
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_ON
|
||||
|
||||
dev2_cluster_on_off.request.reset_mock()
|
||||
|
||||
# turn the light off with a transition
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_off",
|
||||
{"entity_id": device_2_entity_id, "transition": 2},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 0
|
||||
assert dev2_cluster_on_off.request.await_count == 0
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 1
|
||||
assert dev2_cluster_level.request.await_count == 1
|
||||
assert dev2_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
0, # brightness (level in ZCL)
|
||||
20, # transition time
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_OFF
|
||||
|
||||
dev2_cluster_level.request.reset_mock()
|
||||
|
||||
# turn the light back on with no args should use a transition and last known brightness
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": device_2_entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert dev2_cluster_on_off.request.call_count == 0
|
||||
assert dev2_cluster_on_off.request.await_count == 0
|
||||
assert dev2_cluster_color.request.call_count == 0
|
||||
assert dev2_cluster_color.request.await_count == 0
|
||||
assert dev2_cluster_level.request.call_count == 1
|
||||
assert dev2_cluster_level.request.await_count == 1
|
||||
assert dev2_cluster_level.request.call_args == call(
|
||||
False,
|
||||
4,
|
||||
dev2_cluster_level.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
25, # brightness (level in ZCL) - this is the last brightness we set a few tests above
|
||||
1, # transition time - sengled light uses default minimum
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
light2_state = hass.states.get(device_2_entity_id)
|
||||
assert light2_state.state == STATE_ON
|
||||
|
||||
dev2_cluster_level.request.reset_mock()
|
||||
|
||||
# test eWeLink color temp while turning light on from off (color_provided_while_off)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": eWeLink_light_entity_id,
|
||||
"color_temp": 235,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert eWeLink_cluster_on_off.request.call_count == 1
|
||||
assert eWeLink_cluster_on_off.request.await_count == 1
|
||||
assert eWeLink_cluster_color.request.call_count == 1
|
||||
assert eWeLink_cluster_color.request.await_count == 1
|
||||
assert eWeLink_cluster_level.request.call_count == 0
|
||||
assert eWeLink_cluster_level.request.await_count == 0
|
||||
|
||||
# first it comes on
|
||||
assert eWeLink_cluster_on_off.request.call_args_list[0] == call(
|
||||
False,
|
||||
1,
|
||||
eWeLink_cluster_on_off.commands_by_name["on"].schema,
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
assert dev1_cluster_color.request.call_args == call(
|
||||
False,
|
||||
10,
|
||||
dev1_cluster_color.commands_by_name["move_to_color_temp"].schema,
|
||||
235, # color temp mireds
|
||||
0, # transition time (ZCL time in 10ths of a second)
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
tsn=None,
|
||||
)
|
||||
|
||||
eWeLink_state = hass.states.get(eWeLink_light_entity_id)
|
||||
assert eWeLink_state.state == STATE_ON
|
||||
assert eWeLink_state.attributes["color_temp"] == 235
|
||||
assert eWeLink_state.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
|
||||
async def async_test_on_off_from_light(hass, cluster, entity_id):
|
||||
"""Test on off functionality from the light."""
|
||||
# turn on at light
|
||||
|
@ -463,7 +1260,7 @@ async def async_test_level_on_off_from_hass(
|
|||
4,
|
||||
level_cluster.commands_by_name["move_to_level_with_on_off"].schema,
|
||||
10,
|
||||
1,
|
||||
0,
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
tries=1,
|
||||
|
@ -601,7 +1398,10 @@ async def test_zha_group_light_entity(
|
|||
# test that the lights were created and are off
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_OFF
|
||||
assert group_state.attributes["supported_color_modes"] == [ColorMode.HS]
|
||||
assert group_state.attributes["supported_color_modes"] == [
|
||||
ColorMode.COLOR_TEMP,
|
||||
ColorMode.HS,
|
||||
]
|
||||
# Light which is off has no color mode
|
||||
assert "color_mode" not in group_state.attributes
|
||||
|
||||
|
@ -629,7 +1429,10 @@ async def test_zha_group_light_entity(
|
|||
# Check state
|
||||
group_state = hass.states.get(group_entity_id)
|
||||
assert group_state.state == STATE_ON
|
||||
assert group_state.attributes["supported_color_modes"] == [ColorMode.HS]
|
||||
assert group_state.attributes["supported_color_modes"] == [
|
||||
ColorMode.COLOR_TEMP,
|
||||
ColorMode.HS,
|
||||
]
|
||||
assert group_state.attributes["color_mode"] == ColorMode.HS
|
||||
|
||||
# test long flashing the lights from the HA
|
||||
|
|
Loading…
Reference in New Issue