mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add Home Connect light entity for cooling appliances (#126090)
* Add Home Connect light entities for fridge * Update homeassistant/components/home_connect/light.py --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
2ae4989031
commit
4d04402ad4
@ -32,6 +32,15 @@ COFFEE_EVENT_BEAN_CONTAINER_EMPTY = (
|
|||||||
COFFEE_EVENT_WATER_TANK_EMPTY = "ConsumerProducts.CoffeeMaker.Event.WaterTankEmpty"
|
COFFEE_EVENT_WATER_TANK_EMPTY = "ConsumerProducts.CoffeeMaker.Event.WaterTankEmpty"
|
||||||
COFFEE_EVENT_DRIP_TRAY_FULL = "ConsumerProducts.CoffeeMaker.Event.DripTrayFull"
|
COFFEE_EVENT_DRIP_TRAY_FULL = "ConsumerProducts.CoffeeMaker.Event.DripTrayFull"
|
||||||
|
|
||||||
|
REFRIGERATION_INTERNAL_LIGHT_POWER = "Refrigeration.Common.Setting.Light.Internal.Power"
|
||||||
|
REFRIGERATION_INTERNAL_LIGHT_BRIGHTNESS = (
|
||||||
|
"Refrigeration.Common.Setting.Light.Internal.Brightness"
|
||||||
|
)
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_POWER = "Refrigeration.Common.Setting.Light.External.Power"
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS = (
|
||||||
|
"Refrigeration.Common.Setting.Light.External.Brightness"
|
||||||
|
)
|
||||||
|
|
||||||
REFRIGERATION_SUPERMODEFREEZER = "Refrigeration.FridgeFreezer.Setting.SuperModeFreezer"
|
REFRIGERATION_SUPERMODEFREEZER = "Refrigeration.FridgeFreezer.Setting.SuperModeFreezer"
|
||||||
REFRIGERATION_SUPERMODEREFRIGERATOR = (
|
REFRIGERATION_SUPERMODEREFRIGERATOR = (
|
||||||
"Refrigeration.FridgeFreezer.Setting.SuperModeRefrigerator"
|
"Refrigeration.FridgeFreezer.Setting.SuperModeRefrigerator"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Provides a light for Home Connect."""
|
"""Provides a light for Home Connect."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
import logging
|
import logging
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -11,13 +12,15 @@ from homeassistant.components.light import (
|
|||||||
ATTR_HS_COLOR,
|
ATTR_HS_COLOR,
|
||||||
ColorMode,
|
ColorMode,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
|
LightEntityDescription,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITIES
|
from homeassistant.const import CONF_DEVICE, CONF_ENTITIES
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
import homeassistant.util.color as color_util
|
import homeassistant.util.color as color_util
|
||||||
|
|
||||||
|
from .api import HomeConnectDevice
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
BSH_AMBIENT_LIGHT_BRIGHTNESS,
|
BSH_AMBIENT_LIGHT_BRIGHTNESS,
|
||||||
@ -28,12 +31,38 @@ from .const import (
|
|||||||
COOKING_LIGHTING,
|
COOKING_LIGHTING,
|
||||||
COOKING_LIGHTING_BRIGHTNESS,
|
COOKING_LIGHTING_BRIGHTNESS,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
||||||
|
REFRIGERATION_INTERNAL_LIGHT_BRIGHTNESS,
|
||||||
|
REFRIGERATION_INTERNAL_LIGHT_POWER,
|
||||||
)
|
)
|
||||||
from .entity import HomeConnectEntity
|
from .entity import HomeConnectEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class HomeConnectLightEntityDescription(LightEntityDescription):
|
||||||
|
"""Light entity description."""
|
||||||
|
|
||||||
|
on_key: str
|
||||||
|
brightness_key: str | None
|
||||||
|
|
||||||
|
|
||||||
|
LIGHTS: tuple[HomeConnectLightEntityDescription, ...] = (
|
||||||
|
HomeConnectLightEntityDescription(
|
||||||
|
key="Internal Light",
|
||||||
|
on_key=REFRIGERATION_INTERNAL_LIGHT_POWER,
|
||||||
|
brightness_key=REFRIGERATION_INTERNAL_LIGHT_BRIGHTNESS,
|
||||||
|
),
|
||||||
|
HomeConnectLightEntityDescription(
|
||||||
|
key="External Light",
|
||||||
|
on_key=REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
||||||
|
brightness_key=REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
@ -48,7 +77,18 @@ async def async_setup_entry(
|
|||||||
for device_dict in hc_api.devices:
|
for device_dict in hc_api.devices:
|
||||||
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("light", [])
|
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("light", [])
|
||||||
entity_list = [HomeConnectLight(**d) for d in entity_dicts]
|
entity_list = [HomeConnectLight(**d) for d in entity_dicts]
|
||||||
entities += entity_list
|
device: HomeConnectDevice = device_dict[CONF_DEVICE]
|
||||||
|
# Auto-discover entities
|
||||||
|
entities.extend(
|
||||||
|
HomeConnectCoolingLight(
|
||||||
|
device=device,
|
||||||
|
ambient=False,
|
||||||
|
entity_description=description,
|
||||||
|
)
|
||||||
|
for description in LIGHTS
|
||||||
|
if description.on_key in device.appliance.status
|
||||||
|
)
|
||||||
|
entities.extend(entity_list)
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
||||||
@ -57,10 +97,14 @@ async def async_setup_entry(
|
|||||||
class HomeConnectLight(HomeConnectEntity, LightEntity):
|
class HomeConnectLight(HomeConnectEntity, LightEntity):
|
||||||
"""Light for Home Connect."""
|
"""Light for Home Connect."""
|
||||||
|
|
||||||
def __init__(self, device, desc, ambient):
|
def __init__(self, device, desc, ambient) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, desc)
|
super().__init__(device, desc)
|
||||||
self._ambient = ambient
|
self._ambient = ambient
|
||||||
|
self._percentage_scale = (10, 100)
|
||||||
|
self._brightness_key: str | None
|
||||||
|
self._custom_color_key: str | None
|
||||||
|
self._color_key: str | None
|
||||||
if ambient:
|
if ambient:
|
||||||
self._brightness_key = BSH_AMBIENT_LIGHT_BRIGHTNESS
|
self._brightness_key = BSH_AMBIENT_LIGHT_BRIGHTNESS
|
||||||
self._key = BSH_AMBIENT_LIGHT_ENABLED
|
self._key = BSH_AMBIENT_LIGHT_ENABLED
|
||||||
@ -97,10 +141,15 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying selecting customcolor: %s", err)
|
_LOGGER.error("Error while trying selecting customcolor: %s", err)
|
||||||
if self._attr_brightness is not None:
|
if self._attr_brightness is not None:
|
||||||
brightness = 10 + ceil(self._attr_brightness / 255 * 90)
|
brightness_arg = self._attr_brightness
|
||||||
if ATTR_BRIGHTNESS in kwargs:
|
if ATTR_BRIGHTNESS in kwargs:
|
||||||
brightness = 10 + ceil(kwargs[ATTR_BRIGHTNESS] / 255 * 90)
|
brightness_arg = kwargs[ATTR_BRIGHTNESS]
|
||||||
|
|
||||||
|
brightness = ceil(
|
||||||
|
color_util.brightness_to_value(
|
||||||
|
self._percentage_scale, brightness_arg
|
||||||
|
)
|
||||||
|
)
|
||||||
hs_color = kwargs.get(ATTR_HS_COLOR, self._attr_hs_color)
|
hs_color = kwargs.get(ATTR_HS_COLOR, self._attr_hs_color)
|
||||||
|
|
||||||
if hs_color is not None:
|
if hs_color is not None:
|
||||||
@ -120,8 +169,16 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif ATTR_BRIGHTNESS in kwargs:
|
elif ATTR_BRIGHTNESS in kwargs:
|
||||||
_LOGGER.debug("Changing brightness for: %s", self.name)
|
_LOGGER.debug(
|
||||||
brightness = 10 + ceil(kwargs[ATTR_BRIGHTNESS] / 255 * 90)
|
"Changing brightness for: %s, to: %s",
|
||||||
|
self.name,
|
||||||
|
kwargs[ATTR_BRIGHTNESS],
|
||||||
|
)
|
||||||
|
brightness = ceil(
|
||||||
|
color_util.brightness_to_value(
|
||||||
|
self._percentage_scale, kwargs[ATTR_BRIGHTNESS]
|
||||||
|
)
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self._brightness_key, brightness
|
self.device.appliance.set_setting, self._brightness_key, brightness
|
||||||
@ -172,7 +229,9 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
rgb = color_util.rgb_hex_to_rgb_list(colorvalue)
|
rgb = color_util.rgb_hex_to_rgb_list(colorvalue)
|
||||||
hsv = color_util.color_RGB_to_hsv(rgb[0], rgb[1], rgb[2])
|
hsv = color_util.color_RGB_to_hsv(rgb[0], rgb[1], rgb[2])
|
||||||
self._attr_hs_color = (hsv[0], hsv[1])
|
self._attr_hs_color = (hsv[0], hsv[1])
|
||||||
self._attr_brightness = ceil((hsv[2] - 10) * 255 / 90)
|
self._attr_brightness = color_util.value_to_brightness(
|
||||||
|
self._percentage_scale, hsv[2]
|
||||||
|
)
|
||||||
_LOGGER.debug("Updated, new brightness: %s", self._attr_brightness)
|
_LOGGER.debug("Updated, new brightness: %s", self._attr_brightness)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -180,7 +239,24 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
if brightness is None:
|
if brightness is None:
|
||||||
self._attr_brightness = None
|
self._attr_brightness = None
|
||||||
else:
|
else:
|
||||||
self._attr_brightness = ceil(
|
self._attr_brightness = color_util.value_to_brightness(
|
||||||
(brightness.get(ATTR_VALUE) - 10) * 255 / 90
|
self._percentage_scale, brightness[ATTR_VALUE]
|
||||||
)
|
)
|
||||||
_LOGGER.debug("Updated, new brightness: %s", self._attr_brightness)
|
_LOGGER.debug("Updated, new brightness: %s", self._attr_brightness)
|
||||||
|
|
||||||
|
|
||||||
|
class HomeConnectCoolingLight(HomeConnectLight):
|
||||||
|
"""Light entity for Cooling Appliances."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: HomeConnectDevice,
|
||||||
|
ambient: bool,
|
||||||
|
entity_description: HomeConnectLightEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize Cooling Light Entity."""
|
||||||
|
super().__init__(device, entity_description.key, ambient)
|
||||||
|
self.entity_description = entity_description
|
||||||
|
self._key = entity_description.on_key
|
||||||
|
self._brightness_key = entity_description.brightness_key
|
||||||
|
self._percentage_scale = (1, 100)
|
||||||
|
@ -138,6 +138,22 @@
|
|||||||
"constraints": {
|
"constraints": {
|
||||||
"access": "readWrite"
|
"access": "readWrite"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Refrigeration.Common.Setting.Light.External.Power",
|
||||||
|
"value": true,
|
||||||
|
"type": "Boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Refrigeration.Common.Setting.Light.External.Brightness",
|
||||||
|
"value": 70,
|
||||||
|
"unit": "%",
|
||||||
|
"type": "Double",
|
||||||
|
"constraints": {
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"access": "readWrite"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from collections.abc import Awaitable, Callable, Generator
|
from collections.abc import Awaitable, Callable, Generator
|
||||||
from unittest.mock import MagicMock, Mock
|
from unittest.mock import MagicMock, Mock
|
||||||
|
|
||||||
from homeconnect.api import HomeConnectError
|
from homeconnect.api import HomeConnectAppliance, HomeConnectError
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.home_connect.const import (
|
from homeassistant.components.home_connect.const import (
|
||||||
@ -12,6 +12,8 @@ from homeassistant.components.home_connect.const import (
|
|||||||
BSH_AMBIENT_LIGHT_ENABLED,
|
BSH_AMBIENT_LIGHT_ENABLED,
|
||||||
COOKING_LIGHTING,
|
COOKING_LIGHTING,
|
||||||
COOKING_LIGHTING_BRIGHTNESS,
|
COOKING_LIGHTING_BRIGHTNESS,
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
||||||
)
|
)
|
||||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
@ -148,6 +150,19 @@ async def test_light(
|
|||||||
STATE_ON,
|
STATE_ON,
|
||||||
"Hood",
|
"Hood",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"light.fridgefreezer_external_light",
|
||||||
|
{
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_POWER: {
|
||||||
|
"value": True,
|
||||||
|
},
|
||||||
|
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS: {"value": 75},
|
||||||
|
},
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{},
|
||||||
|
STATE_ON,
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
indirect=["appliance"],
|
indirect=["appliance"],
|
||||||
)
|
)
|
||||||
@ -166,7 +181,14 @@ async def test_light_functionality(
|
|||||||
get_appliances: MagicMock,
|
get_appliances: MagicMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test light functionality."""
|
"""Test light functionality."""
|
||||||
appliance.status.update(SETTINGS_STATUS)
|
appliance.status.update(
|
||||||
|
HomeConnectAppliance.json2dict(
|
||||||
|
load_json_object_fixture("home_connect/settings.json")
|
||||||
|
.get(appliance.name)
|
||||||
|
.get("data")
|
||||||
|
.get("settings")
|
||||||
|
)
|
||||||
|
)
|
||||||
get_appliances.return_value = [appliance]
|
get_appliances.return_value = [appliance]
|
||||||
|
|
||||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||||
|
Loading…
x
Reference in New Issue
Block a user