Use feature checks in tplink integration (#133795)

Clean up to use new upstream API:

* Use Feature attributes to check for supported

* Use color_temp range and update tests
This commit is contained in:
Steven B. 2024-12-22 15:17:23 +00:00 committed by GitHub
parent 26d5c55d11
commit 3cc75c3cf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 157 additions and 67 deletions

View File

@ -200,14 +200,13 @@ class TPLinkLightEntity(CoordinatedTPLinkEntity, LightEntity):
# If _attr_name is None the entity name will be the device name # If _attr_name is None the entity name will be the device name
self._attr_name = None if parent is None else device.alias self._attr_name = None if parent is None else device.alias
modes: set[ColorMode] = {ColorMode.ONOFF} modes: set[ColorMode] = {ColorMode.ONOFF}
if light_module.is_variable_color_temp: if color_temp_feat := light_module.get_feature("color_temp"):
modes.add(ColorMode.COLOR_TEMP) modes.add(ColorMode.COLOR_TEMP)
temp_range = light_module.valid_temperature_range self._attr_min_color_temp_kelvin = color_temp_feat.minimum_value
self._attr_min_color_temp_kelvin = temp_range.min self._attr_max_color_temp_kelvin = color_temp_feat.maximum_value
self._attr_max_color_temp_kelvin = temp_range.max if light_module.has_feature("hsv"):
if light_module.is_color:
modes.add(ColorMode.HS) modes.add(ColorMode.HS)
if light_module.is_dimmable: if light_module.has_feature("brightness"):
modes.add(ColorMode.BRIGHTNESS) modes.add(ColorMode.BRIGHTNESS)
self._attr_supported_color_modes = filter_supported_color_modes(modes) self._attr_supported_color_modes = filter_supported_color_modes(modes)
if len(self._attr_supported_color_modes) == 1: if len(self._attr_supported_color_modes) == 1:
@ -270,15 +269,17 @@ class TPLinkLightEntity(CoordinatedTPLinkEntity, LightEntity):
self, color_temp: float, brightness: int | None, transition: int | None self, color_temp: float, brightness: int | None, transition: int | None
) -> None: ) -> None:
light_module = self._light_module light_module = self._light_module
valid_temperature_range = light_module.valid_temperature_range color_temp_feat = light_module.get_feature("color_temp")
assert color_temp_feat
requested_color_temp = round(color_temp) requested_color_temp = round(color_temp)
# Clamp color temp to valid range # Clamp color temp to valid range
# since if the light in a group we will # since if the light in a group we will
# get requests for color temps for the range # get requests for color temps for the range
# of the group and not the light # of the group and not the light
clamped_color_temp = min( clamped_color_temp = min(
valid_temperature_range.max, color_temp_feat.maximum_value,
max(valid_temperature_range.min, requested_color_temp), max(color_temp_feat.minimum_value, requested_color_temp),
) )
await light_module.set_color_temp( await light_module.set_color_temp(
clamped_color_temp, clamped_color_temp,
@ -325,8 +326,11 @@ class TPLinkLightEntity(CoordinatedTPLinkEntity, LightEntity):
# The light supports only a single color mode, return it # The light supports only a single color mode, return it
return self._fixed_color_mode return self._fixed_color_mode
# The light supports both color temp and color, determine which on is active # The light supports both color temp and color, determine which one is active
if self._light_module.is_variable_color_temp and self._light_module.color_temp: if (
self._light_module.has_feature("color_temp")
and self._light_module.color_temp
):
return ColorMode.COLOR_TEMP return ColorMode.COLOR_TEMP
return ColorMode.HS return ColorMode.HS
@ -335,7 +339,7 @@ class TPLinkLightEntity(CoordinatedTPLinkEntity, LightEntity):
"""Update the entity's attributes.""" """Update the entity's attributes."""
light_module = self._light_module light_module = self._light_module
self._attr_is_on = light_module.state.light_on is True self._attr_is_on = light_module.state.light_on is True
if light_module.is_dimmable: if light_module.has_feature("brightness"):
self._attr_brightness = round((light_module.brightness * 255.0) / 100.0) self._attr_brightness = round((light_module.brightness * 255.0) / 100.0)
color_mode = self._determine_color_mode() color_mode = self._determine_color_mode()
self._attr_color_mode = color_mode self._attr_color_mode = color_mode

View File

@ -257,20 +257,27 @@ def _mocked_device(
for module_name in modules for module_name in modules
} }
device_features = {}
if features: if features:
device.features = { device_features = {
feature_id: _mocked_feature(feature_id, require_fixture=True) feature_id: _mocked_feature(feature_id, require_fixture=True)
for feature_id in features for feature_id in features
if isinstance(feature_id, str) if isinstance(feature_id, str)
} }
device.features.update( device_features.update(
{ {
feature.id: feature feature.id: feature
for feature in features for feature in features
if isinstance(feature, Feature) if isinstance(feature, Feature)
} }
) )
device.features = device_features
for mod in device.modules.values():
mod.get_feature.side_effect = device_features.get
mod.has_feature.side_effect = lambda id: id in device_features
device.children = [] device.children = []
if children: if children:
for child in children: for child in children:
@ -289,6 +296,7 @@ def _mocked_device(
device.protocol = _mock_protocol() device.protocol = _mock_protocol()
device.config = device_config device.config = device_config
device.credentials_hash = credentials_hash device.credentials_hash = credentials_hash
return device return device
@ -303,8 +311,8 @@ def _mocked_feature(
precision_hint=None, precision_hint=None,
choices=None, choices=None,
unit=None, unit=None,
minimum_value=0, minimum_value=None,
maximum_value=2**16, # Arbitrary max maximum_value=None,
) -> Feature: ) -> Feature:
"""Get a mocked feature. """Get a mocked feature.
@ -334,11 +342,14 @@ def _mocked_feature(
feature.unit = unit or fixture.get("unit") feature.unit = unit or fixture.get("unit")
# number # number
feature.minimum_value = minimum_value or fixture.get("minimum_value") min_val = minimum_value or fixture.get("minimum_value")
feature.maximum_value = maximum_value or fixture.get("maximum_value") feature.minimum_value = 0 if min_val is None else min_val
max_val = maximum_value or fixture.get("maximum_value")
feature.maximum_value = 2**16 if max_val is None else max_val
# select # select
feature.choices = choices or fixture.get("choices") feature.choices = choices or fixture.get("choices")
return feature return feature
@ -350,13 +361,7 @@ def _mocked_light_module(device) -> Light:
light.state = LightState( light.state = LightState(
light_on=True, brightness=light.brightness, color_temp=light.color_temp light_on=True, brightness=light.brightness, color_temp=light.color_temp
) )
light.is_color = True
light.is_variable_color_temp = True
light.is_dimmable = True
light.is_brightness = True
light.has_effects = False
light.hsv = (10, 30, 5) light.hsv = (10, 30, 5)
light.valid_temperature_range = ColorTempRange(min=4000, max=9000)
light.hw_info = {"sw_ver": "1.0.0", "hw_ver": "1.0.0"} light.hw_info = {"sw_ver": "1.0.0", "hw_ver": "1.0.0"}
async def _set_state(state, *_, **__): async def _set_state(state, *_, **__):
@ -389,7 +394,6 @@ def _mocked_light_module(device) -> Light:
def _mocked_light_effect_module(device) -> LightEffect: def _mocked_light_effect_module(device) -> LightEffect:
effect = MagicMock(spec=LightEffect, name="Mocked light effect") effect = MagicMock(spec=LightEffect, name="Mocked light effect")
effect.has_effects = True
effect.has_custom_effects = True effect.has_custom_effects = True
effect.effect = "Effect1" effect.effect = "Effect1"
effect.effect_list = ["Off", "Effect1", "Effect2"] effect.effect_list = ["Off", "Effect1", "Effect2"]

View File

@ -267,7 +267,9 @@
"target_temperature": { "target_temperature": {
"value": false, "value": false,
"type": "Number", "type": "Number",
"category": "Primary" "category": "Primary",
"minimum_value": 5,
"maximum_value": 30
}, },
"fan_speed_level": { "fan_speed_level": {
"value": 2, "value": 2,

View File

@ -9,8 +9,8 @@
<HVACMode.HEAT: 'heat'>, <HVACMode.HEAT: 'heat'>,
<HVACMode.OFF: 'off'>, <HVACMode.OFF: 'off'>,
]), ]),
'max_temp': 65536, 'max_temp': 30,
'min_temp': None, 'min_temp': 5,
}), }),
'config_entry_id': <ANY>, 'config_entry_id': <ANY>,
'device_class': None, 'device_class': None,
@ -49,8 +49,8 @@
<HVACMode.HEAT: 'heat'>, <HVACMode.HEAT: 'heat'>,
<HVACMode.OFF: 'off'>, <HVACMode.OFF: 'off'>,
]), ]),
'max_temp': 65536, 'max_temp': 30,
'min_temp': None, 'min_temp': 5,
'supported_features': <ClimateEntityFeature: 385>, 'supported_features': <ClimateEntityFeature: 385>,
'temperature': 22.2, 'temperature': 22.2,
}), }),

