Stub light profiles (#42232)

This commit is contained in:
Paulus Schoutsen 2020-10-23 16:28:21 +02:00 committed by GitHub
parent b626df1316
commit 5dac3883b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 220 additions and 243 deletions

View File

@ -199,11 +199,11 @@ def lifx_features(bulb):
) or aiolifx().products.features_map.get(1) ) or aiolifx().products.features_map.get(1)
def find_hsbk(**kwargs): def find_hsbk(hass, **kwargs):
"""Find the desired color from a number of possible inputs.""" """Find the desired color from a number of possible inputs."""
hue, saturation, brightness, kelvin = [None] * 4 hue, saturation, brightness, kelvin = [None] * 4
preprocess_turn_on_alternatives(kwargs) preprocess_turn_on_alternatives(hass, kwargs)
if ATTR_HS_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
hue, saturation = kwargs[ATTR_HS_COLOR] hue, saturation = kwargs[ATTR_HS_COLOR]
@ -330,11 +330,11 @@ class LIFXManager:
period=kwargs.get(ATTR_PERIOD), period=kwargs.get(ATTR_PERIOD),
cycles=kwargs.get(ATTR_CYCLES), cycles=kwargs.get(ATTR_CYCLES),
mode=kwargs.get(ATTR_MODE), mode=kwargs.get(ATTR_MODE),
hsbk=find_hsbk(**kwargs), hsbk=find_hsbk(self.hass, **kwargs),
) )
await self.effects_conductor.start(effect, bulbs) await self.effects_conductor.start(effect, bulbs)
elif service == SERVICE_EFFECT_COLORLOOP: elif service == SERVICE_EFFECT_COLORLOOP:
preprocess_turn_on_alternatives(kwargs) preprocess_turn_on_alternatives(self.hass, kwargs)
brightness = None brightness = None
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
@ -600,7 +600,7 @@ class LIFXLight(LightEntity):
power_on = kwargs.get(ATTR_POWER, False) power_on = kwargs.get(ATTR_POWER, False)
power_off = not kwargs.get(ATTR_POWER, True) power_off = not kwargs.get(ATTR_POWER, True)
hsbk = find_hsbk(**kwargs) hsbk = find_hsbk(self.hass, **kwargs)
# Send messages, waiting for ACK each time # Send messages, waiting for ACK each time
ack = AwaitAioLIFX().wait ack = AwaitAioLIFX().wait

View File

