Add zones support to flux_led (#61072)

pull/62377/head^2
J. Nick Koston 2021-12-20 06:45:34 -06:00 committed by GitHub
parent 3d75befe0a
commit abc7dcf6bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 122 additions and 2 deletions

View File

@ -62,6 +62,7 @@ TRANSITION_STROBE: Final = "strobe"
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}

View File

@ -5,6 +5,7 @@ import ast
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,
@ -43,6 +44,7 @@ from .const import (
CONF_CUSTOM_EFFECT_COLORS,
CONF_CUSTOM_EFFECT_SPEED_PCT,
CONF_CUSTOM_EFFECT_TRANSITION,
CONF_EFFECT,
CONF_SPEED_PCT,
CONF_TRANSITION,
DEFAULT_EFFECT_SPEED,
@ -53,7 +55,12 @@ from .const import (
)
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__)
@ -73,6 +80,7 @@ COLOR_TEMP_WARM_VS_COLD_WHITE_CUT_OFF: Final = 285
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(
@ -88,6 +96,20 @@ CUSTOM_EFFECT_DICT: Final = {
),
}
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,
@ -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:
@ -293,3 +320,13 @@ class FluxLight(FluxOnOffEntity, CoordinatorEntity, LightEntity):
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),
)

View File

@ -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"

View File

@ -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,
@ -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

View File

@ -10,6 +10,7 @@ from flux_led.const import (
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
@ -19,6 +20,7 @@ from homeassistant.components.flux_led.const import (
CONF_CUSTOM_EFFECT_COLORS,
CONF_CUSTOM_EFFECT_SPEED_PCT,
CONF_CUSTOM_EFFECT_TRANSITION,
CONF_EFFECT,
CONF_SPEED_PCT,
CONF_TRANSITION,
DOMAIN,
@ -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."""