mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add support for effects in Govee lights (#137846)
This commit is contained in:
parent
9ec9110e1e
commit
f3021b40ab
@ -89,6 +89,10 @@ class GoveeLocalApiCoordinator(DataUpdateCoordinator[list[GoveeDevice]]):
|
||||
"""Set light color in kelvin."""
|
||||
await device.set_temperature(temperature)
|
||||
|
||||
async def set_scene(self, device: GoveeController, scene: str) -> None:
|
||||
"""Set light scene."""
|
||||
await device.set_scene(scene)
|
||||
|
||||
@property
|
||||
def devices(self) -> list[GoveeDevice]:
|
||||
"""Return a list of discovered Govee devices."""
|
||||
|
@ -10,9 +10,11 @@ from govee_local_api import GoveeDevice, GoveeLightFeatures
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_EFFECT,
|
||||
ATTR_RGB_COLOR,
|
||||
ColorMode,
|
||||
LightEntity,
|
||||
LightEntityFeature,
|
||||
filter_supported_color_modes,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@ -25,6 +27,8 @@ from .coordinator import GoveeLocalApiCoordinator, GoveeLocalConfigEntry
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_NONE_SCENE = "none"
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@ -50,10 +54,22 @@ async def async_setup_entry(
|
||||
class GoveeLight(CoordinatorEntity[GoveeLocalApiCoordinator], LightEntity):
|
||||
"""Govee Light."""
|
||||
|
||||
_attr_translation_key = "govee_light"
|
||||
_attr_has_entity_name = True
|
||||
_attr_name = None
|
||||
_attr_supported_color_modes: set[ColorMode]
|
||||
_fixed_color_mode: ColorMode | None = None
|
||||
_attr_effect_list: list[str] | None = None
|
||||
_attr_effect: str | None = None
|
||||
_attr_supported_features: LightEntityFeature = LightEntityFeature(0)
|
||||
_last_color_state: (
|
||||
tuple[
|
||||
ColorMode | str | None,
|
||||
int | None,
|
||||
tuple[int, int, int] | tuple[int | None] | None,
|
||||
]
|
||||
| None
|
||||
) = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -80,6 +96,13 @@ class GoveeLight(CoordinatorEntity[GoveeLocalApiCoordinator], LightEntity):
|
||||
if GoveeLightFeatures.BRIGHTNESS & capabilities.features:
|
||||
color_modes.add(ColorMode.BRIGHTNESS)
|
||||
|
||||
if (
|
||||
GoveeLightFeatures.SCENES & capabilities.features
|
||||
and capabilities.scenes
|
||||
):
|
||||
self._attr_supported_features = LightEntityFeature.EFFECT
|
||||
self._attr_effect_list = [_NONE_SCENE, *capabilities.scenes.keys()]
|
||||
|
||||
self._attr_supported_color_modes = filter_supported_color_modes(color_modes)
|
||||
if len(self._attr_supported_color_modes) == 1:
|
||||
# If the light supports only a single color mode, set it now
|
||||
@ -143,12 +166,27 @@ class GoveeLight(CoordinatorEntity[GoveeLocalApiCoordinator], LightEntity):
|
||||
|
||||
if ATTR_RGB_COLOR in kwargs:
|
||||
self._attr_color_mode = ColorMode.RGB
|
||||
self._attr_effect = None
|
||||
self._last_color_state = None
|
||||
red, green, blue = kwargs[ATTR_RGB_COLOR]
|
||||
await self.coordinator.set_rgb_color(self._device, red, green, blue)
|
||||
elif ATTR_COLOR_TEMP_KELVIN in kwargs:
|
||||
self._attr_color_mode = ColorMode.COLOR_TEMP
|
||||
self._attr_effect = None
|
||||
self._last_color_state = None
|
||||
temperature: float = kwargs[ATTR_COLOR_TEMP_KELVIN]
|
||||
await self.coordinator.set_temperature(self._device, int(temperature))
|
||||
elif ATTR_EFFECT in kwargs:
|
||||
effect = kwargs[ATTR_EFFECT]
|
||||
if effect and self._attr_effect_list and effect in self._attr_effect_list:
|
||||
if effect == _NONE_SCENE:
|
||||
self._attr_effect = None
|
||||
await self._restore_last_color_state()
|
||||
else:
|
||||
self._attr_effect = effect
|
||||
self._save_last_color_state()
|
||||
await self.coordinator.set_scene(self._device, effect)
|
||||
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
@ -159,3 +197,27 @@ class GoveeLight(CoordinatorEntity[GoveeLocalApiCoordinator], LightEntity):
|
||||
@callback
|
||||
def _update_callback(self, device: GoveeDevice) -> None:
|
||||
self.async_write_ha_state()
|
||||
|
||||
def _save_last_color_state(self) -> None:
|
||||
color_mode = self.color_mode
|
||||
self._last_color_state = (
|
||||
color_mode,
|
||||
self.brightness,
|
||||
(self.color_temp_kelvin,)
|
||||
if color_mode == ColorMode.COLOR_TEMP
|
||||
else self.rgb_color,
|
||||
)
|
||||
|
||||
async def _restore_last_color_state(self) -> None:
|
||||
if self._last_color_state:
|
||||
color_mode, brightness, color = self._last_color_state
|
||||
if color:
|
||||
if color_mode == ColorMode.RGB:
|
||||
await self.coordinator.set_rgb_color(self._device, *color)
|
||||
elif color_mode == ColorMode.COLOR_TEMP:
|
||||
await self.coordinator.set_temperature(self._device, *color)
|
||||
if brightness:
|
||||
await self.coordinator.set_brightness(
|
||||
self._device, int((float(brightness) / 255.0) * 100.0)
|
||||
)
|
||||
self._last_color_state = None
|
||||
|
@ -9,5 +9,29 @@
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"light": {
|
||||
"govee_light": {
|
||||
"state_attributes": {
|
||||
"effect": {
|
||||
"state": {
|
||||
"none": "None",
|
||||
"sunrise": "Sunrise",
|
||||
"sunset": "Sunset",
|
||||
"movie": "Movie",
|
||||
"dating": "Dating",
|
||||
"romantic": "Romantic",
|
||||
"twinkle": "Twinkle",
|
||||
"candlelight": "Candlelight",
|
||||
"snowflake": "Snowflake",
|
||||
"energetic": "Energetic",
|
||||
"breathe": "Breathe",
|
||||
"crossing": "Crossing"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,15 @@ from asyncio import Event
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from govee_local_api import GoveeLightCapabilities
|
||||
from govee_local_api.light_capabilities import COMMON_FEATURES
|
||||
from govee_local_api import GoveeLightCapabilities, GoveeLightFeatures
|
||||
from govee_local_api.light_capabilities import COMMON_FEATURES, SCENE_CODES
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.govee_light_local.coordinator import GoveeController
|
||||
|
||||
|
||||
@pytest.fixture(name="mock_govee_api")
|
||||
def fixture_mock_govee_api():
|
||||
def fixture_mock_govee_api() -> Generator[AsyncMock]:
|
||||
"""Set up Govee Local API fixture."""
|
||||
mock_api = AsyncMock(spec=GoveeController)
|
||||
mock_api.start = AsyncMock()
|
||||
@ -21,8 +21,20 @@ def fixture_mock_govee_api():
|
||||
mock_api.turn_on_off = AsyncMock()
|
||||
mock_api.set_brightness = AsyncMock()
|
||||
mock_api.set_color = AsyncMock()
|
||||
mock_api.set_scene = AsyncMock()
|
||||
mock_api._async_update_data = AsyncMock()
|
||||
return mock_api
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_api,
|
||||
) as mock_controller,
|
||||
patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.GoveeController",
|
||||
return_value=mock_api,
|
||||
),
|
||||
):
|
||||
yield mock_controller.return_value
|
||||
|
||||
|
||||
@pytest.fixture(name="mock_setup_entry")
|
||||
@ -38,3 +50,9 @@ def fixture_mock_setup_entry() -> Generator[AsyncMock]:
|
||||
DEFAULT_CAPABILITIES: GoveeLightCapabilities = GoveeLightCapabilities(
|
||||
features=COMMON_FEATURES, segments=[], scenes={}
|
||||
)
|
||||
|
||||
SCENE_CAPABILITIES: GoveeLightCapabilities = GoveeLightCapabilities(
|
||||
features=COMMON_FEATURES | GoveeLightFeatures.SCENES,
|
||||
segments=[],
|
||||
scenes=SCENE_CODES,
|
||||
)
|
||||
|
@ -32,15 +32,9 @@ async def test_creating_entry_has_no_devices(
|
||||
|
||||
mock_govee_api.devices = []
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.DISCOVERY_TIMEOUT",
|
||||
0,
|
||||
),
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.DISCOVERY_TIMEOUT",
|
||||
0,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
@ -67,24 +61,20 @@ async def test_creating_entry_has_with_devices(
|
||||
|
||||
mock_govee_api.devices = _get_devices(mock_govee_api)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
# Confirmation form
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
# Confirmation form
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_govee_api.start.assert_awaited_once()
|
||||
mock_setup_entry.assert_awaited_once()
|
||||
mock_govee_api.start.assert_awaited_once()
|
||||
mock_setup_entry.assert_awaited_once()
|
||||
|
||||
|
||||
async def test_creating_entry_errno(
|
||||
@ -99,21 +89,17 @@ async def test_creating_entry_errno(
|
||||
mock_govee_api.start.side_effect = e
|
||||
mock_govee_api.devices = _get_devices(mock_govee_api)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.config_flow.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
# Confirmation form
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
# Confirmation form
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_govee_api.start.call_count == 1
|
||||
mock_setup_entry.assert_not_awaited()
|
||||
assert mock_govee_api.start.call_count == 1
|
||||
mock_setup_entry.assert_not_awaited()
|
||||
|
@ -10,7 +10,7 @@ from homeassistant.components.light import ATTR_SUPPORTED_COLOR_MODES, ColorMode
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import DEFAULT_CAPABILITIES
|
||||
from .conftest import DEFAULT_CAPABILITIES, SCENE_CAPABILITIES
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -30,28 +30,24 @@ async def test_light_known_device(
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
|
||||
color_modes = light.attributes[ATTR_SUPPORTED_COLOR_MODES]
|
||||
assert set(color_modes) == {ColorMode.COLOR_TEMP, ColorMode.RGB}
|
||||
color_modes = light.attributes[ATTR_SUPPORTED_COLOR_MODES]
|
||||
assert set(color_modes) == {ColorMode.COLOR_TEMP, ColorMode.RGB}
|
||||
|
||||
# Remove
|
||||
assert await hass.config_entries.async_remove(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("light.H615A") is None
|
||||
# Remove
|
||||
assert await hass.config_entries.async_remove(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("light.H615A") is None
|
||||
|
||||
|
||||
async def test_light_unknown_device(
|
||||
@ -69,26 +65,22 @@ async def test_light_unknown_device(
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.XYZK")
|
||||
assert light is not None
|
||||
light = hass.states.get("light.XYZK")
|
||||
assert light is not None
|
||||
|
||||
assert light.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.ONOFF]
|
||||
assert light.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.ONOFF]
|
||||
|
||||
|
||||
async def test_light_remove(hass: HomeAssistant, mock_govee_api: AsyncMock) -> None:
|
||||
"""Test adding a known device."""
|
||||
"""Test remove device."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
@ -100,49 +92,41 @@ async def test_light_remove(hass: HomeAssistant, mock_govee_api: AsyncMock) -> N
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("light.H615A") is not None
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("light.H615A") is not None
|
||||
|
||||
# Remove 1
|
||||
assert await hass.config_entries.async_remove(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 0
|
||||
# Remove 1
|
||||
assert await hass.config_entries.async_remove(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 0
|
||||
|
||||
|
||||
async def test_light_setup_retry(
|
||||
hass: HomeAssistant, mock_govee_api: AsyncMock
|
||||
) -> None:
|
||||
"""Test adding an unknown device."""
|
||||
"""Test setup retry."""
|
||||
|
||||
mock_govee_api.devices = []
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.DISCOVERY_TIMEOUT",
|
||||
0,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.DISCOVERY_TIMEOUT",
|
||||
0,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_light_setup_retry_eaddrinuse(
|
||||
hass: HomeAssistant, mock_govee_api: AsyncMock
|
||||
) -> None:
|
||||
"""Test adding an unknown device."""
|
||||
"""Test retry on address already in use."""
|
||||
|
||||
mock_govee_api.start.side_effect = OSError()
|
||||
mock_govee_api.start.side_effect.errno = EADDRINUSE
|
||||
@ -156,21 +140,17 @@ async def test_light_setup_retry_eaddrinuse(
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_light_setup_error(
|
||||
hass: HomeAssistant, mock_govee_api: AsyncMock
|
||||
) -> None:
|
||||
"""Test adding an unknown device."""
|
||||
"""Test setup error."""
|
||||
|
||||
mock_govee_api.start.side_effect = OSError()
|
||||
mock_govee_api.start.side_effect.errno = ENETDOWN
|
||||
@ -184,19 +164,15 @@ async def test_light_setup_error(
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_ERROR
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
|
||||
async def test_light_on_off(hass: HomeAssistant, mock_govee_api: MagicMock) -> None:
|
||||
"""Test adding a known device."""
|
||||
"""Test light on and then off."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
@ -208,48 +184,44 @@ async def test_light_on_off(hass: HomeAssistant, mock_govee_api: MagicMock) -> N
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_off",
|
||||
{"entity_id": light.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_off",
|
||||
{"entity_id": light.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], False)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], False)
|
||||
|
||||
|
||||
async def test_light_brightness(hass: HomeAssistant, mock_govee_api: MagicMock) -> None:
|
||||
@ -264,67 +236,59 @@ async def test_light_brightness(hass: HomeAssistant, mock_govee_api: MagicMock)
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness_pct": 50},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness_pct": 50},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
mock_govee_api.set_brightness.assert_awaited_with(mock_govee_api.devices[0], 50)
|
||||
assert light.attributes["brightness"] == 127
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
mock_govee_api.set_brightness.assert_awaited_with(mock_govee_api.devices[0], 50)
|
||||
assert light.attributes["brightness"] == 127
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.set_brightness.assert_awaited_with(
|
||||
mock_govee_api.devices[0], 100
|
||||
)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.set_brightness.assert_awaited_with(mock_govee_api.devices[0], 100)
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.set_brightness.assert_awaited_with(
|
||||
mock_govee_api.devices[0], 100
|
||||
)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.set_brightness.assert_awaited_with(mock_govee_api.devices[0], 100)
|
||||
|
||||
|
||||
async def test_light_color(hass: HomeAssistant, mock_govee_api: MagicMock) -> None:
|
||||
@ -339,54 +303,312 @@ async def test_light_color(hass: HomeAssistant, mock_govee_api: MagicMock) -> No
|
||||
)
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.govee_light_local.coordinator.GoveeController",
|
||||
return_value=mock_govee_api,
|
||||
):
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "rgb_color": [100, 255, 50]},
|
||||
blocking=True,
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "rgb_color": [100, 255, 50]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["rgb_color"] == (100, 255, 50)
|
||||
assert light.attributes["color_mode"] == ColorMode.RGB
|
||||
|
||||
mock_govee_api.set_color.assert_awaited_with(
|
||||
mock_govee_api.devices[0], rgb=(100, 255, 50), temperature=None
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "kelvin": 4400},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["color_temp_kelvin"] == 4400
|
||||
assert light.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
|
||||
mock_govee_api.set_color.assert_awaited_with(
|
||||
mock_govee_api.devices[0], rgb=None, temperature=4400
|
||||
)
|
||||
|
||||
|
||||
async def test_scene_on(hass: HomeAssistant, mock_govee_api: MagicMock) -> None:
|
||||
"""Test turning on scene."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
controller=mock_govee_api,
|
||||
ip="192.168.1.100",
|
||||
fingerprint="asdawdqwdqwd",
|
||||
sku="H615A",
|
||||
capabilities=SCENE_CAPABILITIES,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
]
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["rgb_color"] == (100, 255, 50)
|
||||
assert light.attributes["color_mode"] == ColorMode.RGB
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_govee_api.set_color.assert_awaited_with(
|
||||
mock_govee_api.devices[0], rgb=(100, 255, 50), temperature=None
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "sunrise"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] == "sunrise"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
|
||||
async def test_scene_restore_rgb(
|
||||
hass: HomeAssistant, mock_govee_api: MagicMock
|
||||
) -> None:
|
||||
"""Test restore rgb color."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
controller=mock_govee_api,
|
||||
ip="192.168.1.100",
|
||||
fingerprint="asdawdqwdqwd",
|
||||
sku="H615A",
|
||||
capabilities=SCENE_CAPABILITIES,
|
||||
)
|
||||
]
|
||||
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "kelvin": 4400},
|
||||
blocking=True,
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
initial_color = (12, 34, 56)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
# Set initial color
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "rgb_color": initial_color},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["rgb_color"] == initial_color
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
# Activate scene
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "sunrise"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] == "sunrise"
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
# Deactivate scene
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "none"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] is None
|
||||
assert light.attributes["rgb_color"] == initial_color
|
||||
assert light.attributes["brightness"] == 255
|
||||
|
||||
|
||||
async def test_scene_restore_temperature(
|
||||
hass: HomeAssistant, mock_govee_api: MagicMock
|
||||
) -> None:
|
||||
"""Test restore color temperature."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
controller=mock_govee_api,
|
||||
ip="192.168.1.100",
|
||||
fingerprint="asdawdqwdqwd",
|
||||
sku="H615A",
|
||||
capabilities=SCENE_CAPABILITIES,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
]
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["color_temp_kelvin"] == 4400
|
||||
assert light.attributes["color_mode"] == ColorMode.COLOR_TEMP
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_govee_api.set_color.assert_awaited_with(
|
||||
mock_govee_api.devices[0], rgb=None, temperature=4400
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
initial_color = 3456
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
# Set initial color
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "color_temp_kelvin": initial_color},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["color_temp_kelvin"] == initial_color
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
# Activate scene
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "sunrise"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] == "sunrise"
|
||||
mock_govee_api.set_scene.assert_awaited_with(mock_govee_api.devices[0], "sunrise")
|
||||
|
||||
# Deactivate scene
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "none"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] is None
|
||||
assert light.attributes["color_temp_kelvin"] == initial_color
|
||||
|
||||
|
||||
async def test_scene_none(hass: HomeAssistant, mock_govee_api: MagicMock) -> None:
|
||||
"""Test turn on 'none' scene."""
|
||||
|
||||
mock_govee_api.devices = [
|
||||
GoveeDevice(
|
||||
controller=mock_govee_api,
|
||||
ip="192.168.1.100",
|
||||
fingerprint="asdawdqwdqwd",
|
||||
sku="H615A",
|
||||
capabilities=SCENE_CAPABILITIES,
|
||||
)
|
||||
]
|
||||
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
initial_color = (12, 34, 56)
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "off"
|
||||
|
||||
# Set initial color
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "rgb_color": initial_color},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "brightness": 255},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["rgb_color"] == initial_color
|
||||
assert light.attributes["brightness"] == 255
|
||||
mock_govee_api.turn_on_off.assert_awaited_with(mock_govee_api.devices[0], True)
|
||||
|
||||
# Activate scene
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": light.entity_id, "effect": "none"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light = hass.states.get("light.H615A")
|
||||
assert light is not None
|
||||
assert light.state == "on"
|
||||
assert light.attributes["effect"] is None
|
||||
mock_govee_api.set_scene.assert_not_called()
|
||||
|
Loading…
x
Reference in New Issue
Block a user