@ -3,7 +3,6 @@ import csv
from datetime import timedelta from datetime import timedelta
import logging import logging
import os import os
from typing import Dict, Optional, Tuple
import voluptuous as vol import voluptuous as vol
@ -13,6 +12,7 @@ from homeassistant.const import (
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_ON, STATE_ON,
) )
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401 from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
@ -28,6 +28,7 @@ import homeassistant.util.color as color_util
DOMAIN = "light" DOMAIN = "light"
SCAN_INTERVAL = timedelta(seconds=30) SCAN_INTERVAL = timedelta(seconds=30)
DATA_PROFILES = "light_profiles"
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
@ -122,15 +123,6 @@ LIGHT_TURN_ON_SCHEMA = {
} }
PROFILE_SCHEMA = vol.Schema(
vol.Any(
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte)),
vol.ExactSequence(
(str, cv.small_float, cv.small_float, cv.byte, cv.positive_int)
),
)
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -140,14 +132,17 @@ def is_on(hass, entity_id):
return hass.states.is_state(entity_id, STATE_ON) return hass.states.is_state(entity_id, STATE_ON)
def preprocess_turn_on_alternatives(params): def preprocess_turn_on_alternatives(hass, params):
"""Process extra data for turn light on request.""" """Process extra data for turn light on request.
profile = Profiles.get(params.pop(ATTR_PROFILE, None))
if profile is not None: Async friendly.
params.setdefault(ATTR_XY_COLOR, profile[:2]) """
params.setdefault(ATTR_BRIGHTNESS, profile[2]) # Bail out, we process this later.
if len(profile) > 3: if ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params:
params.setdefault(ATTR_TRANSITION, profile[3]) return
if ATTR_PROFILE in params:
hass.data[DATA_PROFILES].apply_profile(params.pop(ATTR_PROFILE), params)
color_name = params.pop(ATTR_COLOR_NAME, None) color_name = params.pop(ATTR_COLOR_NAME, None)
if color_name is not None: if color_name is not None:
@ -174,24 +169,12 @@ def preprocess_turn_on_alternatives(params):
if rgb_color is not None: if rgb_color is not None:
params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
return params
def filter_turn_off_params(params): def filter_turn_off_params(params):
"""Filter out params not used in turn off.""" """Filter out params not used in turn off."""
return {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)} return {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)}
def preprocess_turn_off(params):
"""Process data for turning light off if brightness is 0."""
if ATTR_BRIGHTNESS in params and params[ATTR_BRIGHTNESS] == 0:
# Zero brightness: Light will be turned off
params = filter_turn_off_params(params)
return (True, params) # Light should be turned off
return (False, None) # Light should be turned on
async def async_setup(hass, config): async def async_setup(hass, config):
"""Expose light control via state machine and services.""" """Expose light control via state machine and services."""
component = hass.data[DOMAIN] = EntityComponent( component = hass.data[DOMAIN] = EntityComponent(
@ -199,10 +182,8 @@ async def async_setup(hass, config):
) )
await component.async_setup(config) await component.async_setup(config)
# load profiles from files profiles = hass.data[DATA_PROFILES] = Profiles(hass)
profiles_valid = await Profiles.load_profiles(hass) await profiles.async_initialize()
if not profiles_valid:
return False
def preprocess_data(data): def preprocess_data(data):
"""Preprocess the service data.""" """Preprocess the service data."""
@ -212,7 +193,8 @@ async def async_setup(hass, config):
if entity_field in data if entity_field in data
} }
base["params"] = preprocess_turn_on_alternatives(data) preprocess_turn_on_alternatives(hass, data)
base["params"] = data
return base return base
async def async_handle_light_on_service(light, call): async def async_handle_light_on_service(light, call):
@ -223,17 +205,14 @@ async def async_setup(hass, config):
params = call.data["params"] params = call.data["params"]
if not params: if not params:
default_profile = Profiles.get_default(light.entity_id) profiles.apply_default(light.entity_id, params)
if default_profile is not None: # Only process params once we processed brightness step
params = {ATTR_PROFILE: default_profile} if params and (
preprocess_turn_on_alternatives(params) ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params
):
elif ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params:
brightness = light.brightness if light.is_on else 0 brightness = light.brightness if light.is_on else 0
params = params.copy()
if ATTR_BRIGHTNESS_STEP in params: if ATTR_BRIGHTNESS_STEP in params:
brightness += params.pop(ATTR_BRIGHTNESS_STEP) brightness += params.pop(ATTR_BRIGHTNESS_STEP)
@ -242,19 +221,18 @@ async def async_setup(hass, config):
params[ATTR_BRIGHTNESS] = max(0, min(255, brightness)) params[ATTR_BRIGHTNESS] = max(0, min(255, brightness))
turn_light_off, off_params = preprocess_turn_off(params) preprocess_turn_on_alternatives(hass, params)
if turn_light_off:
await light.async_turn_off(**off_params) # Zero brightness: Light will be turned off
if params.get(ATTR_BRIGHTNESS) == 0:
await light.async_turn_off(**filter_turn_off_params(params))
else: else:
await light.async_turn_on(**params) await light.async_turn_on(**params)
async def async_handle_toggle_service(light, call): async def async_handle_toggle_service(light, call):
"""Handle toggling a light. """Handle toggling a light."""
If brightness is set to 0, this service will turn the light off.
"""
if light.is_on: if light.is_on:
off_params = filter_turn_off_params(call.data["params"]) off_params = filter_turn_off_params(call.data)
await light.async_turn_off(**off_params) await light.async_turn_off(**off_params)
else: else:
await async_handle_light_on_service(light, call) await async_handle_light_on_service(light, call)
@ -295,73 +273,89 @@ async def async_unload_entry(hass, entry):
class Profiles: class Profiles:
"""Representation of available color profiles.""" """Representation of available color profiles."""
_all: Optional[Dict[str, Tuple[float, float, int]]] = None SCHEMA = vol.Schema(
vol.Any(
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte)),
vol.ExactSequence(
(str, cv.small_float, cv.small_float, cv.byte, cv.positive_int)
),
)
)
@classmethod def __init__(self, hass):
async def load_profiles(cls, hass): """Initialize profiles."""
"""Load and cache profiles.""" self.hass = hass
self.data = None
def load_profile_data(hass): def _load_profile_data(self):
"""Load built-in profiles and custom profiles.""" """Load built-in profiles and custom profiles."""
profile_paths = [ profile_paths = [
os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE), os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE),
hass.config.path(LIGHT_PROFILES_FILE), self.hass.config.path(LIGHT_PROFILES_FILE),
] ]
profiles = {} profiles = {}
for profile_path in profile_paths: for profile_path in profile_paths:
if not os.path.isfile(profile_path): if not os.path.isfile(profile_path):
continue continue
with open(profile_path) as inp: with open(profile_path) as inp:
reader = csv.reader(inp) reader = csv.reader(inp)
# Skip the header # Skip the header
next(reader, None) next(reader, None)
try: try:
for rec in reader: for rec in reader:
( (
profile, profile,
color_x, color_x,
color_y, color_y,
brightness, brightness,
*transition, *transition,
) = PROFILE_SCHEMA(rec) ) = Profiles.SCHEMA(rec)
transition = transition[0] if transition else 0 transition = transition[0] if transition else 0
profiles[profile] = ( profiles[profile] = color_util.color_xy_to_hs(
color_x, color_x, color_y
color_y, ) + (
brightness, brightness,
transition, transition,
)
except vol.MultipleInvalid as ex:
_LOGGER.error(
"Error parsing light profile from %s: %s", profile_path, ex
) )
return None except vol.MultipleInvalid as ex:
return profiles _LOGGER.error(
"Error parsing light profile from %s: %s", profile_path, ex
)
continue
return profiles
cls._all = await hass.async_add_executor_job(load_profile_data, hass) async def async_initialize(self):
return cls._all is not None """Load and cache profiles."""
self.data = await self.hass.async_add_executor_job(self._load_profile_data)
@classmethod @callback
def get(cls, name): def apply_default(self, entity_id, params):
"""Return a named profile."""
return cls._all.get(name)
@classmethod
def get_default(cls, entity_id):
"""Return the default turn-on profile for the given light.""" """Return the default turn-on profile for the given light."""
# pylint: disable=unsupported-membership-test
name = f"{entity_id}.default" name = f"{entity_id}.default"
if name in cls._all: if name in self.data:
return name self.apply_profile(name, params)
return
name = "group.all_lights.default" name = "group.all_lights.default"
if name in cls._all: if name in self.data:
return name self.apply_profile(name, params)
return None
@callback
def apply_profile(self, name, params):
"""Apply a profile."""
profile = self.data.get(name)
if profile is None:
return
params.setdefault(ATTR_HS_COLOR, profile[:2])
params.setdefault(ATTR_BRIGHTNESS, profile[2])
params.setdefault(ATTR_TRANSITION, profile[3])
class LightEntity(ToggleEntity): class LightEntity(ToggleEntity):