View File

@ -41,7 +41,7 @@
}), }),
'area_id': None, 'area_id': None,
'capabilities': dict({ 'capabilities': dict({
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -77,7 +77,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'friendly_name': 'my_device Smooth off', 'friendly_name': 'my_device Smooth off',
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -96,7 +96,7 @@
}), }),
'area_id': None, 'area_id': None,
'capabilities': dict({ 'capabilities': dict({
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -132,7 +132,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'friendly_name': 'my_device Smooth on', 'friendly_name': 'my_device Smooth on',
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -151,7 +151,7 @@
}), }),
'area_id': None, 'area_id': None,
'capabilities': dict({ 'capabilities': dict({
'max': 65536, 'max': 10,
'min': -10, 'min': -10,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -187,7 +187,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'friendly_name': 'my_device Temperature offset', 'friendly_name': 'my_device Temperature offset',
'max': 65536, 'max': 10,
'min': -10, 'min': -10,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -206,7 +206,7 @@
}), }),
'area_id': None, 'area_id': None,
'capabilities': dict({ 'capabilities': dict({
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,
@ -242,7 +242,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'friendly_name': 'my_device Turn off in', 'friendly_name': 'my_device Turn off in',
'max': 65536, 'max': 60,
'min': 0, 'min': 0,
'mode': <NumberMode.BOX: 'box'>, 'mode': <NumberMode.BOX: 'box'>,
'step': 1.0, 'step': 1.0,

View File

@ -54,6 +54,7 @@ from . import (
MAC_ADDRESS, MAC_ADDRESS,
MODEL, MODEL,
_mocked_device, _mocked_device,
_mocked_feature,
_patch_connect, _patch_connect,
_patch_discovery, _patch_discovery,
_patch_single_discovery, _patch_single_discovery,
@ -335,7 +336,14 @@ async def test_update_attrs_fails_in_init(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
light = _mocked_device(modules=[Module.Light], alias="my_light") features = [
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
]
light = _mocked_device(modules=[Module.Light], alias="my_light", features=features)
light_module = light.modules[Module.Light] light_module = light.modules[Module.Light]
p = PropertyMock(side_effect=KasaException) p = PropertyMock(side_effect=KasaException)
type(light_module).color_temp = p type(light_module).color_temp = p
@ -363,7 +371,14 @@ async def test_update_attrs_fails_on_update(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
light = _mocked_device(modules=[Module.Light], alias="my_light") features = [
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
]
light = _mocked_device(modules=[Module.Light], alias="my_light", features=features)
light_module = light.modules[Module.Light] light_module = light.modules[Module.Light]
with _patch_discovery(device=light), _patch_connect(device=light): with _patch_discovery(device=light), _patch_connect(device=light):

View File

@ -54,6 +54,7 @@ from . import (
DEVICE_ID, DEVICE_ID,
MAC_ADDRESS, MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature,
_patch_connect, _patch_connect,
_patch_discovery, _patch_discovery,
_patch_single_discovery, _patch_single_discovery,
@ -118,8 +119,32 @@ async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
("device", "transition"), ("device", "transition"),
[ [
(_mocked_device(modules=[Module.Light]), 2.0), (
(_mocked_device(modules=[Module.Light, Module.LightEffect]), None), _mocked_device(
modules=[Module.Light],
features=[
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
2.0,
),
(
_mocked_device(
modules=[Module.Light, Module.LightEffect],
features=[
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
None,
),
], ],
) )
async def test_color_light( async def test_color_light(
@ -131,7 +156,10 @@ async def test_color_light(
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
light = device.modules[Module.Light] light = device.modules[Module.Light]
# Setting color_temp to None emulates a device with active effects
light.color_temp = None light.color_temp = None
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
await hass.async_block_till_done() await hass.async_block_till_done()
@ -220,9 +248,14 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
device = _mocked_device(modules=[Module.Light], alias="my_light") features = [
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
]
device = _mocked_device(modules=[Module.Light], alias="my_light", features=features)
light = device.modules[Module.Light] light = device.modules[Module.Light]
light.is_variable_color_temp = False
type(light).color_temp = PropertyMock(side_effect=Exception) type(light).color_temp = PropertyMock(side_effect=Exception)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
@ -272,25 +305,47 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
("bulb", "is_color"), ("device", "is_color"),
[ [
(_mocked_device(modules=[Module.Light], alias="my_light"), True), (
(_mocked_device(modules=[Module.Light], alias="my_light"), False), _mocked_device(
modules=[Module.Light],
alias="my_light",
features=[
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
True,
),
(
_mocked_device(
modules=[Module.Light],
alias="my_light",
features=[
_mocked_feature("brightness", value=50),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
False,
),
], ],
) )
async def test_color_temp_light( async def test_color_temp_light(
hass: HomeAssistant, bulb: MagicMock, is_color: bool hass: HomeAssistant, device: MagicMock, is_color: bool
) -> None: ) -> None:
"""Test a light.""" """Test a light."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
device = _mocked_device(modules=[Module.Light], alias="my_light") # device = _mocked_device(modules=[Module.Light], alias="my_light")
light = device.modules[Module.Light] light = device.modules[Module.Light]
light.is_color = is_color
light.color_temp = 4000
light.is_variable_color_temp = True
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
@ -303,7 +358,7 @@ async def test_color_temp_light(
attributes = state.attributes attributes = state.attributes
assert attributes[ATTR_BRIGHTNESS] == 128 assert attributes[ATTR_BRIGHTNESS] == 128
assert attributes[ATTR_COLOR_MODE] == "color_temp" assert attributes[ATTR_COLOR_MODE] == "color_temp"
if light.is_color: if is_color:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"]
else: else:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp"]
@ -368,10 +423,11 @@ async def test_brightness_only_light(hass: HomeAssistant) -> None:
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
device = _mocked_device(modules=[Module.Light], alias="my_light") features = [
_mocked_feature("brightness", value=50),
]
device = _mocked_device(modules=[Module.Light], alias="my_light", features=features)
light = device.modules[Module.Light] light = device.modules[Module.Light]
light.is_color = False
light.is_variable_color_temp = False
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
@ -414,11 +470,8 @@ async def test_on_off_light(hass: HomeAssistant) -> None:
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
device = _mocked_device(modules=[Module.Light], alias="my_light") device = _mocked_device(modules=[Module.Light], alias="my_light", features=[])
light = device.modules[Module.Light] light = device.modules[Module.Light]
light.is_color = False
light.is_variable_color_temp = False
light.is_dimmable = False
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
@ -450,11 +503,9 @@ async def test_off_at_start_light(hass: HomeAssistant) -> None:
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
device = _mocked_device(modules=[Module.Light], alias="my_light") device = _mocked_device(modules=[Module.Light], alias="my_light", features=[])
light = device.modules[Module.Light] light = device.modules[Module.Light]
light.is_color = False
light.is_variable_color_temp = False
light.is_dimmable = False
light.state = LightState(light_on=False) light.state = LightState(light_on=False)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
@ -513,8 +564,15 @@ async def test_smart_strip_effects(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
features = [
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
]
device = _mocked_device( device = _mocked_device(
modules=[Module.Light, Module.LightEffect], alias="my_light" modules=[Module.Light, Module.LightEffect], alias="my_light", features=features
) )
light = device.modules[Module.Light] light = device.modules[Module.Light]
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
@ -977,8 +1035,15 @@ async def test_scene_effect_light(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
features = [
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
]
device = _mocked_device( device = _mocked_device(
modules=[Module.Light, Module.LightEffect], alias="my_light" modules=[Module.Light, Module.LightEffect], alias="my_light", features=features
) )
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF

View File

@ -129,7 +129,7 @@ async def test_color_light_no_emeter(hass: HomeAssistant) -> None:
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
bulb = _mocked_device(alias="my_bulb", modules=[Module.Light]) bulb = _mocked_device(alias="my_bulb", modules=[Module.Light])
bulb.has_emeter = False
with _patch_discovery(device=bulb), _patch_connect(device=bulb): with _patch_discovery(device=bulb), _patch_connect(device=bulb):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
await hass.async_block_till_done() await hass.async_block_till_done()