mirror of https://github.com/home-assistant/core
Add support for the Flame and Morph effects for Tile and Candle (#80014)
This commit is contained in:
parent
117c12d135
commit
257ae4d8d3
|
@ -7,7 +7,12 @@ from enum import IntEnum
|
|||
from functools import partial
|
||||
from typing import Any, cast
|
||||
|
||||
from aiolifx.aiolifx import Light, MultiZoneDirection, MultiZoneEffectType
|
||||
from aiolifx.aiolifx import (
|
||||
Light,
|
||||
MultiZoneDirection,
|
||||
MultiZoneEffectType,
|
||||
TileEffectType,
|
||||
)
|
||||
from aiolifx.connection import LIFXConnection
|
||||
|
||||
from homeassistant.const import Platform
|
||||
|
@ -279,7 +284,11 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
|
|||
self.active_effect = FirmwareEffect[self.device.effect.get("effect", "OFF")]
|
||||
|
||||
async def async_set_multizone_effect(
|
||||
self, effect: str, speed: float, direction: str, power_on: bool = True
|
||||
self,
|
||||
effect: str,
|
||||
speed: float = 3,
|
||||
direction: str = "RIGHT",
|
||||
power_on: bool = True,
|
||||
) -> None:
|
||||
"""Control the firmware-based Move effect on a multizone device."""
|
||||
if lifx_features(self.device)["multizone"] is True:
|
||||
|
@ -296,6 +305,31 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
|
|||
)
|
||||
self.active_effect = FirmwareEffect[effect.upper()]
|
||||
|
||||
async def async_set_matrix_effect(
|
||||
self,
|
||||
effect: str,
|
||||
palette: list[tuple[int, int, int, int]] | None = None,
|
||||
speed: float = 3,
|
||||
power_on: bool = True,
|
||||
) -> None:
|
||||
"""Control the firmware-based effects on a matrix device."""
|
||||
if lifx_features(self.device)["matrix"] is True:
|
||||
if power_on and self.device.power_level == 0:
|
||||
await self.async_set_power(True, 0)
|
||||
|
||||
if palette is None:
|
||||
palette = []
|
||||
|
||||
await async_execute_lifx(
|
||||
partial(
|
||||
self.device.set_tile_effect,
|
||||
effect=TileEffectType[effect.upper()].value,
|
||||
speed=speed,
|
||||
palette=palette,
|
||||
)
|
||||
)
|
||||
self.active_effect = FirmwareEffect[effect.upper()]
|
||||
|
||||
def async_get_active_effect(self) -> int:
|
||||
"""Return the enum value of the currently active firmware effect."""
|
||||
return self.active_effect.value
|
||||
|
|
|
@ -40,6 +40,8 @@ from .coordinator import FirmwareEffect, LIFXUpdateCoordinator
|
|||
from .entity import LIFXEntity
|
||||
from .manager import (
|
||||
SERVICE_EFFECT_COLORLOOP,
|
||||
SERVICE_EFFECT_FLAME,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
SERVICE_EFFECT_MOVE,
|
||||
SERVICE_EFFECT_PULSE,
|
||||
SERVICE_EFFECT_STOP,
|
||||
|
@ -93,8 +95,10 @@ async def async_setup_entry(
|
|||
LIFX_SET_HEV_CYCLE_STATE_SCHEMA,
|
||||
"set_hev_cycle_state",
|
||||
)
|
||||
if lifx_features(device)["extended_multizone"]:
|
||||
entity: LIFXLight = LIFXExtendedMultiZone(coordinator, manager, entry)
|
||||
if lifx_features(device)["matrix"]:
|
||||
entity: LIFXLight = LIFXMatrix(coordinator, manager, entry)
|
||||
elif lifx_features(device)["extended_multizone"]:
|
||||
entity = LIFXExtendedMultiZone(coordinator, manager, entry)
|
||||
elif lifx_features(device)["multizone"]:
|
||||
entity = LIFXMultiZone(coordinator, manager, entry)
|
||||
elif lifx_features(device)["color"]:
|
||||
|
@ -471,3 +475,15 @@ class LIFXExtendedMultiZone(LIFXMultiZone):
|
|||
# set_extended_color_zones does not update the
|
||||
# state of the device, so we need to do that
|
||||
await self.get_color()
|
||||
|
||||
|
||||
class LIFXMatrix(LIFXColor):
|
||||
"""Representation of a LIFX matrix device."""
|
||||
|
||||
_attr_effect_list = [
|
||||
SERVICE_EFFECT_COLORLOOP,
|
||||
SERVICE_EFFECT_FLAME,
|
||||
SERVICE_EFFECT_PULSE,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
SERVICE_EFFECT_STOP,
|
||||
]
|
||||
|
|
|
@ -7,6 +7,7 @@ from datetime import timedelta
|
|||
from typing import Any
|
||||
|
||||
import aiolifx_effects
|
||||
from aiolifx_themes.themes import Theme, ThemeLibrary
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.light import (
|
||||
|
@ -34,9 +35,11 @@ from .util import convert_8_to_16, find_hsbk
|
|||
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
|
||||
SERVICE_EFFECT_PULSE = "effect_pulse"
|
||||
SERVICE_EFFECT_COLORLOOP = "effect_colorloop"
|
||||
SERVICE_EFFECT_FLAME = "effect_flame"
|
||||
SERVICE_EFFECT_MORPH = "effect_morph"
|
||||
SERVICE_EFFECT_MOVE = "effect_move"
|
||||
SERVICE_EFFECT_PULSE = "effect_pulse"
|
||||
SERVICE_EFFECT_STOP = "effect_stop"
|
||||
|
||||
ATTR_POWER_OFF = "power_off"
|
||||
|
@ -47,11 +50,20 @@ ATTR_SPREAD = "spread"
|
|||
ATTR_CHANGE = "change"
|
||||
ATTR_DIRECTION = "direction"
|
||||
ATTR_SPEED = "speed"
|
||||
ATTR_PALETTE = "palette"
|
||||
ATTR_THEME = "theme"
|
||||
|
||||
EFFECT_FLAME = "FLAME"
|
||||
EFFECT_MORPH = "MORPH"
|
||||
EFFECT_MOVE = "MOVE"
|
||||
EFFECT_OFF = "OFF"
|
||||
|
||||
EFFECT_MOVE_DEFAULT_SPEED = 3.0
|
||||
EFFECT_FLAME_DEFAULT_SPEED = 3
|
||||
|
||||
EFFECT_MORPH_DEFAULT_SPEED = 3
|
||||
EFFECT_MORPH_DEFAULT_THEME = "exciting"
|
||||
|
||||
EFFECT_MOVE_DEFAULT_SPEED = 3
|
||||
EFFECT_MOVE_DEFAULT_DIRECTION = "right"
|
||||
EFFECT_MOVE_DIRECTION_RIGHT = "right"
|
||||
EFFECT_MOVE_DIRECTION_LEFT = "left"
|
||||
|
@ -128,6 +140,37 @@ SERVICES = (
|
|||
SERVICE_EFFECT_COLORLOOP,
|
||||
)
|
||||
|
||||
LIFX_EFFECT_FLAME_SCHEMA = cv.make_entity_service_schema(
|
||||
{
|
||||
**LIFX_EFFECT_SCHEMA,
|
||||
ATTR_SPEED: vol.All(vol.Coerce(int), vol.Clamp(min=1, max=25)),
|
||||
}
|
||||
)
|
||||
|
||||
HSBK_SCHEMA = vol.All(
|
||||
vol.Coerce(tuple),
|
||||
vol.ExactSequence(
|
||||
(
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=360)),
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=100)),
|
||||
vol.All(vol.Coerce(float), vol.Clamp(min=0, max=100)),
|
||||
vol.All(vol.Coerce(int), vol.Clamp(min=1500, max=9000)),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
LIFX_EFFECT_MORPH_SCHEMA = cv.make_entity_service_schema(
|
||||
{
|
||||
**LIFX_EFFECT_SCHEMA,
|
||||
ATTR_SPEED: vol.All(vol.Coerce(int), vol.Clamp(min=1, max=25)),
|
||||
vol.Exclusive(ATTR_THEME, COLOR_GROUP): vol.Optional(
|
||||
vol.In(ThemeLibrary().themes)
|
||||
),
|
||||
vol.Exclusive(ATTR_PALETTE, COLOR_GROUP): vol.All(
|
||||
cv.ensure_list, [HSBK_SCHEMA]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
LIFX_EFFECT_MOVE_SCHEMA = cv.make_entity_service_schema(
|
||||
{
|
||||
|
@ -192,6 +235,20 @@ class LIFXManager:
|
|||
schema=LIFX_EFFECT_COLORLOOP_SCHEMA,
|
||||
)
|
||||
|
||||
self.hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT_FLAME,
|
||||
service_handler,
|
||||
schema=LIFX_EFFECT_FLAME_SCHEMA,
|
||||
)
|
||||
|
||||
self.hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
service_handler,
|
||||
schema=LIFX_EFFECT_MORPH_SCHEMA,
|
||||
)
|
||||
|
||||
self.hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT_MOVE,
|
||||
|
@ -222,7 +279,43 @@ class LIFXManager:
|
|||
coordinators.append(coordinator)
|
||||
bulbs.append(coordinator.device)
|
||||
|
||||
if service == SERVICE_EFFECT_MOVE:
|
||||
if service == SERVICE_EFFECT_FLAME:
|
||||
await asyncio.gather(
|
||||
*(
|
||||
coordinator.async_set_matrix_effect(
|
||||
effect=EFFECT_FLAME,
|
||||
speed=kwargs.get(ATTR_SPEED, EFFECT_FLAME_DEFAULT_SPEED),
|
||||
power_on=kwargs.get(ATTR_POWER_ON, True),
|
||||
)
|
||||
for coordinator in coordinators
|
||||
)
|
||||
)
|
||||
|
||||
elif service == SERVICE_EFFECT_MORPH:
|
||||
|
||||
theme_name = kwargs.get(ATTR_THEME, "exciting")
|
||||
palette = kwargs.get(ATTR_PALETTE, None)
|
||||
|
||||
if palette is not None:
|
||||
theme = Theme()
|
||||
for hsbk in palette:
|
||||
theme.add_hsbk(hsbk[0], hsbk[1], hsbk[2], hsbk[3])
|
||||
else:
|
||||
theme = ThemeLibrary().get_theme(theme_name)
|
||||
|
||||
await asyncio.gather(
|
||||
*(
|
||||
coordinator.async_set_matrix_effect(
|
||||
effect=EFFECT_MORPH,
|
||||
speed=kwargs.get(ATTR_SPEED, EFFECT_MORPH_DEFAULT_SPEED),
|
||||
palette=theme.colors,
|
||||
power_on=kwargs.get(ATTR_POWER_ON, True),
|
||||
)
|
||||
for coordinator in coordinators
|
||||
)
|
||||
)
|
||||
|
||||
elif service == SERVICE_EFFECT_MOVE:
|
||||
await asyncio.gather(
|
||||
*(
|
||||
coordinator.async_set_multizone_effect(
|
||||
|
@ -269,9 +362,9 @@ class LIFXManager:
|
|||
await self.effects_conductor.stop(bulbs)
|
||||
|
||||
for coordinator in coordinators:
|
||||
await coordinator.async_set_multizone_effect(
|
||||
effect=EFFECT_OFF,
|
||||
speed=EFFECT_MOVE_DEFAULT_SPEED,
|
||||
direction=EFFECT_MOVE_DEFAULT_DIRECTION,
|
||||
power_on=False,
|
||||
await coordinator.async_set_matrix_effect(
|
||||
effect=EFFECT_OFF, power_on=False
|
||||
)
|
||||
await coordinator.async_set_multizone_effect(
|
||||
effect=EFFECT_OFF, power_on=False
|
||||
)
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
"name": "LIFX",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/lifx",
|
||||
"requirements": ["aiolifx==0.8.6", "aiolifx_effects==0.2.2"],
|
||||
"requirements": [
|
||||
"aiolifx==0.8.6",
|
||||
"aiolifx_effects==0.2.2",
|
||||
"aiolifx_themes==0.1.1"
|
||||
],
|
||||
"quality_scale": "platinum",
|
||||
"dependencies": ["network"],
|
||||
"homekit": {
|
||||
|
|
|
@ -205,7 +205,91 @@ effect_move:
|
|||
default: true
|
||||
selector:
|
||||
boolean:
|
||||
|
||||
effect_flame:
|
||||
name: Flame effect
|
||||
description: Start the firmware-based Flame effect on LIFX Tiles or Candle.
|
||||
target:
|
||||
entity:
|
||||
integration: lifx
|
||||
domain: light
|
||||
fields:
|
||||
speed:
|
||||
name: Speed
|
||||
description: How fast the flames will move.
|
||||
default: 3
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 25
|
||||
step: 1
|
||||
unit_of_measurement: seconds
|
||||
power_on:
|
||||
name: Power on
|
||||
description: Powered off lights will be turned on before starting the effect.
|
||||
default: true
|
||||
selector:
|
||||
boolean:
|
||||
effect_morph:
|
||||
name: Morph effect
|
||||
description: Start the firmware-based Morph effect on LIFX Tiles on Candle.
|
||||
target:
|
||||
entity:
|
||||
integration: lifx
|
||||
domain: light
|
||||
fields:
|
||||
speed:
|
||||
name: Speed
|
||||
description: How fast the colors will move.
|
||||
default: 3
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 25
|
||||
step: 1
|
||||
unit_of_measurement: seconds
|
||||
palette:
|
||||
name: Palette
|
||||
description: List of at least 2 and at most 16 colors as hue (0-360), saturation (0-100), brightness (0-100) and kelvin (1500-900) values to use for this effect. Overrides the theme attribute.
|
||||
example:
|
||||
- "[[0, 100, 100, 3500], [60, 100, 100, 3500]]"
|
||||
selector:
|
||||
object:
|
||||
theme:
|
||||
name: Theme
|
||||
description: Predefined color theme to use for the effect. Overridden by the palette attribute.
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "autumn"
|
||||
- "blissful"
|
||||
- "cheerful"
|
||||
- "dream"
|
||||
- "energizing"
|
||||
- "epic"
|
||||
- "exciting"
|
||||
- "focusing"
|
||||
- "halloween"
|
||||
- "hanukkah"
|
||||
- "holly"
|
||||
- "independence day"
|
||||
- "intense"
|
||||
- "mellow"
|
||||
- "peaceful"
|
||||
- "powerful"
|
||||
- "relaxing"
|
||||
- "santa"
|
||||
- "serene"
|
||||
- "soothing"
|
||||
- "sports"
|
||||
- "spring"
|
||||
- "tranquil"
|
||||
- "warming"
|
||||
power_on:
|
||||
name: Power on
|
||||
description: Powered off lights will be turned on before starting the effect.
|
||||
default: true
|
||||
selector:
|
||||
boolean:
|
||||
effect_stop:
|
||||
name: Stop effect
|
||||
description: Stop a running effect.
|
||||
|
|
|
@ -198,6 +198,9 @@ aiolifx==0.8.6
|
|||
# homeassistant.components.lifx
|
||||
aiolifx_effects==0.2.2
|
||||
|
||||
# homeassistant.components.lifx
|
||||
aiolifx_themes==0.1.1
|
||||
|
||||
# homeassistant.components.lookin
|
||||
aiolookin==0.1.1
|
||||
|
||||
|
|
|
@ -176,6 +176,9 @@ aiolifx==0.8.6
|
|||
# homeassistant.components.lifx
|
||||
aiolifx_effects==0.2.2
|
||||
|
||||
# homeassistant.components.lifx
|
||||
aiolifx_themes==0.1.1
|
||||
|
||||
# homeassistant.components.lookin
|
||||
aiolookin==0.1.1
|
||||
|
||||
|
|
|
@ -156,6 +156,15 @@ def _mocked_light_strip() -> Light:
|
|||
return bulb
|
||||
|
||||
|
||||
def _mocked_tile() -> Light:
|
||||
bulb = _mocked_bulb()
|
||||
bulb.product = 55 # LIFX Tile
|
||||
bulb.effect = {"effect": "OFF"}
|
||||
bulb.get_tile_effect = MockLifxCommand(bulb)
|
||||
bulb.set_tile_effect = MockLifxCommand(bulb)
|
||||
return bulb
|
||||
|
||||
|
||||
def _mocked_bulb_new_firmware() -> Light:
|
||||
bulb = _mocked_bulb()
|
||||
bulb.host_firmware_version = "3.90"
|
||||
|
|
|
@ -12,8 +12,11 @@ from homeassistant.components.lifx.const import ATTR_POWER
|
|||
from homeassistant.components.lifx.light import ATTR_INFRARED, ATTR_ZONES
|
||||
from homeassistant.components.lifx.manager import (
|
||||
ATTR_DIRECTION,
|
||||
ATTR_PALETTE,
|
||||
ATTR_SPEED,
|
||||
ATTR_THEME,
|
||||
SERVICE_EFFECT_COLORLOOP,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
SERVICE_EFFECT_MOVE,
|
||||
)
|
||||
from homeassistant.components.light import (
|
||||
|
@ -55,6 +58,7 @@ from . import (
|
|||
_mocked_bulb_new_firmware,
|
||||
_mocked_clean_bulb,
|
||||
_mocked_light_strip,
|
||||
_mocked_tile,
|
||||
_mocked_white_bulb,
|
||||
_patch_config_flow_try_connect,
|
||||
_patch_device,
|
||||
|
@ -650,6 +654,146 @@ async def test_extended_multizone_messages(hass: HomeAssistant) -> None:
|
|||
)
|
||||
|
||||
|
||||
async def test_matrix_flame_morph_effects(hass: HomeAssistant) -> None:
|
||||
"""Test the firmware flame and morph effects on a matrix device."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=SERIAL
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
bulb = _mocked_tile()
|
||||
bulb.power_level = 0
|
||||
bulb.color = [65535, 65535, 65535, 65535]
|
||||
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||
device=bulb
|
||||
), _patch_device(device=bulb):
|
||||
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.my_bulb"
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "effect_flame"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(bulb.set_power.calls) == 1
|
||||
assert len(bulb.set_tile_effect.calls) == 1
|
||||
|
||||
call_dict = bulb.set_tile_effect.calls[0][1]
|
||||
call_dict.pop("callb")
|
||||
assert call_dict == {
|
||||
"effect": 3,
|
||||
"speed": 3,
|
||||
"palette": [],
|
||||
}
|
||||
bulb.get_tile_effect.reset_mock()
|
||||
bulb.set_tile_effect.reset_mock()
|
||||
bulb.set_power.reset_mock()
|
||||
|
||||
bulb.power_level = 0
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_SPEED: 4, ATTR_THEME: "autumn"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
bulb.power_level = 65535
|
||||
bulb.effect = {
|
||||
"effect": "MORPH",
|
||||
"speed": 4.0,
|
||||
"palette": [
|
||||
(5643, 65535, 32768, 3500),
|
||||
(15109, 65535, 32768, 3500),
|
||||
(8920, 65535, 32768, 3500),
|
||||
(10558, 65535, 32768, 3500),
|
||||
],
|
||||
}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
assert len(bulb.set_power.calls) == 1
|
||||
assert len(bulb.set_tile_effect.calls) == 1
|
||||
call_dict = bulb.set_tile_effect.calls[0][1]
|
||||
call_dict.pop("callb")
|
||||
assert call_dict == {
|
||||
"effect": 2,
|
||||
"speed": 4,
|
||||
"palette": [
|
||||
(5643, 65535, 32768, 3500),
|
||||
(15109, 65535, 32768, 3500),
|
||||
(8920, 65535, 32768, 3500),
|
||||
(10558, 65535, 32768, 3500),
|
||||
],
|
||||
}
|
||||
bulb.get_tile_effect.reset_mock()
|
||||
bulb.set_tile_effect.reset_mock()
|
||||
bulb.set_power.reset_mock()
|
||||
|
||||
bulb.power_level = 0
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT_MORPH,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
ATTR_SPEED: 6,
|
||||
ATTR_PALETTE: [
|
||||
(0, 100, 255, 3500),
|
||||
(60, 100, 255, 3500),
|
||||
(120, 100, 255, 3500),
|
||||
(180, 100, 255, 3500),
|
||||
(240, 100, 255, 3500),
|
||||
(300, 100, 255, 3500),
|
||||
],
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
bulb.power_level = 65535
|
||||
bulb.effect = {
|
||||
"effect": "MORPH",
|
||||
"speed": 6,
|
||||
"palette": [
|
||||
(0, 65535, 65535, 3500),
|
||||
(10922, 65535, 65535, 3500),
|
||||
(21845, 65535, 65535, 3500),
|
||||
(32768, 65535, 65535, 3500),
|
||||
(43690, 65535, 65535, 3500),
|
||||
(54612, 65535, 65535, 3500),
|
||||
],
|
||||
}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
assert len(bulb.set_power.calls) == 1
|
||||
assert len(bulb.set_tile_effect.calls) == 1
|
||||
call_dict = bulb.set_tile_effect.calls[0][1]
|
||||
call_dict.pop("callb")
|
||||
assert call_dict == {
|
||||
"effect": 2,
|
||||
"speed": 6,
|
||||
"palette": [
|
||||
(0, 65535, 65535, 3500),
|
||||
(10922, 65535, 65535, 3500),
|
||||
(21845, 65535, 65535, 3500),
|
||||
(32768, 65535, 65535, 3500),
|
||||
(43690, 65535, 65535, 3500),
|
||||
(54613, 65535, 65535, 3500),
|
||||
],
|
||||
}
|
||||
bulb.get_tile_effect.reset_mock()
|
||||
bulb.set_tile_effect.reset_mock()
|
||||
bulb.set_power.reset_mock()
|
||||
|
||||
|
||||
async def test_lightstrip_move_effect(hass: HomeAssistant) -> None:
|
||||
"""Test the firmware move effect on a light strip."""
|
||||
config_entry = MockConfigEntry(
|
||||
|
@ -697,7 +841,7 @@ async def test_lightstrip_move_effect(hass: HomeAssistant) -> None:
|
|||
)
|
||||
|
||||
bulb.power_level = 65535
|
||||
bulb.effect = {"name": "effect_move", "enable": 1}
|
||||
bulb.effect = {"name": "MOVE", "speed": 4.5, "direction": "Left"}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
|
Loading…
Reference in New Issue