Add set_music_mode service to flux_led for detailed music mode control (#62429)

This commit is contained in:
J. Nick Koston 2021-12-21 05:09:41 -06:00 committed by GitHub
parent eb897c6f48
commit 4b30c9631f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 169 additions and 5 deletions

View File

@ -76,6 +76,11 @@ class FluxEntity(CoordinatorEntity):
unique_id, self._device, coordinator.entry
)
async def _async_ensure_device_on(self) -> None:
"""Turn the device on if it needs to be turned on before a command."""
if self._device.requires_turn_on and not self._device.is_on:
await self._device.async_turn_on()
@property
def extra_state_attributes(self) -> dict[str, str]:
"""Return the attributes."""

View File

@ -6,6 +6,7 @@ import logging
from typing import Any, Final
from flux_led.const import MultiColorEffects
from flux_led.protocol import MusicMode
from flux_led.utils import (
color_temp_to_white_levels,
rgbcw_brightness,
@ -73,6 +74,11 @@ MODE_ATTRS = {
ATTR_WHITE,
}
ATTR_FOREGROUND_COLOR: Final = "foreground_color"
ATTR_BACKGROUND_COLOR: Final = "background_color"
ATTR_SENSITIVITY: Final = "sensitivity"
ATTR_LIGHT_SCREEN: Final = "light_screen"
# Constant color temp values for 2 flux_led special modes
# Warm-white and Cool-white modes
COLOR_TEMP_WARM_VS_COLD_WHITE_CUT_OFF: Final = 285
@ -81,6 +87,7 @@ EFFECT_CUSTOM: Final = "custom"
SERVICE_CUSTOM_EFFECT: Final = "set_custom_effect"
SERVICE_SET_ZONES: Final = "set_zones"
SERVICE_SET_MUSIC_MODE: Final = "set_music_mode"
CUSTOM_EFFECT_DICT: Final = {
vol.Required(CONF_COLORS): vol.All(
@ -96,6 +103,25 @@ CUSTOM_EFFECT_DICT: Final = {
),
}
SET_MUSIC_MODE_DICT: Final = {
vol.Optional(ATTR_SENSITIVITY, default=100): vol.All(
vol.Range(min=0, max=100), vol.Coerce(int)
),
vol.Optional(ATTR_BRIGHTNESS, default=100): vol.All(
vol.Range(min=0, max=100), vol.Coerce(int)
),
vol.Optional(ATTR_EFFECT, default=1): vol.All(
vol.Range(min=1, max=16), vol.Coerce(int)
),
vol.Optional(ATTR_LIGHT_SCREEN, default=False): bool,
vol.Optional(ATTR_FOREGROUND_COLOR): vol.All(
vol.Coerce(tuple), vol.ExactSequence((cv.byte,) * 3)
),
vol.Optional(ATTR_BACKGROUND_COLOR): vol.All(
vol.Coerce(tuple), vol.ExactSequence((cv.byte,) * 3)
),
}
SET_ZONES_DICT: Final = {
vol.Required(CONF_COLORS): vol.All(
cv.ensure_list,
@ -130,6 +156,11 @@ async def async_setup_entry(
SET_ZONES_DICT,
"async_set_zones",
)
platform.async_register_entity_service(
SERVICE_SET_MUSIC_MODE,
SET_MUSIC_MODE_DICT,
"async_set_music_mode",
)
options = entry.options
try:
@ -330,3 +361,23 @@ class FluxLight(FluxOnOffEntity, CoordinatorEntity, LightEntity):
speed_pct,
_str_to_multi_color_effect(effect),
)
async def async_set_music_mode(
self,
sensitivity: int,
brightness: int,
effect: int,
light_screen: bool,
foreground_color: tuple[int, int, int] | None = None,
background_color: tuple[int, int, int] | None = None,
) -> None:
"""Configure music mode."""
await self._async_ensure_device_on()
await self._device.async_set_music_mode(
sensitivity=sensitivity,
brightness=brightness,
mode=MusicMode.LIGHT_SCREEN.value if light_screen else None,
effect=effect,
foreground_color=foreground_color,
background_color=background_color,
)

View File

@ -4,7 +4,7 @@
"config_flow": true,
"dependencies": ["network"],
"documentation": "https://www.home-assistant.io/integrations/flux_led",
"requirements": ["flux_led==0.27.8"],
"requirements": ["flux_led==0.27.10"],
"quality_scale": "platinum",
"codeowners": ["@icemanch"],
"iot_class": "local_push",

View File

@ -77,3 +77,60 @@ set_zones:
- "strobe"
- "jump"
- "breathing"
set_music_mode:
description: Configure music mode on Controller RGB with MIC (0x08), Addressable v2 (0xA2), and Addressable v3 (0xA3) devices that have a built-in microphone.
target:
entity:
integration: flux_led
domain: light
fields:
sensitivity:
description: Microphone sensitivity (0-100)
example: 80
default: 100
required: false
selector:
number:
min: 1
step: 1
max: 100
unit_of_measurement: "%"
brightness:
description: Light brightness (0-100)
example: 80
default: 100
required: false
selector:
number:
min: 1
step: 1
max: 100
unit_of_measurement: "%"
light_screen:
description: Light screen mode for 2 dimensional pixels (Addressable models only)
default: false
required: false
selector:
boolean:
effect:
description: Effect (1-16 on Addressable models, 0-3 on RGB with MIC models)
example: 1
default: 1
required: false
selector:
number:
min: 0
step: 1
max: 16
foreground_color:
description: The foreground RGB color
example: "[255, 100, 100]"
required: false
selector:
object:
background_color:
description: The background RGB color (Addressable models only)
example: "[255, 100, 100]"
required: false
selector:
object:

View File

@ -126,8 +126,7 @@ class FluxMusicSwitch(FluxEntity, SwitchEntity):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the microphone on."""
if self._device.requires_turn_on and not self._device.is_on:
await self._device.async_turn_on()
await self._async_ensure_device_on()
await self._device.async_set_music_mode()
self.async_write_ha_state()
await self.coordinator.async_request_refresh()

View File

@ -664,7 +664,7 @@ fjaraskupan==1.0.2
flipr-api==1.4.1
# homeassistant.components.flux_led
flux_led==0.27.8
flux_led==0.27.10
# homeassistant.components.homekit
fnvhash==0.1.0

View File

@ -405,7 +405,7 @@ fjaraskupan==1.0.2
flipr-api==1.4.1
# homeassistant.components.flux_led
flux_led==0.27.8
flux_led==0.27.10
# homeassistant.components.homekit
fnvhash==0.1.0

View File

@ -10,8 +10,10 @@ 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,
MODE_MUSIC,
MultiColorEffects,
)
from flux_led.protocol import MusicMode
import pytest
from homeassistant.components import flux_led
@ -26,6 +28,12 @@ from homeassistant.components.flux_led.const import (
DOMAIN,
TRANSITION_JUMP,
)
from homeassistant.components.flux_led.light import (
ATTR_BACKGROUND_COLOR,
ATTR_FOREGROUND_COLOR,
ATTR_LIGHT_SCREEN,
ATTR_SENSITIVITY,
)
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_MODE,
@ -1191,3 +1199,47 @@ async def test_addressable_light(hass: HomeAssistant) -> None:
bulb.async_turn_on.assert_called_once()
bulb.async_turn_on.reset_mock()
await async_mock_device_turn_on(hass, bulb)
async def test_music_mode_service(hass: HomeAssistant) -> None:
"""Test music mode service."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE},
unique_id=MAC_ADDRESS,
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.raw_state = bulb.raw_state._replace(model_num=0xA3) # has music mode
bulb.microphone = True
with _patch_discovery(), _patch_wifibulb(device=bulb):
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
await hass.async_block_till_done()
entity_id = "light.bulb_rgbcw_ddeeff"
assert hass.states.get(entity_id)
bulb.effect = MODE_MUSIC
bulb.is_on = False
await hass.services.async_call(
DOMAIN,
"set_music_mode",
{
ATTR_ENTITY_ID: entity_id,
ATTR_EFFECT: 12,
ATTR_LIGHT_SCREEN: True,
ATTR_SENSITIVITY: 50,
ATTR_BRIGHTNESS: 50,
ATTR_FOREGROUND_COLOR: [255, 0, 0],
ATTR_BACKGROUND_COLOR: [0, 255, 0],
},
blocking=True,
)
bulb.async_set_music_mode.assert_called_once_with(
sensitivity=50,
brightness=50,
mode=MusicMode.LIGHT_SCREEN.value,
effect=12,
foreground_color=(255, 0, 0),
background_color=(0, 255, 0),
)