Add support for Elgato Light Strip (#49988)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>pull/50141/head
parent
e4ef06d6b1
commit
ae692a003f
|
@ -1,4 +1,4 @@
|
||||||
"""Support for Elgato Key Lights."""
|
"""Support for Elgato Lights."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from elgato import Elgato, ElgatoConnectionError
|
from elgato import Elgato, ElgatoConnectionError
|
||||||
|
@ -16,7 +16,7 @@ PLATFORMS = [LIGHT_DOMAIN]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up Elgato Key Light from a config entry."""
|
"""Set up Elgato Light from a config entry."""
|
||||||
session = async_get_clientsession(hass)
|
session = async_get_clientsession(hass)
|
||||||
elgato = Elgato(
|
elgato = Elgato(
|
||||||
entry.data[CONF_HOST],
|
entry.data[CONF_HOST],
|
||||||
|
@ -39,7 +39,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Unload Elgato Key Light config entry."""
|
"""Unload Elgato Light config entry."""
|
||||||
# Unload entities for this entry/device.
|
# Unload entities for this entry/device.
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
if unload_ok:
|
if unload_ok:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""Config flow to configure the Elgato Key Light integration."""
|
"""Config flow to configure the Elgato Light integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -16,7 +16,7 @@ from .const import CONF_SERIAL_NUMBER, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||||
"""Handle a Elgato Key Light config flow."""
|
"""Handle a Elgato Light config flow."""
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ class ElgatoFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _get_elgato_serial_number(self, raise_on_progress: bool = True) -> None:
|
async def _get_elgato_serial_number(self, raise_on_progress: bool = True) -> None:
|
||||||
"""Get device information from an Elgato Key Light device."""
|
"""Get device information from an Elgato Light device."""
|
||||||
session = async_get_clientsession(self.hass)
|
session = async_get_clientsession(self.hass)
|
||||||
elgato = Elgato(
|
elgato = Elgato(
|
||||||
host=self.host,
|
host=self.host,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""Constants for the Elgato Key Light integration."""
|
"""Constants for the Elgato Light integration."""
|
||||||
|
|
||||||
# Integration domain
|
# Integration domain
|
||||||
DOMAIN = "elgato"
|
DOMAIN = "elgato"
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
"""Support for LED lights."""
|
"""Support for Elgato lights."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from elgato import Elgato, ElgatoError, Info, State
|
from elgato import Elgato, ElgatoError, Info, Settings, State
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
ATTR_COLOR_TEMP,
|
ATTR_COLOR_TEMP,
|
||||||
SUPPORT_BRIGHTNESS,
|
ATTR_HS_COLOR,
|
||||||
SUPPORT_COLOR_TEMP,
|
COLOR_MODE_COLOR_TEMP,
|
||||||
|
COLOR_MODE_HS,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -42,10 +43,11 @@ async def async_setup_entry(
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Elgato Key Light based on a config entry."""
|
"""Set up Elgato Light based on a config entry."""
|
||||||
elgato: Elgato = hass.data[DOMAIN][entry.entry_id][DATA_ELGATO_CLIENT]
|
elgato: Elgato = hass.data[DOMAIN][entry.entry_id][DATA_ELGATO_CLIENT]
|
||||||
info = await elgato.info()
|
info = await elgato.info()
|
||||||
async_add_entities([ElgatoLight(elgato, info)], True)
|
settings = await elgato.settings()
|
||||||
|
async_add_entities([ElgatoLight(elgato, info, settings)], True)
|
||||||
|
|
||||||
platform = async_get_current_platform()
|
platform = async_get_current_platform()
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
|
@ -56,18 +58,25 @@ async def async_setup_entry(
|
||||||
|
|
||||||
|
|
||||||
class ElgatoLight(LightEntity):
|
class ElgatoLight(LightEntity):
|
||||||
"""Defines a Elgato Key Light."""
|
"""Defines an Elgato Light."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, elgato: Elgato, info: Info, settings: Settings) -> None:
|
||||||
self,
|
"""Initialize Elgato Light."""
|
||||||
elgato: Elgato,
|
self._info = info
|
||||||
info: Info,
|
self._settings = settings
|
||||||
) -> None:
|
|
||||||
"""Initialize Elgato Key Light."""
|
|
||||||
self._info: Info = info
|
|
||||||
self._state: State | None = None
|
self._state: State | None = None
|
||||||
self.elgato = elgato
|
self.elgato = elgato
|
||||||
|
|
||||||
|
self._min_mired = 143
|
||||||
|
self._max_mired = 344
|
||||||
|
self._supported_color_modes = {COLOR_MODE_COLOR_TEMP}
|
||||||
|
|
||||||
|
# Elgato Light supporting color, have a different temperature range
|
||||||
|
if settings.power_on_hue is not None:
|
||||||
|
self._supported_color_modes = {COLOR_MODE_COLOR_TEMP, COLOR_MODE_HS}
|
||||||
|
self._min_mired = 153
|
||||||
|
self._max_mired = 285
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Return the name of the entity."""
|
"""Return the name of the entity."""
|
||||||
|
@ -99,17 +108,38 @@ class ElgatoLight(LightEntity):
|
||||||
@property
|
@property
|
||||||
def min_mireds(self) -> int:
|
def min_mireds(self) -> int:
|
||||||
"""Return the coldest color_temp that this light supports."""
|
"""Return the coldest color_temp that this light supports."""
|
||||||
return 143
|
return self._min_mired
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_mireds(self) -> int:
|
def max_mireds(self) -> int:
|
||||||
"""Return the warmest color_temp that this light supports."""
|
"""Return the warmest color_temp that this light supports."""
|
||||||
return 344
|
# Elgato lights with color capabilities have a different highest value
|
||||||
|
return self._max_mired
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self) -> int:
|
def supported_color_modes(self) -> set[str]:
|
||||||
"""Flag supported features."""
|
"""Flag supported color modes."""
|
||||||
return SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP
|
return self._supported_color_modes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def color_mode(self) -> str | None:
|
||||||
|
"""Return the color mode of the light."""
|
||||||
|
if self._state and self._state.hue is not None:
|
||||||
|
return COLOR_MODE_HS
|
||||||
|
|
||||||
|
return COLOR_MODE_COLOR_TEMP
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hs_color(self) -> tuple[float, float] | None:
|
||||||
|
"""Return the hue and saturation color value [float, float]."""
|
||||||
|
if (
|
||||||
|
self._state is None
|
||||||
|
or self._state.hue is None
|
||||||
|
or self._state.saturation is None
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return (self._state.hue, self._state.saturation)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
|
@ -122,22 +152,44 @@ class ElgatoLight(LightEntity):
|
||||||
try:
|
try:
|
||||||
await self.elgato.light(on=False)
|
await self.elgato.light(on=False)
|
||||||
except ElgatoError:
|
except ElgatoError:
|
||||||
_LOGGER.error("An error occurred while updating the Elgato Key Light")
|
_LOGGER.error("An error occurred while updating the Elgato Light")
|
||||||
self._state = None
|
self._state = None
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the light."""
|
"""Turn on the light."""
|
||||||
temperature = kwargs.get(ATTR_COLOR_TEMP)
|
temperature = kwargs.get(ATTR_COLOR_TEMP)
|
||||||
|
|
||||||
|
hue = None
|
||||||
|
saturation = None
|
||||||
|
if ATTR_HS_COLOR in kwargs:
|
||||||
|
hue, saturation = kwargs[ATTR_HS_COLOR]
|
||||||
|
|
||||||
brightness = None
|
brightness = None
|
||||||
if ATTR_BRIGHTNESS in kwargs:
|
if ATTR_BRIGHTNESS in kwargs:
|
||||||
brightness = round((kwargs[ATTR_BRIGHTNESS] / 255) * 100)
|
brightness = round((kwargs[ATTR_BRIGHTNESS] / 255) * 100)
|
||||||
|
|
||||||
|
# For Elgato lights supporting color mode, but in temperature mode;
|
||||||
|
# adjusting only brightness make them jump back to color mode.
|
||||||
|
# Resending temperature prevents that.
|
||||||
|
if (
|
||||||
|
brightness
|
||||||
|
and ATTR_HS_COLOR not in kwargs
|
||||||
|
and ATTR_COLOR_TEMP not in kwargs
|
||||||
|
and COLOR_MODE_HS in self.supported_color_modes
|
||||||
|
and self.color_mode == COLOR_MODE_COLOR_TEMP
|
||||||
|
):
|
||||||
|
temperature = self.color_temp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.elgato.light(
|
await self.elgato.light(
|
||||||
on=True, brightness=brightness, temperature=temperature
|
on=True,
|
||||||
|
brightness=brightness,
|
||||||
|
hue=hue,
|
||||||
|
saturation=saturation,
|
||||||
|
temperature=temperature,
|
||||||
)
|
)
|
||||||
except ElgatoError:
|
except ElgatoError:
|
||||||
_LOGGER.error("An error occurred while updating the Elgato Key Light")
|
_LOGGER.error("An error occurred while updating the Elgato Light")
|
||||||
self._state = None
|
self._state = None
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
|
@ -149,12 +201,12 @@ class ElgatoLight(LightEntity):
|
||||||
_LOGGER.info("Connection restored")
|
_LOGGER.info("Connection restored")
|
||||||
except ElgatoError as err:
|
except ElgatoError as err:
|
||||||
meth = _LOGGER.error if self._state else _LOGGER.debug
|
meth = _LOGGER.error if self._state else _LOGGER.debug
|
||||||
meth("An error occurred while updating the Elgato Key Light: %s", err)
|
meth("An error occurred while updating the Elgato Light: %s", err)
|
||||||
self._state = None
|
self._state = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
"""Return device information about this Elgato Key Light."""
|
"""Return device information about this Elgato Light."""
|
||||||
return {
|
return {
|
||||||
ATTR_IDENTIFIERS: {(DOMAIN, self._info.serial_number)},
|
ATTR_IDENTIFIERS: {(DOMAIN, self._info.serial_number)},
|
||||||
ATTR_NAME: self._info.product_name,
|
ATTR_NAME: self._info.product_name,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"domain": "elgato",
|
"domain": "elgato",
|
||||||
"name": "Elgato Key Light",
|
"name": "Elgato Light",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/elgato",
|
"documentation": "https://www.home-assistant.io/integrations/elgato",
|
||||||
"requirements": ["elgato==2.1.0"],
|
"requirements": ["elgato==2.1.0"],
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
"flow_title": "Elgato Key Light: {serial_number}",
|
"flow_title": "Elgato Light: {serial_number}",
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"description": "Set up your Elgato Key Light to integrate with Home Assistant.",
|
"description": "Set up your Elgato Light to integrate with Home Assistant.",
|
||||||
"data": {
|
"data": {
|
||||||
"host": "[%key:common::config_flow::data::host%]",
|
"host": "[%key:common::config_flow::data::host%]",
|
||||||
"port": "[%key:common::config_flow::data::port%]"
|
"port": "[%key:common::config_flow::data::port%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zeroconf_confirm": {
|
"zeroconf_confirm": {
|
||||||
"description": "Do you want to add the Elgato Key Light with serial number `{serial_number}` to Home Assistant?",
|
"description": "Do you want to add the Elgato Light with serial number `{serial_number}` to Home Assistant?",
|
||||||
"title": "Discovered Elgato Key Light device"
|
"title": "Discovered Elgato Light device"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
|
|
@ -7,18 +7,18 @@
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "Failed to connect"
|
"cannot_connect": "Failed to connect"
|
||||||
},
|
},
|
||||||
"flow_title": "Elgato Key Light: {serial_number}",
|
"flow_title": "Elgato Light: {serial_number}",
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"host": "Host",
|
"host": "Host",
|
||||||
"port": "Port"
|
"port": "Port"
|
||||||
},
|
},
|
||||||
"description": "Set up your Elgato Key Light to integrate with Home Assistant."
|
"description": "Set up your Elgato Light to integrate with Home Assistant."
|
||||||
},
|
},
|
||||||
"zeroconf_confirm": {
|
"zeroconf_confirm": {
|
||||||
"description": "Do you want to add the Elgato Key Light with serial number `{serial_number}` to Home Assistant?",
|
"description": "Do you want to add the Elgato Light with serial number `{serial_number}` to Home Assistant?",
|
||||||
"title": "Discovered Elgato Key Light device"
|
"title": "Discovered Elgato Light device"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ async def init_integration(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
aioclient_mock: AiohttpClientMocker,
|
aioclient_mock: AiohttpClientMocker,
|
||||||
skip_setup: bool = False,
|
skip_setup: bool = False,
|
||||||
|
color: bool = False,
|
||||||
|
mode_color: bool = False,
|
||||||
) -> MockConfigEntry:
|
) -> MockConfigEntry:
|
||||||
"""Set up the Elgato Key Light integration in Home Assistant."""
|
"""Set up the Elgato Key Light integration in Home Assistant."""
|
||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
|
@ -20,24 +22,38 @@ async def init_integration(
|
||||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
)
|
)
|
||||||
|
|
||||||
aioclient_mock.put(
|
|
||||||
"http://127.0.0.1:9123/elgato/lights",
|
|
||||||
text=load_fixture("elgato/state.json"),
|
|
||||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
|
||||||
)
|
|
||||||
|
|
||||||
aioclient_mock.get(
|
|
||||||
"http://127.0.0.1:9123/elgato/lights",
|
|
||||||
text=load_fixture("elgato/state.json"),
|
|
||||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
|
||||||
)
|
|
||||||
|
|
||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
"http://127.0.0.2:9123/elgato/accessory-info",
|
"http://127.0.0.2:9123/elgato/accessory-info",
|
||||||
text=load_fixture("elgato/info.json"),
|
text=load_fixture("elgato/info.json"),
|
||||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
settings = "elgato/settings.json"
|
||||||
|
if color:
|
||||||
|
settings = "elgato/settings-color.json"
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1:9123/elgato/lights/settings",
|
||||||
|
text=load_fixture(settings),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = "elgato/state.json"
|
||||||
|
if mode_color:
|
||||||
|
state = "elgato/state-color.json"
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1:9123/elgato/lights",
|
||||||
|
text=load_fixture(state),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
|
||||||
|
aioclient_mock.put(
|
||||||
|
"http://127.0.0.1:9123/elgato/lights",
|
||||||
|
text=load_fixture("elgato/state.json"),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
unique_id="CN11A1A00001",
|
unique_id="CN11A1A00001",
|
||||||
|
|
|
@ -2,11 +2,19 @@
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from elgato import ElgatoError
|
from elgato import ElgatoError
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.elgato.const import DOMAIN, SERVICE_IDENTIFY
|
from homeassistant.components.elgato.const import DOMAIN, SERVICE_IDENTIFY
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
|
ATTR_COLOR_MODE,
|
||||||
ATTR_COLOR_TEMP,
|
ATTR_COLOR_TEMP,
|
||||||
|
ATTR_HS_COLOR,
|
||||||
|
ATTR_MAX_MIREDS,
|
||||||
|
ATTR_MIN_MIREDS,
|
||||||
|
ATTR_SUPPORTED_COLOR_MODES,
|
||||||
|
COLOR_MODE_COLOR_TEMP,
|
||||||
|
COLOR_MODE_HS,
|
||||||
DOMAIN as LIGHT_DOMAIN,
|
DOMAIN as LIGHT_DOMAIN,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
@ -24,10 +32,10 @@ from tests.components.elgato import init_integration
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
|
|
||||||
async def test_light_state(
|
async def test_light_state_temperature(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the creation and values of the Elgato Key Lights."""
|
"""Test the creation and values of the Elgato Lights in temperature mode."""
|
||||||
await init_integration(hass, aioclient_mock)
|
await init_integration(hass, aioclient_mock)
|
||||||
|
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
|
@ -37,6 +45,11 @@ async def test_light_state(
|
||||||
assert state
|
assert state
|
||||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 54
|
assert state.attributes.get(ATTR_BRIGHTNESS) == 54
|
||||||
assert state.attributes.get(ATTR_COLOR_TEMP) == 297
|
assert state.attributes.get(ATTR_COLOR_TEMP) == 297
|
||||||
|
assert state.attributes.get(ATTR_HS_COLOR) is None
|
||||||
|
assert state.attributes.get(ATTR_COLOR_MODE) == COLOR_MODE_COLOR_TEMP
|
||||||
|
assert state.attributes.get(ATTR_MIN_MIREDS) == 143
|
||||||
|
assert state.attributes.get(ATTR_MAX_MIREDS) == 344
|
||||||
|
assert state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) == [COLOR_MODE_COLOR_TEMP]
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
entry = entity_registry.async_get("light.frenck")
|
entry = entity_registry.async_get("light.frenck")
|
||||||
|
@ -44,13 +57,42 @@ async def test_light_state(
|
||||||
assert entry.unique_id == "CN11A1A00001"
|
assert entry.unique_id == "CN11A1A00001"
|
||||||
|
|
||||||
|
|
||||||
async def test_light_change_state(
|
async def test_light_state_color(
|
||||||
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||||
|
) -> None:
|
||||||
|
"""Test the creation and values of the Elgato Lights in temperature mode."""
|
||||||
|
await init_integration(hass, aioclient_mock, color=True, mode_color=True)
|
||||||
|
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
|
# First segment of the strip
|
||||||
|
state = hass.states.get("light.frenck")
|
||||||
|
assert state
|
||||||
|
assert state.attributes.get(ATTR_BRIGHTNESS) == 128
|
||||||
|
assert state.attributes.get(ATTR_COLOR_TEMP) is None
|
||||||
|
assert state.attributes.get(ATTR_HS_COLOR) == (358.0, 6.0)
|
||||||
|
assert state.attributes.get(ATTR_MIN_MIREDS) == 153
|
||||||
|
assert state.attributes.get(ATTR_MAX_MIREDS) == 285
|
||||||
|
assert state.attributes.get(ATTR_COLOR_MODE) == COLOR_MODE_HS
|
||||||
|
assert state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) == [
|
||||||
|
COLOR_MODE_COLOR_TEMP,
|
||||||
|
COLOR_MODE_HS,
|
||||||
|
]
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
|
entry = entity_registry.async_get("light.frenck")
|
||||||
|
assert entry
|
||||||
|
assert entry.unique_id == "CN11A1A00001"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_change_state_temperature(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the change of state of a Elgato Key Light device."""
|
"""Test the change of state of a Elgato Key Light device."""
|
||||||
await init_integration(hass, aioclient_mock)
|
await init_integration(hass, aioclient_mock, color=True, mode_color=False)
|
||||||
|
|
||||||
state = hass.states.get("light.frenck")
|
state = hass.states.get("light.frenck")
|
||||||
|
assert state
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
|
@ -69,12 +111,25 @@ async def test_light_change_state(
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(mock_light.mock_calls) == 1
|
assert len(mock_light.mock_calls) == 1
|
||||||
mock_light.assert_called_with(on=True, brightness=100, temperature=100)
|
mock_light.assert_called_with(
|
||||||
|
on=True, brightness=100, temperature=100, hue=None, saturation=None
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: "light.frenck",
|
||||||
|
ATTR_BRIGHTNESS: 255,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(mock_light.mock_calls) == 2
|
||||||
|
mock_light.assert_called_with(
|
||||||
|
on=True, brightness=100, temperature=297, hue=None, saturation=None
|
||||||
|
)
|
||||||
|
|
||||||
with patch(
|
|
||||||
"homeassistant.components.elgato.light.Elgato.light",
|
|
||||||
return_value=mock_coro(),
|
|
||||||
) as mock_light:
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -82,14 +137,46 @@ async def test_light_change_state(
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(mock_light.mock_calls) == 1
|
assert len(mock_light.mock_calls) == 3
|
||||||
mock_light.assert_called_with(on=False)
|
mock_light.assert_called_with(on=False)
|
||||||
|
|
||||||
|
|
||||||
async def test_light_unavailable(
|
async def test_light_change_state_color(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test error/unavailable handling of an Elgato Key Light."""
|
"""Test the color state state of a Elgato Light device."""
|
||||||
|
await init_integration(hass, aioclient_mock, color=True)
|
||||||
|
|
||||||
|
state = hass.states.get("light.frenck")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.elgato.light.Elgato.light",
|
||||||
|
return_value=mock_coro(),
|
||||||
|
) as mock_light:
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: "light.frenck",
|
||||||
|
ATTR_BRIGHTNESS: 255,
|
||||||
|
ATTR_HS_COLOR: (10.1, 20.2),
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(mock_light.mock_calls) == 1
|
||||||
|
mock_light.assert_called_with(
|
||||||
|
on=True, brightness=100, temperature=None, hue=10.1, saturation=20.2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("service", [SERVICE_TURN_ON, SERVICE_TURN_OFF])
|
||||||
|
async def test_light_unavailable(
|
||||||
|
service: str, hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||||
|
) -> None:
|
||||||
|
"""Test error/unavailable handling of an Elgato Light."""
|
||||||
await init_integration(hass, aioclient_mock)
|
await init_integration(hass, aioclient_mock)
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.elgato.light.Elgato.light",
|
"homeassistant.components.elgato.light.Elgato.light",
|
||||||
|
@ -100,7 +187,7 @@ async def test_light_unavailable(
|
||||||
):
|
):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
service,
|
||||||
{ATTR_ENTITY_ID: "light.frenck"},
|
{ATTR_ENTITY_ID: "light.frenck"},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"powerOnBehavior": 2,
|
||||||
|
"powerOnHue": 40.0,
|
||||||
|
"powerOnSaturation": 15.0,
|
||||||
|
"powerOnBrightness": 40,
|
||||||
|
"powerOnTemperature": 0,
|
||||||
|
"switchOnDurationMs": 150,
|
||||||
|
"switchOffDurationMs": 400,
|
||||||
|
"colorChangeDurationMs": 150
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"powerOnBehavior": 1,
|
||||||
|
"powerOnBrightness": 20,
|
||||||
|
"powerOnTemperature": 213,
|
||||||
|
"switchOnDurationMs": 100,
|
||||||
|
"switchOffDurationMs": 300,
|
||||||
|
"colorChangeDurationMs": 100
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"numberOfLights": 1,
|
||||||
|
"lights": [
|
||||||
|
{
|
||||||
|
"on": 1,
|
||||||
|
"hue": 358.0,
|
||||||
|
"saturation": 6.0,
|
||||||
|
"brightness": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue