Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions homeassistant/components/flux_led/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
CONF_COLORS: Final = "colors"
CONF_SPEED_PCT: Final = "speed_pct"
CONF_TRANSITION: Final = "transition"
CONF_EFFECT: Final = "effect"


EFFECT_SPEED_SUPPORT_MODES: Final = {COLOR_MODE_RGB, COLOR_MODE_RGBW, COLOR_MODE_RGBWW}
Expand Down
39 changes: 38 additions & 1 deletion homeassistant/components/flux_led/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from typing import Any, Final

from flux_led.const import MultiColorEffects
from flux_led.utils import (
color_temp_to_white_levels,
rgbcw_brightness,
Expand Down Expand Up @@ -43,6 +44,7 @@
CONF_CUSTOM_EFFECT_COLORS,
CONF_CUSTOM_EFFECT_SPEED_PCT,
CONF_CUSTOM_EFFECT_TRANSITION,
CONF_EFFECT,
CONF_SPEED_PCT,
CONF_TRANSITION,
DEFAULT_EFFECT_SPEED,
Expand All @@ -53,7 +55,12 @@
)
from .coordinator import FluxLedUpdateCoordinator
from .entity import FluxOnOffEntity
from .util import _effect_brightness, _flux_color_mode_to_hass, _hass_color_modes
from .util import (
_effect_brightness,
_flux_color_mode_to_hass,
_hass_color_modes,
_str_to_multi_color_effect,
)

_LOGGER = logging.getLogger(__name__)

Expand All @@ -73,6 +80,7 @@
EFFECT_CUSTOM: Final = "custom"

SERVICE_CUSTOM_EFFECT: Final = "set_custom_effect"
SERVICE_SET_ZONES: Final = "set_zones"

CUSTOM_EFFECT_DICT: Final = {
vol.Required(CONF_COLORS): vol.All(
Expand All @@ -88,6 +96,20 @@
),
}

SET_ZONES_DICT: Final = {
vol.Required(CONF_COLORS): vol.All(
cv.ensure_list,
vol.Length(min=1, max=2048),
[vol.All(vol.Coerce(tuple), vol.ExactSequence((cv.byte, cv.byte, cv.byte)))],
),
vol.Optional(CONF_SPEED_PCT, default=50): vol.All(
vol.Range(min=0, max=100), vol.Coerce(int)
),
vol.Optional(CONF_EFFECT, default=MultiColorEffects.STATIC.name.lower()): vol.All(
cv.string, vol.In([effect.name.lower() for effect in MultiColorEffects])
),
}


async def async_setup_entry(
hass: HomeAssistant,
Expand All @@ -103,6 +125,11 @@ async def async_setup_entry(
CUSTOM_EFFECT_DICT,
"async_set_custom_effect",
)
platform.async_register_entity_service(
SERVICE_SET_ZONES,
SET_ZONES_DICT,
"async_set_zones",
)
options = entry.options

try:
Expand Down Expand Up @@ -293,3 +320,13 @@ async def async_set_custom_effect(
speed_pct,
transition,
)

async def async_set_zones(
self, colors: list[tuple[int, int, int]], speed_pct: int, effect: str
) -> None:
"""Set a colors for zones."""
await self._device.async_set_zones(
colors,
speed_pct,
_str_to_multi_color_effect(effect),
)
41 changes: 41 additions & 0 deletions homeassistant/components/flux_led/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,44 @@ set_custom_effect:
- "gradual"
- "jump"
- "strobe"
set_zones:
description: Set strip zones for Addressable v3 controllers (0xA3).
target:
entity:
integration: flux_led
domain: light
fields:
colors:
description: List of colors for each zone (RGB). The length of each zone is the number of pixels per segment divided by the number of colors. (Max 2048 Colors)
example: |
- [255,0,0]
- [0,255,0]
- [0,0,255]
- [255,255,255]
required: true
selector:
object:
speed_pct:
description: Effect speed for the custom effect (0-100)
example: 80
default: 50
required: false
selector:
number:
min: 1
step: 1
max: 100
unit_of_measurement: "%"
effect:
description: Effect
example: 'running_water'
default: 'static'
required: false
selector:
select:
options:
- "static"
- "running_water"
- "strobe"
- "jump"
- "breathing"
11 changes: 10 additions & 1 deletion homeassistant/components/flux_led/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import annotations

from flux_led.aio import AIOWifiLedBulb
from flux_led.const import COLOR_MODE_DIM as FLUX_COLOR_MODE_DIM
from flux_led.const import COLOR_MODE_DIM as FLUX_COLOR_MODE_DIM, MultiColorEffects

from homeassistant.components.light import (
COLOR_MODE_BRIGHTNESS,
Expand Down Expand Up @@ -34,3 +34,12 @@ def _flux_color_mode_to_hass(
def _effect_brightness(brightness: int) -> int:
"""Convert hass brightness to effect brightness."""
return round(brightness / 255 * 100)


def _str_to_multi_color_effect(effect_str: str) -> MultiColorEffects:
"""Convert an multicolor effect string to MultiColorEffects."""
for effect in MultiColorEffects:
if effect.name.lower() == effect_str:
return effect
# unreachable due to schema validation
assert False # pragma: no cover
32 changes: 32 additions & 0 deletions tests/components/flux_led/test_light.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
COLOR_MODE_RGBW as FLUX_COLOR_MODE_RGBW,
COLOR_MODE_RGBWW as FLUX_COLOR_MODE_RGBWW,
COLOR_MODES_RGB_W as FLUX_COLOR_MODES_RGB_W,
MultiColorEffects,
)
import pytest

Expand All @@ -19,6 +20,7 @@
CONF_CUSTOM_EFFECT_COLORS,
CONF_CUSTOM_EFFECT_SPEED_PCT,
CONF_CUSTOM_EFFECT_TRANSITION,
CONF_EFFECT,
CONF_SPEED_PCT,
CONF_TRANSITION,
DOMAIN,
Expand Down Expand Up @@ -1119,6 +1121,36 @@ async def test_rgb_light_custom_effect_via_service(
)
bulb.async_set_custom_pattern.reset_mock()

await hass.services.async_call(
DOMAIN,
"set_zones",
{
ATTR_ENTITY_ID: entity_id,
CONF_COLORS: [[0, 0, 255], [255, 0, 0]],
CONF_EFFECT: "running_water",
},
blocking=True,
)
bulb.async_set_zones.assert_called_with(
[(0, 0, 255), (255, 0, 0)], 50, MultiColorEffects.RUNNING_WATER
)
bulb.async_set_zones.reset_mock()

await hass.services.async_call(
DOMAIN,
"set_zones",
{
ATTR_ENTITY_ID: entity_id,
CONF_COLORS: [[0, 0, 255], [255, 0, 0]],
CONF_SPEED_PCT: 30,
},
blocking=True,
)
bulb.async_set_zones.assert_called_with(
[(0, 0, 255), (255, 0, 0)], 30, MultiColorEffects.STATIC
)
bulb.async_set_zones.reset_mock()


async def test_addressable_light(hass: HomeAssistant) -> None:
"""Test an addressable light."""
Expand Down