View File

@ -3,6 +3,7 @@ import abodepy.helpers.constants as CONST
import pytest import pytest
from tests.common import load_fixture from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)

View File

@ -0,0 +1,2 @@
"""axis conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""PyTest fixtures and test helpers.""" """PyTest fixtures and test helpers."""
from unittest import mock from unittest import mock
import blebox_uniapi import blebox_uniapi
@ -11,6 +10,7 @@ from homeassistant.setup import async_setup_component
from tests.async_mock import AsyncMock, PropertyMock, patch from tests.async_mock import AsyncMock, PropertyMock, patch
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
def patch_product_identify(path=None, **kwargs): def patch_product_identify(path=None, **kwargs):

View File

@ -0,0 +1,2 @@
"""bond conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""deconz conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""demo conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""dynalite conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""elgato conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""everlights conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""group conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -8,6 +8,7 @@ import pytest
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
import tests.async_mock import tests.async_mock
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture @pytest.fixture

View File

@ -24,6 +24,7 @@ from .helper import AUTH_TOKEN, HAPID, HAPPIN, HomeFactory
from tests.async_mock import AsyncMock, MagicMock, Mock, patch from tests.async_mock import AsyncMock, MagicMock, Mock, patch
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="mock_connection") @pytest.fixture(name="mock_connection")

View File

@ -12,6 +12,7 @@ from homeassistant.components import hue
from homeassistant.components.hue import sensor_base as hue_sensor_base from homeassistant.components.hue import sensor_base as hue_sensor_base
from tests.async_mock import AsyncMock, Mock, patch from tests.async_mock import AsyncMock, Mock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)

View File

@ -0,0 +1,2 @@
"""hyperion conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,26 @@
"""Light conftest."""
import pytest
from homeassistant.components.light import Profiles
from tests.async_mock import AsyncMock, patch
@pytest.fixture(autouse=True)
def mock_light_profiles():
"""Mock loading of profiles."""
data = {}
def mock_profiles_class(hass):
profiles = Profiles(hass)
profiles.data = data
profiles.async_initialize = AsyncMock()
return profiles
with patch(
"homeassistant.components.light.Profiles",
SCHEMA=Profiles.SCHEMA,
side_effect=mock_profiles_class,
):
yield data

