Add support for changing the white strip type to flux_led (#63943)
This commit is contained in:
parent
5622db10b1
commit
1c6ca908d1
11 changed files with 304 additions and 54 deletions
|
@ -7,7 +7,7 @@ from typing import Any, Final, cast
|
|||
|
||||
from flux_led import DeviceType
|
||||
from flux_led.aio import AIOWifiLedBulb
|
||||
from flux_led.const import ATTR_ID
|
||||
from flux_led.const import ATTR_ID, WhiteChannelType
|
||||
from flux_led.scanner import FluxLEDDiscovery
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
@ -23,6 +23,7 @@ from homeassistant.helpers.event import (
|
|||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import (
|
||||
CONF_WHITE_CHANNEL_TYPE,
|
||||
DISCOVER_SCAN_TIMEOUT,
|
||||
DOMAIN,
|
||||
FLUX_LED_DISCOVERY,
|
||||
|
@ -56,6 +57,9 @@ PLATFORMS_BY_TYPE: Final = {
|
|||
}
|
||||
DISCOVERY_INTERVAL: Final = timedelta(minutes=15)
|
||||
REQUEST_REFRESH_DELAY: Final = 1.5
|
||||
NAME_TO_WHITE_CHANNEL_TYPE: Final = {
|
||||
option.name.lower(): option for option in WhiteChannelType
|
||||
}
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -95,6 +99,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
device: AIOWifiLedBulb = async_wifi_bulb_for_host(host, discovery=discovery)
|
||||
signal = SIGNAL_STATE_UPDATED.format(device.ipaddr)
|
||||
device.discovery = discovery
|
||||
if white_channel_type := entry.data.get(CONF_WHITE_CHANNEL_TYPE):
|
||||
device.white_channel_channel_type = NAME_TO_WHITE_CHANNEL_TYPE[
|
||||
white_channel_type
|
||||
]
|
||||
|
||||
@callback
|
||||
def _async_state_changed(*_: Any) -> None:
|
||||
|
|
|
@ -28,6 +28,7 @@ FLUX_COLOR_MODE_TO_HASS: Final = {
|
|||
FLUX_COLOR_MODE_CCT: COLOR_MODE_COLOR_TEMP,
|
||||
}
|
||||
|
||||
MULTI_BRIGHTNESS_COLOR_MODES: Final = {COLOR_MODE_RGBWW, COLOR_MODE_RGBW}
|
||||
|
||||
API: Final = "flux_api"
|
||||
|
||||
|
@ -57,6 +58,8 @@ CONF_MINOR_VERSION: Final = "minor_version"
|
|||
CONF_REMOTE_ACCESS_ENABLED: Final = "remote_access_enabled"
|
||||
CONF_REMOTE_ACCESS_HOST: Final = "remote_access_host"
|
||||
CONF_REMOTE_ACCESS_PORT: Final = "remote_access_port"
|
||||
CONF_WHITE_CHANNEL_TYPE: Final = "white_channel_type"
|
||||
|
||||
|
||||
TRANSITION_GRADUAL: Final = "gradual"
|
||||
TRANSITION_JUMP: Final = "jump"
|
||||
|
|
|
@ -7,12 +7,7 @@ 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,
|
||||
rgbcw_to_rgbwc,
|
||||
rgbw_brightness,
|
||||
)
|
||||
from flux_led.utils import rgbcw_brightness, rgbcw_to_rgbwc, rgbw_brightness
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -24,7 +19,6 @@ from homeassistant.components.light import (
|
|||
ATTR_RGBW_COLOR,
|
||||
ATTR_RGBWW_COLOR,
|
||||
ATTR_WHITE,
|
||||
COLOR_MODE_RGBWW,
|
||||
SUPPORT_EFFECT,
|
||||
SUPPORT_TRANSITION,
|
||||
LightEntity,
|
||||
|
@ -50,6 +44,7 @@ from .const import (
|
|||
CONF_TRANSITION,
|
||||
DEFAULT_EFFECT_SPEED,
|
||||
DOMAIN,
|
||||
MULTI_BRIGHTNESS_COLOR_MODES,
|
||||
TRANSITION_GRADUAL,
|
||||
TRANSITION_JUMP,
|
||||
TRANSITION_STROBE,
|
||||
|
@ -203,9 +198,7 @@ class FluxLight(FluxOnOffEntity, CoordinatorEntity, LightEntity):
|
|||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(coordinator, unique_id, name, None)
|
||||
self._attr_min_mireds = (
|
||||
color_temperature_kelvin_to_mired(self._device.max_temp) + 1
|
||||
) # for rounding
|
||||
self._attr_min_mireds = color_temperature_kelvin_to_mired(self._device.max_temp)
|
||||
self._attr_max_mireds = color_temperature_kelvin_to_mired(self._device.min_temp)
|
||||
self._attr_supported_color_modes = _hass_color_modes(self._device)
|
||||
custom_effects: list[str] = []
|
||||
|
@ -306,20 +299,14 @@ class FluxLight(FluxOnOffEntity, CoordinatorEntity, LightEntity):
|
|||
# Handle switch to CCT Color Mode
|
||||
if color_temp_mired := kwargs.get(ATTR_COLOR_TEMP):
|
||||
color_temp_kelvin = color_temperature_mired_to_kelvin(color_temp_mired)
|
||||
if self.color_mode != COLOR_MODE_RGBWW:
|
||||
await self._device.async_set_white_temp(color_temp_kelvin, brightness)
|
||||
return
|
||||
|
||||
# When switching to color temp from RGBWW mode,
|
||||
# we do not want the overall brightness, we only
|
||||
# want the brightness of the white channels
|
||||
brightness = kwargs.get(
|
||||
ATTR_BRIGHTNESS, self._device.getWhiteTemperature()[1]
|
||||
)
|
||||
channels = color_temp_to_white_levels(color_temp_kelvin, brightness)
|
||||
warm = channels.warm_white
|
||||
cold = channels.cool_white
|
||||
await self._device.async_set_levels(r=0, b=0, g=0, w=warm, w2=cold)
|
||||
if (
|
||||
ATTR_BRIGHTNESS not in kwargs
|
||||
and self.color_mode in MULTI_BRIGHTNESS_COLOR_MODES
|
||||
):
|
||||
# When switching to color temp from RGBWW or RGB&W mode,
|
||||
# we do not want the overall brightness of the RGB channels
|
||||
brightness = max(self._device.rgb)
|
||||
await self._device.async_set_white_temp(color_temp_kelvin, brightness)
|
||||
return
|
||||
# Handle switch to RGB Color Mode
|
||||
if rgb := kwargs.get(ATTR_RGB_COLOR):
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"config_flow": true,
|
||||
"dependencies": ["network"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/flux_led",
|
||||
"requirements": ["flux_led==0.27.45"],
|
||||
"requirements": ["flux_led==0.28.1"],
|
||||
"quality_scale": "platinum",
|
||||
"codeowners": ["@icemanch", "@bdraco"],
|
||||
"iot_class": "local_push",
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
|
||||
from flux_led.aio import AIOWifiLedBulb
|
||||
from flux_led.base_device import DeviceType
|
||||
from flux_led.const import DEFAULT_WHITE_CHANNEL_TYPE, WhiteChannelType
|
||||
from flux_led.protocol import PowerRestoreState, RemoteConfig
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -12,9 +13,14 @@ from homeassistant.core import HomeAssistant, callback
|
|||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import CONF_WHITE_CHANNEL_TYPE, DOMAIN, FLUX_COLOR_MODE_RGBW
|
||||
from .coordinator import FluxLedUpdateCoordinator
|
||||
from .entity import FluxBaseEntity, FluxEntity
|
||||
from .util import _human_readable_option
|
||||
|
||||
NAME_TO_POWER_RESTORE_STATE = {
|
||||
_human_readable_option(option.name): option for option in PowerRestoreState
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -31,6 +37,7 @@ async def async_setup_entry(
|
|||
| FluxWiringsSelect
|
||||
| FluxICTypeSelect
|
||||
| FluxRemoteConfigSelect
|
||||
| FluxWhiteChannelSelect
|
||||
] = []
|
||||
name = entry.data[CONF_NAME]
|
||||
unique_id = entry.unique_id
|
||||
|
@ -57,20 +64,30 @@ async def async_setup_entry(
|
|||
coordinator, unique_id, f"{name} Remote Config", "remote_config"
|
||||
)
|
||||
)
|
||||
if FLUX_COLOR_MODE_RGBW in device.color_modes:
|
||||
entities.append(FluxWhiteChannelSelect(coordinator.device, entry))
|
||||
|
||||
if entities:
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
def _human_readable_option(const_option: str) -> str:
|
||||
return const_option.replace("_", " ").title()
|
||||
class FluxConfigAtStartSelect(FluxBaseEntity, SelectEntity):
|
||||
"""Representation of a flux config entity that only updates at start or change."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
|
||||
class FluxPowerStateSelect(FluxBaseEntity, SelectEntity):
|
||||
class FluxConfigSelect(FluxEntity, SelectEntity):
|
||||
"""Representation of a flux config entity that updates."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
|
||||
class FluxPowerStateSelect(FluxConfigAtStartSelect, SelectEntity):
|
||||
"""Representation of a Flux power restore state option."""
|
||||
|
||||
_attr_icon = "mdi:transmission-tower-off"
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_attr_options = list(NAME_TO_POWER_RESTORE_STATE)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -82,10 +99,6 @@ class FluxPowerStateSelect(FluxBaseEntity, SelectEntity):
|
|||
self._attr_name = f"{entry.data[CONF_NAME]} Power Restored"
|
||||
if entry.unique_id:
|
||||
self._attr_unique_id = f"{entry.unique_id}_power_restored"
|
||||
self._name_to_state = {
|
||||
_human_readable_option(option.name): option for option in PowerRestoreState
|
||||
}
|
||||
self._attr_options = list(self._name_to_state)
|
||||
self._async_set_current_option_from_device()
|
||||
|
||||
@callback
|
||||
|
@ -98,17 +111,13 @@ class FluxPowerStateSelect(FluxBaseEntity, SelectEntity):
|
|||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Change the power state."""
|
||||
await self._device.async_set_power_restore(channel1=self._name_to_state[option])
|
||||
await self._device.async_set_power_restore(
|
||||
channel1=NAME_TO_POWER_RESTORE_STATE[option]
|
||||
)
|
||||
self._async_set_current_option_from_device()
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class FluxConfigSelect(FluxEntity, SelectEntity):
|
||||
"""Representation of a flux config entity that updates."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
|
||||
class FluxICTypeSelect(FluxConfigSelect):
|
||||
"""Representation of Flux ic type."""
|
||||
|
||||
|
@ -202,3 +211,39 @@ class FluxRemoteConfigSelect(FluxConfigSelect):
|
|||
"""Change the remote config setting."""
|
||||
remote_config: RemoteConfig = self._name_to_state[option]
|
||||
await self._device.async_config_remotes(remote_config)
|
||||
|
||||
|
||||
class FluxWhiteChannelSelect(FluxConfigAtStartSelect):
|
||||
"""Representation of Flux white channel."""
|
||||
|
||||
_attr_options = [_human_readable_option(option.name) for option in WhiteChannelType]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device: AIOWifiLedBulb,
|
||||
entry: config_entries.ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize the white channel select."""
|
||||
super().__init__(device, entry)
|
||||
self._attr_name = f"{entry.data[CONF_NAME]} White Channel"
|
||||
if entry.unique_id:
|
||||
self._attr_unique_id = f"{entry.unique_id}_white_channel"
|
||||
|
||||
@property
|
||||
def current_option(self) -> str | None:
|
||||
"""Return the current white channel type."""
|
||||
return _human_readable_option(
|
||||
self.entry.data.get(
|
||||
CONF_WHITE_CHANNEL_TYPE, DEFAULT_WHITE_CHANNEL_TYPE.name
|
||||
)
|
||||
)
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Change the white channel type."""
|
||||
entry = self.entry
|
||||
hass = self.hass
|
||||
hass.config_entries.async_update_entry(
|
||||
entry, data={**entry.data, CONF_WHITE_CHANNEL_TYPE: option.lower()}
|
||||
)
|
||||
# reload since we need to reinit the device
|
||||
hass.async_create_task(hass.config_entries.async_reload(entry.entry_id))
|
||||
|
|
|
@ -23,6 +23,10 @@ def format_as_flux_mac(mac: str | None) -> str | None:
|
|||
return None if mac is None else mac.replace(":", "").upper()
|
||||
|
||||
|
||||
def _human_readable_option(const_option: str) -> str:
|
||||
return const_option.replace("_", " ").title()
|
||||
|
||||
|
||||
def _flux_color_mode_to_hass(
|
||||
flux_color_mode: str | None, flux_color_modes: set[str]
|
||||
) -> str:
|
||||
|
|
|
@ -681,7 +681,7 @@ fjaraskupan==1.0.2
|
|||
flipr-api==1.4.1
|
||||
|
||||
# homeassistant.components.flux_led
|
||||
flux_led==0.27.45
|
||||
flux_led==0.28.1
|
||||
|
||||
# homeassistant.components.homekit
|
||||
fnvhash==0.1.0
|
||||
|
|
|
@ -424,7 +424,7 @@ fjaraskupan==1.0.2
|
|||
flipr-api==1.4.1
|
||||
|
||||
# homeassistant.components.flux_led
|
||||
flux_led==0.27.45
|
||||
flux_led==0.28.1
|
||||
|
||||
# homeassistant.components.homekit
|
||||
fnvhash==0.1.0
|
||||
|
|
|
@ -12,6 +12,7 @@ from flux_led.aio import AIOWifiLedBulb
|
|||
from flux_led.const import (
|
||||
COLOR_MODE_CCT as FLUX_COLOR_MODE_CCT,
|
||||
COLOR_MODE_RGB as FLUX_COLOR_MODE_RGB,
|
||||
WhiteChannelType,
|
||||
)
|
||||
from flux_led.models_db import MODEL_MAP
|
||||
from flux_led.protocol import (
|
||||
|
@ -105,6 +106,7 @@ def _mocked_bulb() -> AIOWifiLedBulb:
|
|||
bulb.async_set_brightness = AsyncMock()
|
||||
bulb.async_set_device_config = AsyncMock()
|
||||
bulb.async_config_remotes = AsyncMock()
|
||||
bulb.white_channel_channel_type = WhiteChannelType.WARM
|
||||
bulb.paired_remotes = 2
|
||||
bulb.pixels_per_segment = 300
|
||||
bulb.segments = 2
|
||||
|
|
|
@ -12,6 +12,7 @@ from flux_led.const import (
|
|||
COLOR_MODES_RGB_W as FLUX_COLOR_MODES_RGB_W,
|
||||
MODE_MUSIC,
|
||||
MultiColorEffects,
|
||||
WhiteChannelType,
|
||||
)
|
||||
from flux_led.protocol import MusicMode
|
||||
import pytest
|
||||
|
@ -25,6 +26,7 @@ from homeassistant.components.flux_led.const import (
|
|||
CONF_EFFECT,
|
||||
CONF_SPEED_PCT,
|
||||
CONF_TRANSITION,
|
||||
CONF_WHITE_CHANNEL_TYPE,
|
||||
DOMAIN,
|
||||
TRANSITION_JUMP,
|
||||
)
|
||||
|
@ -520,11 +522,15 @@ async def test_rgb_cct_light(hass: HomeAssistant) -> None:
|
|||
bulb.async_set_brightness.reset_mock()
|
||||
|
||||
|
||||
async def test_rgbw_light(hass: HomeAssistant) -> None:
|
||||
"""Test an rgbw light."""
|
||||
async def test_rgbw_light_cold_white(hass: HomeAssistant) -> None:
|
||||
"""Test an rgbw light with a cold white channel."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE},
|
||||
data={
|
||||
CONF_HOST: IP_ADDRESS,
|
||||
CONF_NAME: DEFAULT_ENTRY_TITLE,
|
||||
CONF_WHITE_CHANNEL_TYPE: WhiteChannelType.COLD.name.lower(),
|
||||
},
|
||||
unique_id=MAC_ADDRESS,
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
@ -622,6 +628,148 @@ async def test_rgbw_light(hass: HomeAssistant) -> None:
|
|||
bulb.async_set_effect.reset_mock()
|
||||
|
||||
|
||||
async def test_rgbw_light_warm_white(hass: HomeAssistant) -> None:
|
||||
"""Test an rgbw light with a warm white channel."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: IP_ADDRESS,
|
||||
CONF_NAME: DEFAULT_ENTRY_TITLE,
|
||||
CONF_WHITE_CHANNEL_TYPE: WhiteChannelType.WARM.name.lower(),
|
||||
},
|
||||
unique_id=MAC_ADDRESS,
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
bulb = _mocked_bulb()
|
||||
bulb.color_modes = {FLUX_COLOR_MODE_RGBW, FLUX_COLOR_MODE_CCT}
|
||||
bulb.color_mode = FLUX_COLOR_MODE_RGBW
|
||||
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"
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
attributes = state.attributes
|
||||
assert attributes[ATTR_BRIGHTNESS] == 128
|
||||
assert attributes[ATTR_COLOR_MODE] == "rgbw"
|
||||
assert attributes[ATTR_EFFECT_LIST] == bulb.effect_list
|
||||
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "rgbw"]
|
||||
assert attributes[ATTR_RGB_COLOR] == (255, 42, 42)
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
bulb.async_turn_off.assert_called_once()
|
||||
await async_mock_device_turn_off(hass, bulb)
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
bulb.async_turn_on.assert_called_once()
|
||||
bulb.async_turn_on.reset_mock()
|
||||
bulb.is_on = True
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_brightness.assert_called_with(100)
|
||||
bulb.async_set_brightness.reset_mock()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
ATTR_RGBW_COLOR: (255, 255, 255, 255),
|
||||
ATTR_BRIGHTNESS: 128,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(128, 128, 128, 128)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_RGBW_COLOR: (255, 255, 255, 255)},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(255, 255, 255, 255)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_RGBW_COLOR: (255, 191, 178, 0)},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(255, 191, 178, 0)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 154},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_white_temp.assert_called_with(6493, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 154, ATTR_BRIGHTNESS: 255},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_white_temp.assert_called_with(6493, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 290},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_white_temp.assert_called_with(3448, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_RGBW_COLOR: (255, 191, 178, 0)},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(255, 191, 178, 0)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "random"},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_effect.assert_called_once()
|
||||
bulb.async_set_effect.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "purple_fade", ATTR_BRIGHTNESS: 255},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_effect.assert_called_with("purple_fade", 50, 100)
|
||||
bulb.async_set_effect.reset_mock()
|
||||
|
||||
|
||||
async def test_rgb_or_w_light(hass: HomeAssistant) -> None:
|
||||
"""Test an rgb or w light."""
|
||||
config_entry = MockConfigEntry(
|
||||
|
@ -811,8 +959,8 @@ async def test_rgbcw_light(hass: HomeAssistant) -> None:
|
|||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 154},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(r=0, b=0, g=0, w=0, w2=127)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
bulb.async_set_white_temp.assert_called_with(6493, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
|
@ -820,8 +968,8 @@ async def test_rgbcw_light(hass: HomeAssistant) -> None:
|
|||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 154, ATTR_BRIGHTNESS: 255},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(r=0, b=0, g=0, w=0, w2=255)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
bulb.async_set_white_temp.assert_called_with(6493, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
|
@ -829,8 +977,8 @@ async def test_rgbcw_light(hass: HomeAssistant) -> None:
|
|||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 290},
|
||||
blocking=True,
|
||||
)
|
||||
bulb.async_set_levels.assert_called_with(r=0, b=0, g=0, w=102, w2=25)
|
||||
bulb.async_set_levels.reset_mock()
|
||||
bulb.async_set_white_temp.assert_called_with(3448, 255)
|
||||
bulb.async_set_white_temp.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
"""Tests for select platform."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from flux_led.const import (
|
||||
COLOR_MODE_CCT as FLUX_COLOR_MODE_CCT,
|
||||
COLOR_MODE_RGBW as FLUX_COLOR_MODE_RGBW,
|
||||
WhiteChannelType,
|
||||
)
|
||||
from flux_led.protocol import PowerRestoreState, RemoteConfig
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import flux_led
|
||||
from homeassistant.components.flux_led.const import DOMAIN
|
||||
from homeassistant.components.flux_led.const import CONF_WHITE_CHANNEL_TYPE, DOMAIN
|
||||
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_OPTION, CONF_HOST, CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -191,3 +196,51 @@ async def test_select_24ghz_remote_config(hass: HomeAssistant) -> None:
|
|||
)
|
||||
bulb.async_config_remotes.assert_called_once_with(RemoteConfig.PAIRED_ONLY)
|
||||
bulb.async_config_remotes.reset_mock()
|
||||
|
||||
|
||||
async def test_select_white_channel_type(hass: HomeAssistant) -> None:
|
||||
"""Test selecting the white channel type."""
|
||||
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.color_modes = {FLUX_COLOR_MODE_RGBW, FLUX_COLOR_MODE_CCT}
|
||||
bulb.color_mode = FLUX_COLOR_MODE_RGBW
|
||||
bulb.raw_state = bulb.raw_state._replace(model_num=0x06) # rgbw
|
||||
with _patch_discovery(), _patch_wifibulb(device=bulb):
|
||||
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
operating_mode_entity_id = "select.bulb_rgbcw_ddeeff_white_channel"
|
||||
state = hass.states.get(operating_mode_entity_id)
|
||||
assert state.state == WhiteChannelType.WARM.name.title()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
"select_option",
|
||||
{ATTR_ENTITY_ID: operating_mode_entity_id, ATTR_OPTION: "INVALID"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.flux_led.async_setup_entry"
|
||||
) as mock_setup_entry:
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
"select_option",
|
||||
{
|
||||
ATTR_ENTITY_ID: operating_mode_entity_id,
|
||||
ATTR_OPTION: WhiteChannelType.NATURAL.name.title(),
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
config_entry.data[CONF_WHITE_CHANNEL_TYPE]
|
||||
== WhiteChannelType.NATURAL.name.lower()
|
||||
)
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
|
Loading…
Add table
Reference in a new issue