diff --git a/custom_components/home_connect_beta/api.py b/custom_components/home_connect_beta/api.py index 0961153..0aea4e7 100644 --- a/custom_components/home_connect_beta/api.py +++ b/custom_components/home_connect_beta/api.py @@ -1,7 +1,7 @@ """API for Home Connect bound to HASS OAuth.""" -from asyncio import run_coroutine_threadsafe import logging +from asyncio import run_coroutine_threadsafe import homeconnect from homeconnect.api import HomeConnectError @@ -13,8 +13,10 @@ from .const import ( BSH_ACTIVE_PROGRAM, + BSH_AMBIENTLIGHTENABLED, BSH_POWER_OFF, BSH_POWER_STANDBY, + COOKING_LIGHTING, SIGNAL_UPDATE_ENTITIES, ) @@ -179,6 +181,19 @@ def get_light_entity(self): return { "device": self, "desc": "Light", + "ambient" : None, + } + + +class DeviceWithAmbientLight(HomeConnectDevice): + """Device that has ambient lighting.""" + + def get_ambientlight_entity(self): + """Get a dictionary with info about the ambient lighting.""" + return { + "device": self, + "desc": "AmbientLight", + "ambient" : True, } @@ -216,8 +231,6 @@ def get_entity_info(self): } - - class WasherDryer(DeviceWithDoor, DeviceWithPrograms): """Washer class.""" @@ -273,7 +286,7 @@ def get_entity_info(self): } -class Dishwasher(DeviceWithDoor, DeviceWithPrograms): +class Dishwasher(DeviceWithDoor, DeviceWithAmbientLight, DeviceWithPrograms): """Dishwasher class.""" PROGRAMS = [ @@ -303,6 +316,7 @@ class Dishwasher(DeviceWithDoor, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" + ambientlight_entity = self.get_ambientlight_entity() door_entity = self.get_door_entity() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() @@ -310,6 +324,7 @@ def get_entity_info(self): "binary_sensor": [door_entity], "switch": program_switches, "sensor": program_sensors, + "light": [ambientlight_entity] } @@ -430,7 +445,7 @@ def get_entity_info(self): return {"switch": program_switches, "sensor": program_sensors} -class Hood(DeviceWithLight, DeviceWithPrograms): +class Hood(DeviceWithLight, DeviceWithAmbientLight, DeviceWithPrograms): """Hood class.""" PROGRAMS = [ @@ -442,12 +457,13 @@ class Hood(DeviceWithLight, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" light_entity = self.get_light_entity() + ambientlight_entity = self.get_ambientlight_entity() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { "switch": program_switches, "sensor": program_sensors, - "light" : [light_entity], + "light" : [light_entity, ambientlight_entity] } diff --git a/custom_components/home_connect_beta/const.py b/custom_components/home_connect_beta/const.py index ad2430d..124f093 100644 --- a/custom_components/home_connect_beta/const.py +++ b/custom_components/home_connect_beta/const.py @@ -11,8 +11,16 @@ BSH_POWER_STANDBY = "BSH.Common.EnumType.PowerState.Standby" BSH_ACTIVE_PROGRAM = "BSH.Common.Root.ActiveProgram" BSH_OPERATION_STATE = "BSH.Common.Status.OperationState" + COOKING_LIGHTING = "Cooking.Common.Setting.Lighting" COOKING_LIGHTINGBRIGHTNESS = "Cooking.Common.Setting.LightingBrightness" + +BSH_AMBIENTLIGHTENABLED = "BSH.Common.Setting.AmbientLightEnabled" +BSH_AMBIENTLIGHTBRIGHTNESS = "BSH.Common.Setting.AmbientLightBrightness" +BSH_AMBIENTLIGHTCOLOR = "BSH.Common.Setting.AmbientLightColor" +BSH_AMBIENTLIGHTCOLOR_CUSTOMCOLOR = "BSH.Common.EnumType.AmbientLightColor.CustomColor" +BSH_AMBIENTLIGHTCUSTOMCOLOR = "BSH.Common.Setting.AmbientLightCustomColor" + BSH_DOOR_STATE = "BSH.Common.Status.DoorState" BSH_PAUSE = "BSH.Common.Command.PauseProgram" BSH_RESUME = "BSH.Common.Command.ResumeProgram" @@ -28,4 +36,4 @@ ATTR_PROGRAM = "program" ATTR_KEY = "key" -ATTR_VALUE = "value" \ No newline at end of file +ATTR_VALUE = "value" diff --git a/custom_components/home_connect_beta/light.py b/custom_components/home_connect_beta/light.py index 4864844..57fd0c7 100644 --- a/custom_components/home_connect_beta/light.py +++ b/custom_components/home_connect_beta/light.py @@ -4,13 +4,25 @@ from homeconnect.api import HomeConnectError +import homeassistant.util.color as color_util from homeassistant.components.light import ( ATTR_BRIGHTNESS, - LightEntity, + ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, + LightEntity, ) -from .const import COOKING_LIGHTING, COOKING_LIGHTINGBRIGHTNESS, DOMAIN +from .const import ( + BSH_AMBIENTLIGHTBRIGHTNESS, + BSH_AMBIENTLIGHTCOLOR, + BSH_AMBIENTLIGHTCOLOR_CUSTOMCOLOR, + BSH_AMBIENTLIGHTCUSTOMCOLOR, + BSH_AMBIENTLIGHTENABLED, + COOKING_LIGHTING, + COOKING_LIGHTINGBRIGHTNESS, + DOMAIN, +) from .entity import HomeConnectEntity _LOGGER = logging.getLogger(__name__) @@ -35,11 +47,23 @@ def get_entities(): class HomeConnectLight(HomeConnectEntity, LightEntity): """Light for Home Connect.""" - def __init__(self, device, desc): + def __init__(self, device, desc, ambient): """Initialize the entity.""" super().__init__(device, desc) self._state = None self._brightness = None + self._hs_color = None + self._ambient = ambient + if self._ambient: + self._brightnesskey = BSH_AMBIENTLIGHTBRIGHTNESS + self._key = BSH_AMBIENTLIGHTENABLED + self._customcolorkey = BSH_AMBIENTLIGHTCUSTOMCOLOR + self._colorkey = BSH_AMBIENTLIGHTCOLOR + else: + self._brightnesskey = COOKING_LIGHTINGBRIGHTNESS + self._key = COOKING_LIGHTING + self._customcolorkey = None + self._colorkey = None @property def is_on(self): @@ -51,22 +75,68 @@ def brightness(self): """Return the brightness of the light.""" return self._brightness + @property + def hs_color(self): + """Return the color property.""" + return self._hs_color + @property def supported_features(self): """Flag supported features.""" + if self._ambient: + return SUPPORT_BRIGHTNESS | SUPPORT_COLOR return SUPPORT_BRIGHTNESS async def async_turn_on(self, **kwargs): - """Switch the light on / change brightness.""" - if ATTR_BRIGHTNESS in kwargs: + """Switch the light on, change brightness, change color.""" + if self._ambient: + if ATTR_BRIGHTNESS in kwargs or ATTR_HS_COLOR in kwargs: + try: + await self.hass.async_add_executor_job( + self.device.appliance.set_setting, + self._colorkey, + BSH_AMBIENTLIGHTCOLOR_CUSTOMCOLOR, + ) + except HomeConnectError as err: + _LOGGER.error("Error while trying selecting customcolor: %s", err) + if self._brightness != None: + brightness = 10 + ceil(self._brightness / 255 * 90) + if ATTR_BRIGHTNESS in kwargs: + brightness = 10 + ceil(kwargs[ATTR_BRIGHTNESS] / 255 * 90) + + hs_color = self._hs_color + if ATTR_HS_COLOR in kwargs: + hs_color = kwargs[ATTR_HS_COLOR] + + if hs_color != None: + rgb = color_util.color_hsv_to_RGB(*hs_color, brightness) + hex = color_util.color_rgb_to_hex(rgb[0], rgb[1], rgb[2]) + try: + await self.hass.async_add_executor_job( + self.device.appliance.set_setting, + self._customcolorkey, + "#" + hex, + ) + except HomeConnectError as err: + _LOGGER.error("Error while trying setting the color: %s", err) + self._state = False + else: + _LOGGER.debug("Tried to switch light on for: %s", self.name) + try: + await self.hass.async_add_executor_job( + self.device.appliance.set_setting, self._key, True, + ) + except HomeConnectError as err: + _LOGGER.error("Error while trying to turn on ambient light: %s", err) + self._state = False + + elif ATTR_BRIGHTNESS in kwargs: _LOGGER.debug("Tried to change brightness for: %s", self.name) - """Convert Home Assistant brightness (0-255) to Home Connect brightness (10-100)""" + """Convert Home Assistant brightness (0-255) to Home Connect brightness (10-100).""" brightness = 10 + ceil(kwargs[ATTR_BRIGHTNESS] / 255 * 90) try: await self.hass.async_add_executor_job( - self.device.appliance.set_setting, - COOKING_LIGHTINGBRIGHTNESS, - brightness, + self.device.appliance.set_setting, self._brightnesskey, brightness, ) except HomeConnectError as err: _LOGGER.error("Error while trying set the brightness: %s", err) @@ -76,11 +146,12 @@ async def async_turn_on(self, **kwargs): _LOGGER.debug("Tried to switch light on for: %s", self.name) try: await self.hass.async_add_executor_job( - self.device.appliance.set_setting, COOKING_LIGHTING, True, + self.device.appliance.set_setting, self._key, True, ) except HomeConnectError as err: _LOGGER.error("Error while trying to turn on light: %s", err) self._state = False + self.async_entity_update() async def async_turn_off(self, **kwargs): @@ -88,7 +159,7 @@ async def async_turn_off(self, **kwargs): _LOGGER.debug("tried to switch light off for: %s", self.name) try: await self.hass.async_add_executor_job( - self.device.appliance.set_setting, COOKING_LIGHTING, False, + self.device.appliance.set_setting, self._key, False, ) except HomeConnectError as err: _LOGGER.error("Error while trying to turn off light: %s", err) @@ -97,18 +168,33 @@ async def async_turn_off(self, **kwargs): async def async_update(self): """Update the light's status.""" - if self.device.appliance.status.get(COOKING_LIGHTING, {}).get("value") is True: + if self.device.appliance.status.get(self._key, {}).get("value") is True: self._state = True - elif ( - self.device.appliance.status.get(COOKING_LIGHTING, {}).get("value") is False - ): + elif self.device.appliance.status.get(self._key, {}).get("value") is False: self._state = False else: self._state = None - brightness = self.device.appliance.status.get(COOKING_LIGHTINGBRIGHTNESS, {}) - if brightness is None: - self._brightness = None - else: - self._brightness = ceil((brightness.get("value") - 10) * 255 / 90) + _LOGGER.debug("Updated, new light state: %s", self._state) - _LOGGER.debug("Updated, new brightness: %s", self._brightness) + + if self._ambient: + color = self.device.appliance.status.get(self._customcolorkey, {}) + + if not color: + self._hs_color = None + self._brightness = None + else: + colorvalue = color.get("value")[1:] + rgb = color_util.rgb_hex_to_rgb_list(colorvalue) + hsv = color_util.color_RGB_to_hsv(rgb[0], rgb[1], rgb[2]) + self._hs_color = [hsv[0], hsv[1]] + self._brightness = ceil((hsv[2] - 10) * 255 / 90) + _LOGGER.debug("Updated, new brightness: %s", self._brightness) + + else: + brightness = self.device.appliance.status.get(self._brightnesskey, {}) + if brightness is None: + self._brightness = None + else: + self._brightness = ceil((brightness.get("value") - 10) * 255 / 90) + _LOGGER.debug("Updated, new brightness: %s", self._brightness)