View File

@ -1,8 +1,4 @@
"""The tests for the Light component.""" """The tests for the Light component."""
# pylint: disable=protected-access
from io import StringIO
import os
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@ -20,19 +16,11 @@ from homeassistant.const import (
) )
from homeassistant.exceptions import Unauthorized from homeassistant.exceptions import Unauthorized
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import color
import tests.async_mock as mock
from tests.common import async_mock_service from tests.common import async_mock_service
orig_Profiles = light.Profiles
@pytest.fixture
def mock_storage(hass, hass_storage):
"""Clean up user light files at the end."""
yield
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
if os.path.isfile(user_light_file):
os.remove(user_light_file)
async def test_methods(hass): async def test_methods(hass):
@ -117,7 +105,7 @@ async def test_methods(hass):
assert call.data[light.ATTR_TRANSITION] == "transition_val" assert call.data[light.ATTR_TRANSITION] == "transition_val"
async def test_services(hass): async def test_services(hass, mock_light_profiles):
"""Test the provided services.""" """Test the provided services."""
platform = getattr(hass.components, "test.light") platform = getattr(hass.components, "test.light")
@ -292,6 +280,7 @@ async def test_services(hass):
assert data == {} assert data == {}
# One of the light profiles # One of the light profiles
mock_light_profiles["relax"] = (35.932, 69.412, 144, 0)
prof_name, prof_h, prof_s, prof_bri, prof_t = "relax", 35.932, 69.412, 144, 0 prof_name, prof_h, prof_s, prof_bri, prof_t = "relax", 35.932, 69.412, 144, 0
# Test light profiles # Test light profiles
@ -418,34 +407,13 @@ async def test_services(hass):
assert data == {} assert data == {}
async def test_broken_light_profiles(hass, mock_storage): async def test_light_profiles(hass, mock_light_profiles):
"""Test light profiles.""" """Test light profiles."""
platform = getattr(hass.components, "test.light") platform = getattr(hass.components, "test.light")
platform.init() platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE) mock_light_profiles["test"] = color.color_xy_to_hs(0.4, 0.6) + (100, 0)
mock_light_profiles["test_off"] = 0, 0, 0, 0
# Setup a wrong light file
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness,transition\n")
user_file.write("I,WILL,NOT,WORK,EVER\n")
assert not await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
async def test_light_profiles(hass, mock_storage):
"""Test light profiles."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness\n")
user_file.write("test,.4,.6,100\n")
user_file.write("test_off,0,0,0\n")
assert await async_setup_component( assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}} hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
@ -484,80 +452,21 @@ async def test_light_profiles(hass, mock_storage):
assert data == {light.ATTR_TRANSITION: 0} assert data == {light.ATTR_TRANSITION: 0}
async def test_light_profiles_with_transition(hass, mock_storage): async def test_default_profiles_group(hass, mock_light_profiles):
"""Test light profiles with transition.""" """Test default turn-on light profile for all lights."""
platform = getattr(hass.components, "test.light") platform = getattr(hass.components, "test.light")
platform.init() platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness,transition\n")
user_file.write("test,.4,.6,100,2\n")
user_file.write("test_off,0,0,0,0\n")
assert await async_setup_component( assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}} hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
) )
await hass.async_block_till_done() await hass.async_block_till_done()
ent1, _, _ = platform.ENTITIES mock_light_profiles["group.all_lights.default"] = color.color_xy_to_hs(0.4, 0.6) + (
99,
await hass.services.async_call( 2,
light.DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test"},
blocking=True,
) )
_, data = ent1.last_call("turn_on")
assert light.is_on(hass, ent1.entity_id)
assert data == {
light.ATTR_HS_COLOR: (71.059, 100),
light.ATTR_BRIGHTNESS: 100,
light.ATTR_TRANSITION: 2,
}
await hass.services.async_call(
light.DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test_off"},
blocking=True,
)
_, data = ent1.last_call("turn_off")
assert not light.is_on(hass, ent1.entity_id)
assert data == {light.ATTR_TRANSITION: 0}
async def test_default_profiles_group(hass, mock_storage):
"""Test default turn-on light profile for all lights."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
real_isfile = os.path.isfile
real_open = open
def _mock_isfile(path):
if path == user_light_file:
return True
return real_isfile(path)
def _mock_open(path, *args, **kwargs):
if path == user_light_file:
return StringIO(profile_data)
return real_open(path, *args, **kwargs)
profile_data = "id,x,y,brightness,transition\ngroup.all_lights.default,.4,.6,99,2\n"
with mock.patch("os.path.isfile", side_effect=_mock_isfile), mock.patch(
"builtins.open", side_effect=_mock_open
):
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
ent, _, _ = platform.ENTITIES ent, _, _ = platform.ENTITIES
await hass.services.async_call( await hass.services.async_call(
light.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ent.entity_id}, blocking=True light.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ent.entity_id}, blocking=True
@ -571,37 +480,24 @@ async def test_default_profiles_group(hass, mock_storage):
} }
async def test_default_profiles_light(hass, mock_storage): async def test_default_profiles_light(hass, mock_light_profiles):
"""Test default turn-on light profile for a specific light.""" """Test default turn-on light profile for a specific light."""
platform = getattr(hass.components, "test.light") platform = getattr(hass.components, "test.light")
platform.init() platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE) assert await async_setup_component(
real_isfile = os.path.isfile hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
real_open = open )
await hass.async_block_till_done()
def _mock_isfile(path):
if path == user_light_file: mock_light_profiles["group.all_lights.default"] = color.color_xy_to_hs(0.3, 0.5) + (
return True 200,
return real_isfile(path) 0,
)
def _mock_open(path, *args, **kwargs): mock_light_profiles["light.ceiling_2.default"] = color.color_xy_to_hs(0.6, 0.6) + (
if path == user_light_file: 100,
return StringIO(profile_data) 3,
return real_open(path, *args, **kwargs)
profile_data = (
"id,x,y,brightness,transition\n"
+ "group.all_lights.default,.3,.5,200,0\n"
+ "light.ceiling_2.default,.6,.6,100,3\n"
) )
with mock.patch("os.path.isfile", side_effect=_mock_isfile), mock.patch(
"builtins.open", side_effect=_mock_open
):
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
dev = next(filter(lambda x: x.entity_id == "light.ceiling_2", platform.ENTITIES)) dev = next(filter(lambda x: x.entity_id == "light.ceiling_2", platform.ENTITIES))
await hass.services.async_call( await hass.services.async_call(
@ -775,3 +671,15 @@ def test_deprecated_base_class(caplog):
CustomLight() CustomLight()
assert "Light is deprecated, modify CustomLight" in caplog.text assert "Light is deprecated, modify CustomLight" in caplog.text
async def test_profiles(hass):
"""Test profiles loading."""
profiles = orig_Profiles(hass)
await profiles.async_initialize()
assert profiles.data == {
"concentrate": (35.932, 69.412, 219, 0),
"energize": (43.333, 21.176, 203, 0),
"reading": (38.88, 49.02, 240, 0),
"relax": (35.932, 69.412, 144, 0),
}

View File

@ -0,0 +1,2 @@
"""litejet conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""mochad conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1 +1,2 @@
"""Test fixtures for mqtt component.""" """Test fixtures for mqtt component."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -7,6 +7,7 @@ from .common import MQTTMessage
from tests.async_mock import patch from tests.async_mock import patch
from tests.common import load_fixture from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="generic_data", scope="session") @pytest.fixture(name="generic_data", scope="session")

View File

@ -0,0 +1,2 @@
"""rflink conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -9,6 +9,7 @@ from homeassistant.util.dt import utcnow
from tests.async_mock import patch from tests.async_mock import patch
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
from tests.components.light.conftest import mock_light_profiles # noqa
def create_rfx_test_cfg(device="abcd", automatic_add=False, devices=None): def create_rfx_test_cfg(device="abcd", automatic_add=False, devices=None):

View File

@ -5,6 +5,7 @@ import pytest
import requests_mock import requests_mock
from tests.common import load_fixture from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="requests_mock") @pytest.fixture(name="requests_mock")

View File

@ -47,6 +47,7 @@ from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch from tests.async_mock import Mock, patch
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
COMPONENT_PREFIX = "homeassistant.components.smartthings." COMPONENT_PREFIX = "homeassistant.components.smartthings."

View File

@ -0,0 +1,2 @@
"""switch conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""Test fixtures for Tasmota component.""" """Test fixtures for Tasmota component."""
from hatasmota.discovery import get_status_sensor_entities from hatasmota.discovery import get_status_sensor_entities
import pytest import pytest
@ -17,6 +16,7 @@ from tests.common import (
mock_device_registry, mock_device_registry,
mock_registry, mock_registry,
) )
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture @pytest.fixture

View File

@ -0,0 +1,2 @@
"""template conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""tplink conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -4,6 +4,7 @@ import pytest
from . import MOCK_GATEWAY_ID from . import MOCK_GATEWAY_ID
from tests.async_mock import Mock, patch from tests.async_mock import Mock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
# pylint: disable=protected-access # pylint: disable=protected-access

View File

@ -1,10 +1,10 @@
"""Fixtures for tests.""" """Fixtures for tests."""
import pytest import pytest
from .common import ComponentFactory from .common import ComponentFactory
from tests.async_mock import patch from tests.async_mock import patch
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture() @pytest.fixture()

View File

@ -0,0 +1,2 @@
"""wilight conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""wled conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""yeelight conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""zerproc conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""Test configuration for the ZHA component.""" """Test configuration for the ZHA component."""
import pytest import pytest
import zigpy import zigpy
from zigpy.application import ControllerApplication from zigpy.application import ControllerApplication
@ -16,6 +15,7 @@ from .common import FakeDevice, FakeEndpoint, get_zha_gateway
from tests.async_mock import AsyncMock, MagicMock, PropertyMock, patch from tests.async_mock import AsyncMock, MagicMock, PropertyMock, patch
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
FIXTURE_GRP_ID = 0x1001 FIXTURE_GRP_ID = 0x1001
FIXTURE_GRP_NAME = "fixture group" FIXTURE_GRP_NAME = "fixture group"

View File

@ -4,6 +4,7 @@ import pytest
from homeassistant.components.zwave import const from homeassistant.components.zwave import const
from tests.async_mock import AsyncMock, MagicMock, patch from tests.async_mock import AsyncMock, MagicMock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
from tests.mock.zwave import MockNetwork, MockNode, MockOption, MockValue from tests.mock.zwave import MockNetwork, MockNode, MockOption, MockValue