Use _attr_
for MQTT light (#81465)
* Schema basic * Schema json * Schema template * add color_mode - follow up comments * Fix regression * Follow up comments 2 * Fix mypy errors * Update homeassistant/components/mqtt/light/schema_template.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
parent
8c0a7b9d7f
commit
d66d079330
3 changed files with 195 additions and 387 deletions
|
@ -1,5 +1,6 @@
|
|||
"""Support for MQTT lights."""
|
||||
import logging
|
||||
from typing import cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -256,18 +257,6 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def __init__(self, hass, config, config_entry, discovery_data):
|
||||
"""Initialize MQTT light."""
|
||||
self._brightness = None
|
||||
self._color_mode = None
|
||||
self._color_temp = None
|
||||
self._effect = None
|
||||
self._hs_color = None
|
||||
self._rgb_color = None
|
||||
self._rgbw_color = None
|
||||
self._rgbww_color = None
|
||||
self._state = None
|
||||
self._supported_color_modes = None
|
||||
self._xy_color = None
|
||||
|
||||
self._topic = None
|
||||
self._payload = None
|
||||
self._command_templates = None
|
||||
|
@ -292,6 +281,10 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def _setup_from_config(self, config):
|
||||
"""(Re)Setup the entity."""
|
||||
self._attr_min_mireds = config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
self._attr_max_mireds = config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
self._attr_effect_list = config.get(CONF_EFFECT_LIST)
|
||||
|
||||
if CONF_STATE_VALUE_TEMPLATE not in config and CONF_VALUE_TEMPLATE in config:
|
||||
config[CONF_STATE_VALUE_TEMPLATE] = config[CONF_VALUE_TEMPLATE]
|
||||
|
||||
|
@ -378,39 +371,47 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
supported_color_modes = set()
|
||||
if topic[CONF_COLOR_TEMP_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.COLOR_TEMP)
|
||||
self._color_mode = ColorMode.COLOR_TEMP
|
||||
self._attr_color_mode = ColorMode.COLOR_TEMP
|
||||
if topic[CONF_HS_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.HS)
|
||||
self._color_mode = ColorMode.HS
|
||||
self._attr_color_mode = ColorMode.HS
|
||||
if topic[CONF_RGB_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.RGB)
|
||||
self._color_mode = ColorMode.RGB
|
||||
self._attr_color_mode = ColorMode.RGB
|
||||
if topic[CONF_RGBW_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.RGBW)
|
||||
self._color_mode = ColorMode.RGBW
|
||||
self._attr_color_mode = ColorMode.RGBW
|
||||
if topic[CONF_RGBWW_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.RGBWW)
|
||||
self._color_mode = ColorMode.RGBWW
|
||||
self._attr_color_mode = ColorMode.RGBWW
|
||||
if topic[CONF_WHITE_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.WHITE)
|
||||
if topic[CONF_XY_COMMAND_TOPIC] is not None:
|
||||
supported_color_modes.add(ColorMode.XY)
|
||||
self._color_mode = ColorMode.XY
|
||||
self._attr_color_mode = ColorMode.XY
|
||||
if len(supported_color_modes) > 1:
|
||||
self._color_mode = ColorMode.UNKNOWN
|
||||
self._attr_color_mode = ColorMode.UNKNOWN
|
||||
|
||||
if not supported_color_modes:
|
||||
if topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None:
|
||||
self._color_mode = ColorMode.BRIGHTNESS
|
||||
self._attr_color_mode = ColorMode.BRIGHTNESS
|
||||
supported_color_modes.add(ColorMode.BRIGHTNESS)
|
||||
else:
|
||||
self._color_mode = ColorMode.ONOFF
|
||||
self._attr_color_mode = ColorMode.ONOFF
|
||||
supported_color_modes.add(ColorMode.ONOFF)
|
||||
|
||||
# Validate the color_modes configuration
|
||||
self._supported_color_modes = valid_supported_color_modes(supported_color_modes)
|
||||
self._attr_supported_color_modes = valid_supported_color_modes(
|
||||
supported_color_modes
|
||||
)
|
||||
|
||||
def _is_optimistic(self, attribute):
|
||||
supported_features: int = 0
|
||||
supported_features |= (
|
||||
topic[CONF_EFFECT_COMMAND_TOPIC] is not None and LightEntityFeature.EFFECT
|
||||
)
|
||||
self._attr_supported_features = supported_features
|
||||
|
||||
def _is_optimistic(self, attribute: str) -> bool:
|
||||
"""Return True if the attribute is optimistically updated."""
|
||||
return getattr(self, f"_optimistic_{attribute}")
|
||||
|
||||
|
@ -438,11 +439,11 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
return
|
||||
|
||||
if payload == self._payload["on"]:
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
elif payload == self._payload["off"]:
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
elif payload == PAYLOAD_NONE:
|
||||
self._state = None
|
||||
self._attr_is_on = None
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
if self._topic[CONF_STATE_TOPIC] is not None:
|
||||
|
@ -466,7 +467,8 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
device_value = float(payload)
|
||||
percent_bright = device_value / self._config[CONF_BRIGHTNESS_SCALE]
|
||||
self._brightness = percent_bright * 255
|
||||
self._attr_brightness = min(round(percent_bright * 255), 255)
|
||||
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_BRIGHTNESS_STATE_TOPIC, brightness_received)
|
||||
|
@ -483,11 +485,11 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
return None
|
||||
color = tuple(int(val) for val in payload.split(","))
|
||||
if self._optimistic_color_mode:
|
||||
self._color_mode = color_mode
|
||||
self._attr_color_mode = color_mode
|
||||
if self._topic[CONF_BRIGHTNESS_STATE_TOPIC] is None:
|
||||
rgb = convert_color(*color)
|
||||
percent_bright = float(color_util.color_RGB_to_hsv(*rgb)[2]) / 100.0
|
||||
self._brightness = percent_bright * 255
|
||||
self._attr_brightness = min(round(percent_bright * 255), 255)
|
||||
return color
|
||||
|
||||
@callback
|
||||
|
@ -499,7 +501,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
)
|
||||
if not rgb:
|
||||
return
|
||||
self._rgb_color = rgb
|
||||
self._attr_rgb_color = rgb
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_RGB_STATE_TOPIC, rgb_received)
|
||||
|
@ -516,7 +518,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
)
|
||||
if not rgbw:
|
||||
return
|
||||
self._rgbw_color = rgbw
|
||||
self._attr_rgbw_color = rgbw
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_RGBW_STATE_TOPIC, rgbw_received)
|
||||
|
@ -533,7 +535,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
)
|
||||
if not rgbww:
|
||||
return
|
||||
self._rgbww_color = rgbww
|
||||
self._attr_rgbww_color = rgbww
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_RGBWW_STATE_TOPIC, rgbww_received)
|
||||
|
@ -549,7 +551,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
_LOGGER.debug("Ignoring empty color mode message from '%s'", msg.topic)
|
||||
return
|
||||
|
||||
self._color_mode = payload
|
||||
self._attr_color_mode = payload
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_COLOR_MODE_STATE_TOPIC, color_mode_received)
|
||||
|
@ -566,8 +568,8 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
return
|
||||
|
||||
if self._optimistic_color_mode:
|
||||
self._color_mode = ColorMode.COLOR_TEMP
|
||||
self._color_temp = int(payload)
|
||||
self._attr_color_mode = ColorMode.COLOR_TEMP
|
||||
self._attr_color_temp = int(payload)
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_COLOR_TEMP_STATE_TOPIC, color_temp_received)
|
||||
|
@ -583,7 +585,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
_LOGGER.debug("Ignoring empty effect message from '%s'", msg.topic)
|
||||
return
|
||||
|
||||
self._effect = payload
|
||||
self._attr_effect = payload
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_EFFECT_STATE_TOPIC, effect_received)
|
||||
|
@ -599,10 +601,13 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
_LOGGER.debug("Ignoring empty hs message from '%s'", msg.topic)
|
||||
return
|
||||
try:
|
||||
hs_color = tuple(float(val) for val in payload.split(",", 2))
|
||||
hs_color = cast(
|
||||
tuple[float, float],
|
||||
tuple(float(val) for val in payload.split(",", 2)),
|
||||
)
|
||||
if self._optimistic_color_mode:
|
||||
self._color_mode = ColorMode.HS
|
||||
self._hs_color = hs_color
|
||||
self._attr_color_mode = ColorMode.HS
|
||||
self._attr_hs_color = hs_color
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
except ValueError:
|
||||
_LOGGER.debug("Failed to parse hs state update: '%s'", payload)
|
||||
|
@ -620,10 +625,12 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
_LOGGER.debug("Ignoring empty xy-color message from '%s'", msg.topic)
|
||||
return
|
||||
|
||||
xy_color = tuple(float(val) for val in payload.split(","))
|
||||
xy_color = cast(
|
||||
tuple[float, float], tuple(float(val) for val in payload.split(",", 2))
|
||||
)
|
||||
if self._optimistic_color_mode:
|
||||
self._color_mode = ColorMode.XY
|
||||
self._xy_color = xy_color
|
||||
self._attr_color_mode = ColorMode.XY
|
||||
self._attr_xy_color = xy_color
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
add_topic(CONF_XY_STATE_TOPIC, xy_received)
|
||||
|
@ -643,10 +650,10 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
condition_attribute = attribute
|
||||
optimistic = self._is_optimistic(condition_attribute)
|
||||
if optimistic and last_state and last_state.attributes.get(attribute):
|
||||
setattr(self, f"_{attribute}", last_state.attributes[attribute])
|
||||
setattr(self, f"_attr_{attribute}", last_state.attributes[attribute])
|
||||
|
||||
if self._topic[CONF_STATE_TOPIC] is None and self._optimistic and last_state:
|
||||
self._state = last_state.state == STATE_ON
|
||||
self._attr_is_on = last_state.state == STATE_ON
|
||||
restore_state(ATTR_BRIGHTNESS)
|
||||
restore_state(ATTR_RGB_COLOR)
|
||||
restore_state(ATTR_HS_COLOR, ATTR_RGB_COLOR)
|
||||
|
@ -659,93 +666,11 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
restore_state(ATTR_XY_COLOR)
|
||||
restore_state(ATTR_HS_COLOR, ATTR_XY_COLOR)
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
if brightness := self._brightness:
|
||||
brightness = min(round(brightness), 255)
|
||||
return brightness
|
||||
|
||||
@property
|
||||
def color_mode(self):
|
||||
"""Return current color mode."""
|
||||
return self._color_mode
|
||||
|
||||
@property
|
||||
def hs_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._hs_color
|
||||
|
||||
@property
|
||||
def rgb_color(self):
|
||||
"""Return the rgb color value."""
|
||||
return self._rgb_color
|
||||
|
||||
@property
|
||||
def rgbw_color(self):
|
||||
"""Return the rgbw color value."""
|
||||
return self._rgbw_color
|
||||
|
||||
@property
|
||||
def rgbww_color(self):
|
||||
"""Return the rgbww color value."""
|
||||
return self._rgbww_color
|
||||
|
||||
@property
|
||||
def xy_color(self):
|
||||
"""Return the xy color value."""
|
||||
return self._xy_color
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Return the color temperature in mired."""
|
||||
return self._color_temp
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def assumed_state(self):
|
||||
"""Return true if we do optimistic updates."""
|
||||
return self._optimistic
|
||||
|
||||
@property
|
||||
def effect_list(self):
|
||||
"""Return the list of supported effects."""
|
||||
return self._config.get(CONF_EFFECT_LIST)
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
"""Return the current effect."""
|
||||
return self._effect
|
||||
|
||||
@property
|
||||
def supported_color_modes(self):
|
||||
"""Flag supported color modes."""
|
||||
return self._supported_color_modes
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
supported_features = 0
|
||||
supported_features |= (
|
||||
self._topic[CONF_EFFECT_COMMAND_TOPIC] is not None
|
||||
and LightEntityFeature.EFFECT
|
||||
)
|
||||
return supported_features
|
||||
|
||||
async def async_turn_on(self, **kwargs): # noqa: C901
|
||||
"""Turn the device on.
|
||||
|
||||
|
@ -772,9 +697,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
if self._topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None:
|
||||
brightness = 255
|
||||
else:
|
||||
brightness = kwargs.get(
|
||||
ATTR_BRIGHTNESS, self._brightness if self._brightness else 255
|
||||
)
|
||||
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255)
|
||||
return tuple(int(channel * brightness / 255) for channel in color)
|
||||
|
||||
def render_rgbx(color, template, color_mode):
|
||||
|
@ -797,8 +720,9 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
if not self._is_optimistic(condition_attribute):
|
||||
return False
|
||||
if color_mode and self._optimistic_color_mode:
|
||||
self._color_mode = color_mode
|
||||
setattr(self, f"_{attribute}", value)
|
||||
self._attr_color_mode = color_mode
|
||||
|
||||
setattr(self, f"_attr_{attribute}", value)
|
||||
return True
|
||||
|
||||
if on_command_type == "first":
|
||||
|
@ -813,7 +737,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
and ATTR_BRIGHTNESS not in kwargs
|
||||
and ATTR_WHITE not in kwargs
|
||||
):
|
||||
kwargs[ATTR_BRIGHTNESS] = self._brightness if self._brightness else 255
|
||||
kwargs[ATTR_BRIGHTNESS] = self.brightness or 255
|
||||
|
||||
hs_color = kwargs.get(ATTR_HS_COLOR)
|
||||
|
||||
|
@ -871,7 +795,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
and ATTR_RGB_COLOR not in kwargs
|
||||
and self._topic[CONF_RGB_COMMAND_TOPIC] is not None
|
||||
):
|
||||
rgb_color = self._rgb_color if self._rgb_color is not None else (255,) * 3
|
||||
rgb_color = self.rgb_color or (255,) * 3
|
||||
rgb = scale_rgbx(rgb_color, kwargs[ATTR_BRIGHTNESS])
|
||||
rgb_s = render_rgbx(rgb, CONF_RGB_COMMAND_TEMPLATE, ColorMode.RGB)
|
||||
await publish(CONF_RGB_COMMAND_TOPIC, rgb_s)
|
||||
|
@ -881,9 +805,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
and ATTR_RGBW_COLOR not in kwargs
|
||||
and self._topic[CONF_RGBW_COMMAND_TOPIC] is not None
|
||||
):
|
||||
rgbw_color = (
|
||||
self._rgbw_color if self._rgbw_color is not None else (255,) * 4
|
||||
)
|
||||
rgbw_color = self.rgbw_color or (255,) * 4
|
||||
rgbw = scale_rgbx(rgbw_color, kwargs[ATTR_BRIGHTNESS])
|
||||
rgbw_s = render_rgbx(rgbw, CONF_RGBW_COMMAND_TEMPLATE, ColorMode.RGBW)
|
||||
await publish(CONF_RGBW_COMMAND_TOPIC, rgbw_s)
|
||||
|
@ -893,9 +815,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
and ATTR_RGBWW_COLOR not in kwargs
|
||||
and self._topic[CONF_RGBWW_COMMAND_TOPIC] is not None
|
||||
):
|
||||
rgbww_color = (
|
||||
self._rgbww_color if self._rgbww_color is not None else (255,) * 5
|
||||
)
|
||||
rgbww_color = self.rgbww_color or (255,) * 5
|
||||
rgbww = scale_rgbx(rgbww_color, kwargs[ATTR_BRIGHTNESS])
|
||||
rgbww_s = render_rgbx(rgbww, CONF_RGBWW_COMMAND_TEMPLATE, ColorMode.RGBWW)
|
||||
await publish(CONF_RGBWW_COMMAND_TOPIC, rgbww_s)
|
||||
|
@ -938,7 +858,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
if self._optimistic:
|
||||
# Optimistically assume that the light has changed state.
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
should_update = True
|
||||
|
||||
if should_update:
|
||||
|
@ -959,5 +879,5 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
if self._optimistic:
|
||||
# Optimistically assume that the light has changed state.
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
self.async_write_ha_state()
|
||||
|
|
|
@ -188,22 +188,10 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def __init__(self, hass, config, config_entry, discovery_data):
|
||||
"""Initialize MQTT JSON light."""
|
||||
self._state = None
|
||||
self._supported_features = 0
|
||||
|
||||
self._topic = None
|
||||
self._optimistic = False
|
||||
self._brightness = None
|
||||
self._color_mode = None
|
||||
self._color_temp = None
|
||||
self._effect = None
|
||||
self._fixed_color_mode = None
|
||||
self._flash_times = None
|
||||
self._hs = None
|
||||
self._rgb = None
|
||||
self._rgbw = None
|
||||
self._rgbww = None
|
||||
self._xy = None
|
||||
|
||||
MqttEntity.__init__(self, hass, config, config_entry, discovery_data)
|
||||
|
||||
|
@ -214,6 +202,10 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def _setup_from_config(self, config):
|
||||
"""(Re)Setup the entity."""
|
||||
self._attr_max_mireds = config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
self._attr_min_mireds = config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
self._attr_effect_list = config.get(CONF_EFFECT_LIST)
|
||||
|
||||
self._topic = {
|
||||
key: config.get(key) for key in (CONF_STATE_TOPIC, CONF_COMMAND_TOPIC)
|
||||
}
|
||||
|
@ -225,10 +217,12 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
for key in (CONF_FLASH_TIME_SHORT, CONF_FLASH_TIME_LONG)
|
||||
}
|
||||
|
||||
self._supported_features = (
|
||||
self._attr_supported_features = (
|
||||
LightEntityFeature.TRANSITION | LightEntityFeature.FLASH
|
||||
)
|
||||
self._supported_features |= config[CONF_EFFECT] and LightEntityFeature.EFFECT
|
||||
self._attr_supported_features |= (
|
||||
config[CONF_EFFECT] and LightEntityFeature.EFFECT
|
||||
)
|
||||
if not self._config[CONF_COLOR_MODE]:
|
||||
color_modes = {ColorMode.ONOFF}
|
||||
if config[CONF_BRIGHTNESS]:
|
||||
|
@ -237,13 +231,13 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
color_modes.add(ColorMode.COLOR_TEMP)
|
||||
if config[CONF_HS] or config[CONF_RGB] or config[CONF_XY]:
|
||||
color_modes.add(ColorMode.HS)
|
||||
self._supported_color_modes = filter_supported_color_modes(color_modes)
|
||||
if len(self._supported_color_modes) == 1:
|
||||
self._fixed_color_mode = next(iter(self._supported_color_modes))
|
||||
self._attr_supported_color_modes = filter_supported_color_modes(color_modes)
|
||||
if len(self.supported_color_modes) == 1:
|
||||
self._fixed_color_mode = next(iter(self.supported_color_modes))
|
||||
else:
|
||||
self._supported_color_modes = self._config[CONF_SUPPORTED_COLOR_MODES]
|
||||
if len(self._supported_color_modes) == 1:
|
||||
self._color_mode = next(iter(self._supported_color_modes))
|
||||
self._attr_supported_color_modes = self._config[CONF_SUPPORTED_COLOR_MODES]
|
||||
if len(self.supported_color_modes) == 1:
|
||||
self._attr_color_mode = next(iter(self.supported_color_modes))
|
||||
|
||||
def _update_color(self, values):
|
||||
if not self._config[CONF_COLOR_MODE]:
|
||||
|
@ -252,7 +246,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
red = int(values["color"]["r"])
|
||||
green = int(values["color"]["g"])
|
||||
blue = int(values["color"]["b"])
|
||||
self._hs = color_util.color_RGB_to_hs(red, green, blue)
|
||||
self._attr_hs_color = color_util.color_RGB_to_hs(red, green, blue)
|
||||
except KeyError:
|
||||
pass
|
||||
except ValueError:
|
||||
|
@ -264,7 +258,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
try:
|
||||
x_color = float(values["color"]["x"])
|
||||
y_color = float(values["color"]["y"])
|
||||
self._hs = color_util.color_xy_to_hs(x_color, y_color)
|
||||
self._attr_hs_color = color_util.color_xy_to_hs(x_color, y_color)
|
||||
except KeyError:
|
||||
pass
|
||||
except ValueError:
|
||||
|
@ -276,7 +270,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
try:
|
||||
hue = float(values["color"]["h"])
|
||||
saturation = float(values["color"]["s"])
|
||||
self._hs = (hue, saturation)
|
||||
self._attr_hs_color = (hue, saturation)
|
||||
except KeyError:
|
||||
pass
|
||||
except ValueError:
|
||||
|
@ -293,41 +287,41 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
return
|
||||
try:
|
||||
if color_mode == ColorMode.COLOR_TEMP:
|
||||
self._color_temp = int(values["color_temp"])
|
||||
self._color_mode = ColorMode.COLOR_TEMP
|
||||
self._attr_color_temp = int(values["color_temp"])
|
||||
self._attr_color_mode = ColorMode.COLOR_TEMP
|
||||
elif color_mode == ColorMode.HS:
|
||||
hue = float(values["color"]["h"])
|
||||
saturation = float(values["color"]["s"])
|
||||
self._color_mode = ColorMode.HS
|
||||
self._hs = (hue, saturation)
|
||||
self._attr_color_mode = ColorMode.HS
|
||||
self._attr_hs_color = (hue, saturation)
|
||||
elif color_mode == ColorMode.RGB:
|
||||
r = int(values["color"]["r"]) # pylint: disable=invalid-name
|
||||
g = int(values["color"]["g"]) # pylint: disable=invalid-name
|
||||
b = int(values["color"]["b"]) # pylint: disable=invalid-name
|
||||
self._color_mode = ColorMode.RGB
|
||||
self._rgb = (r, g, b)
|
||||
self._attr_color_mode = ColorMode.RGB
|
||||
self._attr_rgb_color = (r, g, b)
|
||||
elif color_mode == ColorMode.RGBW:
|
||||
r = int(values["color"]["r"]) # pylint: disable=invalid-name
|
||||
g = int(values["color"]["g"]) # pylint: disable=invalid-name
|
||||
b = int(values["color"]["b"]) # pylint: disable=invalid-name
|
||||
w = int(values["color"]["w"]) # pylint: disable=invalid-name
|
||||
self._color_mode = ColorMode.RGBW
|
||||
self._rgbw = (r, g, b, w)
|
||||
self._attr_color_mode = ColorMode.RGBW
|
||||
self._attr_rgbw_color = (r, g, b, w)
|
||||
elif color_mode == ColorMode.RGBWW:
|
||||
r = int(values["color"]["r"]) # pylint: disable=invalid-name
|
||||
g = int(values["color"]["g"]) # pylint: disable=invalid-name
|
||||
b = int(values["color"]["b"]) # pylint: disable=invalid-name
|
||||
c = int(values["color"]["c"]) # pylint: disable=invalid-name
|
||||
w = int(values["color"]["w"]) # pylint: disable=invalid-name
|
||||
self._color_mode = ColorMode.RGBWW
|
||||
self._rgbww = (r, g, b, c, w)
|
||||
self._attr_color_mode = ColorMode.RGBWW
|
||||
self._attr_rgbww_color = (r, g, b, c, w)
|
||||
elif color_mode == ColorMode.WHITE:
|
||||
self._color_mode = ColorMode.WHITE
|
||||
self._attr_color_mode = ColorMode.WHITE
|
||||
elif color_mode == ColorMode.XY:
|
||||
x = float(values["color"]["x"]) # pylint: disable=invalid-name
|
||||
y = float(values["color"]["y"]) # pylint: disable=invalid-name
|
||||
self._color_mode = ColorMode.XY
|
||||
self._xy = (x, y)
|
||||
self._attr_color_mode = ColorMode.XY
|
||||
self._attr_xy_color = (x, y)
|
||||
except (KeyError, ValueError):
|
||||
_LOGGER.warning(
|
||||
"Invalid or incomplete color value received for entity %s",
|
||||
|
@ -344,29 +338,29 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
values = json_loads(msg.payload)
|
||||
|
||||
if values["state"] == "ON":
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
elif values["state"] == "OFF":
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
elif values["state"] is None:
|
||||
self._state = None
|
||||
self._attr_is_on = None
|
||||
|
||||
if (
|
||||
not self._config[CONF_COLOR_MODE]
|
||||
and color_supported(self._supported_color_modes)
|
||||
and color_supported(self.supported_color_modes)
|
||||
and "color" in values
|
||||
):
|
||||
# Deprecated color handling
|
||||
if values["color"] is None:
|
||||
self._hs = None
|
||||
self._attr_hs_color = None
|
||||
else:
|
||||
self._update_color(values)
|
||||
|
||||
if self._config[CONF_COLOR_MODE] and "color_mode" in values:
|
||||
self._update_color(values)
|
||||
|
||||
if brightness_supported(self._supported_color_modes):
|
||||
if brightness_supported(self.supported_color_modes):
|
||||
try:
|
||||
self._brightness = int(
|
||||
self._attr_brightness = int(
|
||||
values["brightness"]
|
||||
/ float(self._config[CONF_BRIGHTNESS_SCALE])
|
||||
* 255
|
||||
|
@ -380,15 +374,15 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
)
|
||||
|
||||
if (
|
||||
ColorMode.COLOR_TEMP in self._supported_color_modes
|
||||
ColorMode.COLOR_TEMP in self.supported_color_modes
|
||||
and not self._config[CONF_COLOR_MODE]
|
||||
):
|
||||
# Deprecated color handling
|
||||
try:
|
||||
if values["color_temp"] is None:
|
||||
self._color_temp = None
|
||||
self._attr_color_temp = None
|
||||
else:
|
||||
self._color_temp = int(values["color_temp"])
|
||||
self._attr_color_temp = int(values["color_temp"])
|
||||
except KeyError:
|
||||
pass
|
||||
except ValueError:
|
||||
|
@ -397,9 +391,9 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
self.entity_id,
|
||||
)
|
||||
|
||||
if self._supported_features and LightEntityFeature.EFFECT:
|
||||
if self.supported_features and LightEntityFeature.EFFECT:
|
||||
with suppress(KeyError):
|
||||
self._effect = values["effect"]
|
||||
self._attr_effect = values["effect"]
|
||||
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
|
||||
|
@ -423,77 +417,27 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
last_state = await self.async_get_last_state()
|
||||
if self._optimistic and last_state:
|
||||
self._state = last_state.state == STATE_ON
|
||||
self._attr_is_on = last_state.state == STATE_ON
|
||||
last_attributes = last_state.attributes
|
||||
self._brightness = last_attributes.get(ATTR_BRIGHTNESS, self._brightness)
|
||||
self._color_mode = last_attributes.get(ATTR_COLOR_MODE, self._color_mode)
|
||||
self._color_temp = last_attributes.get(ATTR_COLOR_TEMP, self._color_temp)
|
||||
self._effect = last_attributes.get(ATTR_EFFECT, self._effect)
|
||||
self._hs = last_attributes.get(ATTR_HS_COLOR, self._hs)
|
||||
self._rgb = last_attributes.get(ATTR_RGB_COLOR, self._rgb)
|
||||
self._rgbw = last_attributes.get(ATTR_RGBW_COLOR, self._rgbw)
|
||||
self._rgbww = last_attributes.get(ATTR_RGBWW_COLOR, self._rgbww)
|
||||
self._xy = last_attributes.get(ATTR_XY_COLOR, self._xy)
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
return self._brightness
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Return the color temperature in mired."""
|
||||
return self._color_temp
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
"""Return the current effect."""
|
||||
return self._effect
|
||||
|
||||
@property
|
||||
def effect_list(self):
|
||||
"""Return the list of supported effects."""
|
||||
return self._config.get(CONF_EFFECT_LIST)
|
||||
|
||||
@property
|
||||
def hs_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._hs
|
||||
|
||||
@property
|
||||
def rgb_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._rgb
|
||||
|
||||
@property
|
||||
def rgbw_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._rgbw
|
||||
|
||||
@property
|
||||
def rgbww_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._rgbww
|
||||
|
||||
@property
|
||||
def xy_color(self):
|
||||
"""Return the hs color value."""
|
||||
return self._xy
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on."""
|
||||
return self._state
|
||||
self._attr_brightness = last_attributes.get(
|
||||
ATTR_BRIGHTNESS, self.brightness
|
||||
)
|
||||
self._attr_color_mode = last_attributes.get(
|
||||
ATTR_COLOR_MODE, self.color_mode
|
||||
)
|
||||
self._attr_color_temp = last_attributes.get(
|
||||
ATTR_COLOR_TEMP, self.color_temp
|
||||
)
|
||||
self._attr_effect = last_attributes.get(ATTR_EFFECT, self.effect)
|
||||
self._attr_hs_color = last_attributes.get(ATTR_HS_COLOR, self.hs_color)
|
||||
self._attr_rgb_color = last_attributes.get(ATTR_RGB_COLOR, self.rgb_color)
|
||||
self._attr_rgbw_color = last_attributes.get(
|
||||
ATTR_RGBW_COLOR, self.rgbw_color
|
||||
)
|
||||
self._attr_rgbww_color = last_attributes.get(
|
||||
ATTR_RGBWW_COLOR, self.rgbww_color
|
||||
)
|
||||
self._attr_xy_color = last_attributes.get(ATTR_XY_COLOR, self.xy_color)
|
||||
|
||||
@property
|
||||
def assumed_state(self):
|
||||
|
@ -504,25 +448,15 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
def color_mode(self):
|
||||
"""Return current color mode."""
|
||||
if self._config[CONF_COLOR_MODE]:
|
||||
return self._color_mode
|
||||
return self._attr_color_mode
|
||||
if self._fixed_color_mode:
|
||||
# Legacy light with support for a single color mode
|
||||
return self._fixed_color_mode
|
||||
# Legacy light with support for ct + hs, prioritize hs
|
||||
if self._hs is not None:
|
||||
if self.hs_color is not None:
|
||||
return ColorMode.HS
|
||||
return ColorMode.COLOR_TEMP
|
||||
|
||||
@property
|
||||
def supported_color_modes(self):
|
||||
"""Flag supported color modes."""
|
||||
return self._supported_color_modes
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return self._supported_features
|
||||
|
||||
def _set_flash_and_transition(self, message, **kwargs):
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
message["transition"] = kwargs[ATTR_TRANSITION]
|
||||
|
@ -587,32 +521,32 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
message["color"]["s"] = hs_color[1]
|
||||
|
||||
if self._optimistic:
|
||||
self._color_temp = None
|
||||
self._hs = kwargs[ATTR_HS_COLOR]
|
||||
self._attr_color_temp = None
|
||||
self._attr_hs_color = kwargs[ATTR_HS_COLOR]
|
||||
should_update = True
|
||||
|
||||
if ATTR_HS_COLOR in kwargs and self._supports_color_mode(ColorMode.HS):
|
||||
hs_color = kwargs[ATTR_HS_COLOR]
|
||||
message["color"] = {"h": hs_color[0], "s": hs_color[1]}
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.HS
|
||||
self._hs = hs_color
|
||||
self._attr_color_mode = ColorMode.HS
|
||||
self._attr_hs_color = hs_color
|
||||
should_update = True
|
||||
|
||||
if ATTR_RGB_COLOR in kwargs and self._supports_color_mode(ColorMode.RGB):
|
||||
rgb = self._scale_rgbxx(kwargs[ATTR_RGB_COLOR], kwargs)
|
||||
message["color"] = {"r": rgb[0], "g": rgb[1], "b": rgb[2]}
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.RGB
|
||||
self._rgb = rgb
|
||||
self._attr_color_mode = ColorMode.RGB
|
||||
self._attr_rgb_color = rgb
|
||||
should_update = True
|
||||
|
||||
if ATTR_RGBW_COLOR in kwargs and self._supports_color_mode(ColorMode.RGBW):
|
||||
rgb = self._scale_rgbxx(kwargs[ATTR_RGBW_COLOR], kwargs)
|
||||
message["color"] = {"r": rgb[0], "g": rgb[1], "b": rgb[2], "w": rgb[3]}
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.RGBW
|
||||
self._rgbw = rgb
|
||||
self._attr_color_mode = ColorMode.RGBW
|
||||
self._attr_rgbw_color = rgb
|
||||
should_update = True
|
||||
|
||||
if ATTR_RGBWW_COLOR in kwargs and self._supports_color_mode(ColorMode.RGBWW):
|
||||
|
@ -625,16 +559,16 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
"w": rgb[4],
|
||||
}
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.RGBWW
|
||||
self._rgbww = rgb
|
||||
self._attr_color_mode = ColorMode.RGBWW
|
||||
self._attr_rgbww_color = rgb
|
||||
should_update = True
|
||||
|
||||
if ATTR_XY_COLOR in kwargs and self._supports_color_mode(ColorMode.XY):
|
||||
xy = kwargs[ATTR_XY_COLOR] # pylint: disable=invalid-name
|
||||
message["color"] = {"x": xy[0], "y": xy[1]}
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.XY
|
||||
self._xy = xy
|
||||
self._attr_color_mode = ColorMode.XY
|
||||
self._attr_xy_color = xy
|
||||
should_update = True
|
||||
|
||||
self._set_flash_and_transition(message, **kwargs)
|
||||
|
@ -650,23 +584,23 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
message["brightness"] = device_brightness
|
||||
|
||||
if self._optimistic:
|
||||
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
self._attr_brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
should_update = True
|
||||
|
||||
if ATTR_COLOR_TEMP in kwargs:
|
||||
message["color_temp"] = int(kwargs[ATTR_COLOR_TEMP])
|
||||
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.COLOR_TEMP
|
||||
self._color_temp = kwargs[ATTR_COLOR_TEMP]
|
||||
self._hs = None
|
||||
self._attr_color_mode = ColorMode.COLOR_TEMP
|
||||
self._attr_color_temp = kwargs[ATTR_COLOR_TEMP]
|
||||
self._attr_hs_color = None
|
||||
should_update = True
|
||||
|
||||
if ATTR_EFFECT in kwargs:
|
||||
message["effect"] = kwargs[ATTR_EFFECT]
|
||||
|
||||
if self._optimistic:
|
||||
self._effect = kwargs[ATTR_EFFECT]
|
||||
self._attr_effect = kwargs[ATTR_EFFECT]
|
||||
should_update = True
|
||||
|
||||
if ATTR_WHITE in kwargs and self._supports_color_mode(ColorMode.WHITE):
|
||||
|
@ -678,8 +612,8 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
message["white"] = device_white_level
|
||||
|
||||
if self._optimistic:
|
||||
self._color_mode = ColorMode.WHITE
|
||||
self._brightness = kwargs[ATTR_WHITE]
|
||||
self._attr_color_mode = ColorMode.WHITE
|
||||
self._attr_brightness = kwargs[ATTR_WHITE]
|
||||
should_update = True
|
||||
|
||||
await self.async_publish(
|
||||
|
@ -692,7 +626,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
if self._optimistic:
|
||||
# Optimistically assume that the light has changed state.
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
should_update = True
|
||||
|
||||
if should_update:
|
||||
|
@ -717,5 +651,5 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
if self._optimistic:
|
||||
# Optimistically assume that the light has changed state.
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
self.async_write_ha_state()
|
||||
|
|
|
@ -121,18 +121,12 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def __init__(self, hass, config, config_entry, discovery_data):
|
||||
"""Initialize a MQTT Template light."""
|
||||
self._state = None
|
||||
|
||||
self._topics = None
|
||||
self._templates = None
|
||||
self._optimistic = False
|
||||
|
||||
# features
|
||||
self._brightness = None
|
||||
self._fixed_color_mode = None
|
||||
self._color_temp = None
|
||||
self._hs = None
|
||||
self._effect = None
|
||||
|
||||
MqttEntity.__init__(self, hass, config, config_entry, discovery_data)
|
||||
|
||||
|
@ -143,6 +137,10 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
def _setup_from_config(self, config):
|
||||
"""(Re)Setup the entity."""
|
||||
self._attr_max_mireds = config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
self._attr_min_mireds = config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
self._attr_effect_list = config.get(CONF_EFFECT_LIST)
|
||||
|
||||
self._topics = {
|
||||
key: config.get(key) for key in (CONF_STATE_TOPIC, CONF_COMMAND_TOPIC)
|
||||
}
|
||||
|
@ -178,9 +176,23 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
and self._templates[CONF_BLUE_TEMPLATE] is not None
|
||||
):
|
||||
color_modes.add(ColorMode.HS)
|
||||
self._supported_color_modes = filter_supported_color_modes(color_modes)
|
||||
if len(self._supported_color_modes) == 1:
|
||||
self._fixed_color_mode = next(iter(self._supported_color_modes))
|
||||
self._attr_supported_color_modes = filter_supported_color_modes(color_modes)
|
||||
self._fixed_color_mode = None
|
||||
if len(self.supported_color_modes) == 1:
|
||||
self._fixed_color_mode = next(iter(self.supported_color_modes))
|
||||
self._attr_color_mode = self._fixed_color_mode
|
||||
|
||||
features = LightEntityFeature.FLASH | LightEntityFeature.TRANSITION
|
||||
if config.get(CONF_EFFECT_LIST) is not None:
|
||||
features = features | LightEntityFeature.EFFECT
|
||||
self._attr_supported_features = features
|
||||
|
||||
def _update_color_mode(self):
|
||||
"""Update the color_mode attribute."""
|
||||
if self._fixed_color_mode:
|
||||
return
|
||||
# Support for ct + hs, prioritize hs
|
||||
self._attr_color_mode = ColorMode.HS if self.hs_color else ColorMode.COLOR_TEMP
|
||||
|
||||
def _prepare_subscribe_topics(self):
|
||||
"""(Re)Subscribe to topics."""
|
||||
|
@ -196,17 +208,17 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
CONF_STATE_TEMPLATE
|
||||
].async_render_with_possible_json_value(msg.payload)
|
||||
if state == STATE_ON:
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
elif state == STATE_OFF:
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
elif state == PAYLOAD_NONE:
|
||||
self._state = None
|
||||
self._attr_is_on = None
|
||||
else:
|
||||
_LOGGER.warning("Invalid state value received")
|
||||
|
||||
if self._templates[CONF_BRIGHTNESS_TEMPLATE] is not None:
|
||||
try:
|
||||
self._brightness = int(
|
||||
self._attr_brightness = int(
|
||||
self._templates[
|
||||
CONF_BRIGHTNESS_TEMPLATE
|
||||
].async_render_with_possible_json_value(msg.payload)
|
||||
|
@ -219,7 +231,9 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
color_temp = self._templates[
|
||||
CONF_COLOR_TEMP_TEMPLATE
|
||||
].async_render_with_possible_json_value(msg.payload)
|
||||
self._color_temp = int(color_temp) if color_temp != "None" else None
|
||||
self._attr_color_temp = (
|
||||
int(color_temp) if color_temp != "None" else None
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.warning("Invalid color temperature value received")
|
||||
|
||||
|
@ -239,11 +253,12 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
CONF_BLUE_TEMPLATE
|
||||
].async_render_with_possible_json_value(msg.payload)
|
||||
if red == "None" and green == "None" and blue == "None":
|
||||
self._hs = None
|
||||
self._attr_hs_color = None
|
||||
else:
|
||||
self._hs = color_util.color_RGB_to_hs(
|
||||
self._attr_hs_color = color_util.color_RGB_to_hs(
|
||||
int(red), int(green), int(blue)
|
||||
)
|
||||
self._update_color_mode()
|
||||
except ValueError:
|
||||
_LOGGER.warning("Invalid color value received")
|
||||
|
||||
|
@ -253,7 +268,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
].async_render_with_possible_json_value(msg.payload)
|
||||
|
||||
if effect in self._config.get(CONF_EFFECT_LIST):
|
||||
self._effect = effect
|
||||
self._attr_effect = effect
|
||||
else:
|
||||
_LOGGER.warning("Unsupported effect value received")
|
||||
|
||||
|
@ -279,61 +294,22 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
last_state = await self.async_get_last_state()
|
||||
if self._optimistic and last_state:
|
||||
self._state = last_state.state == STATE_ON
|
||||
self._attr_is_on = last_state.state == STATE_ON
|
||||
if last_state.attributes.get(ATTR_BRIGHTNESS):
|
||||
self._brightness = last_state.attributes.get(ATTR_BRIGHTNESS)
|
||||
self._attr_brightness = last_state.attributes.get(ATTR_BRIGHTNESS)
|
||||
if last_state.attributes.get(ATTR_HS_COLOR):
|
||||
self._hs = last_state.attributes.get(ATTR_HS_COLOR)
|
||||
self._attr_hs_color = last_state.attributes.get(ATTR_HS_COLOR)
|
||||
self._update_color_mode()
|
||||
if last_state.attributes.get(ATTR_COLOR_TEMP):
|
||||
self._color_temp = last_state.attributes.get(ATTR_COLOR_TEMP)
|
||||
self._attr_color_temp = last_state.attributes.get(ATTR_COLOR_TEMP)
|
||||
if last_state.attributes.get(ATTR_EFFECT):
|
||||
self._effect = last_state.attributes.get(ATTR_EFFECT)
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
return self._brightness
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Return the color temperature in mired."""
|
||||
return self._color_temp
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MIN_MIREDS, super().min_mireds)
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
return self._config.get(CONF_MAX_MIREDS, super().max_mireds)
|
||||
|
||||
@property
|
||||
def hs_color(self):
|
||||
"""Return the hs color value [int, int]."""
|
||||
return self._hs
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if entity is on."""
|
||||
return self._state
|
||||
self._attr_effect = last_state.attributes.get(ATTR_EFFECT)
|
||||
|
||||
@property
|
||||
def assumed_state(self):
|
||||
"""Return True if unable to access real state of the entity."""
|
||||
return self._optimistic
|
||||
|
||||
@property
|
||||
def effect_list(self):
|
||||
"""Return the list of supported effects."""
|
||||
return self._config.get(CONF_EFFECT_LIST)
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
"""Return the current effect."""
|
||||
return self._effect
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the entity on.
|
||||
|
||||
|
@ -341,20 +317,21 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
"""
|
||||
values = {"state": True}
|
||||
if self._optimistic:
|
||||
self._state = True
|
||||
self._attr_is_on = True
|
||||
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
values["brightness"] = int(kwargs[ATTR_BRIGHTNESS])
|
||||
|
||||
if self._optimistic:
|
||||
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
self._attr_brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
|
||||
if ATTR_COLOR_TEMP in kwargs:
|
||||
values["color_temp"] = int(kwargs[ATTR_COLOR_TEMP])
|
||||
|
||||
if self._optimistic:
|
||||
self._color_temp = kwargs[ATTR_COLOR_TEMP]
|
||||
self._hs = None
|
||||
self._attr_color_temp = kwargs[ATTR_COLOR_TEMP]
|
||||
self._attr_hs_color = None
|
||||
self._update_color_mode()
|
||||
|
||||
if ATTR_HS_COLOR in kwargs:
|
||||
hs_color = kwargs[ATTR_HS_COLOR]
|
||||
|
@ -366,7 +343,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
else:
|
||||
brightness = kwargs.get(
|
||||
ATTR_BRIGHTNESS,
|
||||
self._brightness if self._brightness is not None else 255,
|
||||
self._attr_brightness if self._attr_brightness is not None else 255,
|
||||
)
|
||||
rgb = color_util.color_hsv_to_RGB(
|
||||
hs_color[0], hs_color[1], brightness / 255 * 100
|
||||
|
@ -378,14 +355,15 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
values["sat"] = hs_color[1]
|
||||
|
||||
if self._optimistic:
|
||||
self._color_temp = None
|
||||
self._hs = kwargs[ATTR_HS_COLOR]
|
||||
self._attr_color_temp = None
|
||||
self._attr_hs_color = kwargs[ATTR_HS_COLOR]
|
||||
self._update_color_mode()
|
||||
|
||||
if ATTR_EFFECT in kwargs:
|
||||
values["effect"] = kwargs.get(ATTR_EFFECT)
|
||||
|
||||
if self._optimistic:
|
||||
self._effect = kwargs[ATTR_EFFECT]
|
||||
self._attr_effect = kwargs[ATTR_EFFECT]
|
||||
|
||||
if ATTR_FLASH in kwargs:
|
||||
values["flash"] = kwargs.get(ATTR_FLASH)
|
||||
|
@ -413,7 +391,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
"""
|
||||
values = {"state": False}
|
||||
if self._optimistic:
|
||||
self._state = False
|
||||
self._attr_is_on = False
|
||||
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
values["transition"] = kwargs[ATTR_TRANSITION]
|
||||
|
@ -430,27 +408,3 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
|||
|
||||
if self._optimistic:
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def color_mode(self):
|
||||
"""Return current color mode."""
|
||||
if self._fixed_color_mode:
|
||||
return self._fixed_color_mode
|
||||
# Support for ct + hs, prioritize hs
|
||||
if self._hs is not None:
|
||||
return ColorMode.HS
|
||||
return ColorMode.COLOR_TEMP
|
||||
|
||||
@property
|
||||
def supported_color_modes(self):
|
||||
"""Flag supported color modes."""
|
||||
return self._supported_color_modes
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
features = LightEntityFeature.FLASH | LightEntityFeature.TRANSITION
|
||||
if self._config.get(CONF_EFFECT_LIST) is not None:
|
||||
features = features | LightEntityFeature.EFFECT
|
||||
|
||||
return features
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue