Align MQTT light's default color temperature (#41842)

pull/42167/head
Erik Montnemery 2020-10-21 15:46:29 +02:00 committed by GitHub
parent a07c0d1605
commit e203896638
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 277 deletions

View File

@ -348,17 +348,12 @@ class MqttLight(
"msg_callback": brightness_received,
"qos": self._config[CONF_QOS],
}
self._brightness = 255
elif (
self._optimistic_brightness
and last_state
and last_state.attributes.get(ATTR_BRIGHTNESS)
):
self._brightness = last_state.attributes.get(ATTR_BRIGHTNESS)
elif self._topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None:
self._brightness = 255
else:
self._brightness = None
@callback
@log_messages(self.hass, self.entity_id)
@ -382,15 +377,12 @@ class MqttLight(
"msg_callback": rgb_received,
"qos": self._config[CONF_QOS],
}
self._hs = (0, 0)
if (
self._optimistic_rgb
and last_state
and last_state.attributes.get(ATTR_HS_COLOR)
):
self._hs = last_state.attributes.get(ATTR_HS_COLOR)
elif self._topic[CONF_RGB_COMMAND_TOPIC] is not None:
self._hs = (0, 0)
@callback
@log_messages(self.hass, self.entity_id)
@ -412,17 +404,12 @@ class MqttLight(
"msg_callback": color_temp_received,
"qos": self._config[CONF_QOS],
}
self._color_temp = 150
if (
self._optimistic_color_temp
and last_state
and last_state.attributes.get(ATTR_COLOR_TEMP)
):
self._color_temp = last_state.attributes.get(ATTR_COLOR_TEMP)
elif self._topic[CONF_COLOR_TEMP_COMMAND_TOPIC] is not None:
self._color_temp = 150
else:
self._color_temp = None
@callback
@log_messages(self.hass, self.entity_id)
@ -444,17 +431,12 @@ class MqttLight(
"msg_callback": effect_received,
"qos": self._config[CONF_QOS],
}
self._effect = "none"
if (
self._optimistic_effect
and last_state
and last_state.attributes.get(ATTR_EFFECT)
):
self._effect = last_state.attributes.get(ATTR_EFFECT)
elif self._topic[CONF_EFFECT_COMMAND_TOPIC] is not None:
self._effect = "none"
else:
self._effect = None
@callback
@log_messages(self.hass, self.entity_id)
@ -478,15 +460,12 @@ class MqttLight(
"msg_callback": hs_received,
"qos": self._config[CONF_QOS],
}
self._hs = (0, 0)
if (
self._optimistic_hs
and last_state
and last_state.attributes.get(ATTR_HS_COLOR)
):
self._hs = last_state.attributes.get(ATTR_HS_COLOR)
elif self._topic[CONF_HS_COMMAND_TOPIC] is not None:
self._hs = (0, 0)
@callback
@log_messages(self.hass, self.entity_id)
@ -510,17 +489,12 @@ class MqttLight(
"msg_callback": white_value_received,
"qos": self._config[CONF_QOS],
}
self._white_value = 255
elif (
self._optimistic_white_value
and last_state
and last_state.attributes.get(ATTR_WHITE_VALUE)
):
self._white_value = last_state.attributes.get(ATTR_WHITE_VALUE)
elif self._topic[CONF_WHITE_VALUE_COMMAND_TOPIC] is not None:
self._white_value = 255
else:
self._white_value = None
@callback
@log_messages(self.hass, self.entity_id)
@ -541,15 +515,12 @@ class MqttLight(
"msg_callback": xy_received,
"qos": self._config[CONF_QOS],
}
self._hs = (0, 0)
if (
self._optimistic_xy
and last_state
and last_state.attributes.get(ATTR_HS_COLOR)
):
self._hs = last_state.attributes.get(ATTR_HS_COLOR)
elif self._topic[CONF_XY_COMMAND_TOPIC] is not None:
self._hs = (0, 0)
self._sub_state = await subscription.async_subscribe_topics(
self.hass, self._sub_state, topics
@ -781,8 +752,9 @@ class MqttLight(
and ATTR_HS_COLOR not in kwargs
and self._topic[CONF_RGB_COMMAND_TOPIC] is not None
):
hs_color = self._hs if self._hs is not None else (0, 0)
rgb = color_util.color_hsv_to_RGB(
self._hs[0], self._hs[1], kwargs[ATTR_BRIGHTNESS] / 255 * 100
hs_color[0], hs_color[1], kwargs[ATTR_BRIGHTNESS] / 255 * 100
)
tpl = self._command_templates[CONF_RGB_COMMAND_TEMPLATE]
if tpl:

View File

@ -192,35 +192,6 @@ class MqttLightJson(
optimistic = config[CONF_OPTIMISTIC]
self._optimistic = optimistic or self._topic[CONF_STATE_TOPIC] is None
brightness = config[CONF_BRIGHTNESS]
if brightness:
self._brightness = 255
else:
self._brightness = None
color_temp = config[CONF_COLOR_TEMP]
if color_temp:
self._color_temp = 150
else:
self._color_temp = None
effect = config[CONF_EFFECT]
if effect:
self._effect = "none"
else:
self._effect = None
white_value = config[CONF_WHITE_VALUE]
if white_value:
self._white_value = 255
else:
self._white_value = None
if config[CONF_HS] or config[CONF_RGB] or config[CONF_XY]:
self._hs = [0, 0]
else:
self._hs = None
self._flash_times = {
key: config.get(key)
for key in (CONF_FLASH_TIME_SHORT, CONF_FLASH_TIME_LONG)
@ -228,10 +199,10 @@ class MqttLightJson(
self._supported_features = SUPPORT_TRANSITION | SUPPORT_FLASH
self._supported_features |= config[CONF_RGB] and SUPPORT_COLOR
self._supported_features |= brightness and SUPPORT_BRIGHTNESS
self._supported_features |= color_temp and SUPPORT_COLOR_TEMP
self._supported_features |= effect and SUPPORT_EFFECT
self._supported_features |= white_value and SUPPORT_WHITE_VALUE
self._supported_features |= config[CONF_BRIGHTNESS] and SUPPORT_BRIGHTNESS
self._supported_features |= config[CONF_COLOR_TEMP] and SUPPORT_COLOR_TEMP
self._supported_features |= config[CONF_EFFECT] and SUPPORT_EFFECT
self._supported_features |= config[CONF_WHITE_VALUE] and SUPPORT_WHITE_VALUE
self._supported_features |= config[CONF_XY] and SUPPORT_COLOR
self._supported_features |= config[CONF_HS] and SUPPORT_COLOR
@ -250,7 +221,7 @@ class MqttLightJson(
elif values["state"] == "OFF":
self._state = False
if self._hs is not None:
if self._supported_features and SUPPORT_COLOR:
try:
red = int(values["color"]["r"])
green = int(values["color"]["g"])
@ -282,7 +253,7 @@ class MqttLightJson(
except ValueError:
_LOGGER.warning("Invalid HS color value received")
if self._brightness is not None:
if self._supported_features and SUPPORT_BRIGHTNESS:
try:
self._brightness = int(
values["brightness"]
@ -294,7 +265,7 @@ class MqttLightJson(
except (TypeError, ValueError):
_LOGGER.warning("Invalid brightness value received")
if self._color_temp is not None:
if self._supported_features and SUPPORT_COLOR_TEMP:
try:
self._color_temp = int(values["color_temp"])
except KeyError:
@ -302,13 +273,13 @@ class MqttLightJson(
except ValueError:
_LOGGER.warning("Invalid color temp value received")
if self._effect is not None:
if self._supported_features and SUPPORT_EFFECT:
try:
self._effect = values["effect"]
except KeyError:
pass
if self._white_value is not None:
if self._supported_features and SUPPORT_WHITE_VALUE:
try:
self._white_value = int(values["white_value"])
except KeyError:
@ -440,7 +411,7 @@ class MqttLightJson(
if self._config[CONF_RGB]:
# If there's a brightness topic set, we don't want to scale the
# RGB values given using the brightness.
if self._brightness is not None:
if self._config[CONF_BRIGHTNESS]:
brightness = 255
else:
brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
@ -473,7 +444,7 @@ class MqttLightJson(
if ATTR_TRANSITION in kwargs:
message["transition"] = kwargs[ATTR_TRANSITION]
if ATTR_BRIGHTNESS in kwargs and self._brightness is not None:
if ATTR_BRIGHTNESS in kwargs and self._config[CONF_BRIGHTNESS]:
brightness_normalized = kwargs[ATTR_BRIGHTNESS] / DEFAULT_BRIGHTNESS_SCALE
brightness_scale = self._config[CONF_BRIGHTNESS_SCALE]
device_brightness = min(

View File

@ -185,32 +185,6 @@ class MqttLightTemplate(
or self._templates[CONF_STATE_TEMPLATE] is None
)
# features
if self._templates[CONF_BRIGHTNESS_TEMPLATE] is not None:
self._brightness = 255
else:
self._brightness = None
if self._templates[CONF_COLOR_TEMP_TEMPLATE] is not None:
self._color_temp = 255
else:
self._color_temp = None
if self._templates[CONF_WHITE_VALUE_TEMPLATE] is not None:
self._white_value = 255
else:
self._white_value = None
if (
self._templates[CONF_RED_TEMPLATE] is not None
and self._templates[CONF_GREEN_TEMPLATE] is not None
and self._templates[CONF_BLUE_TEMPLATE] is not None
):
self._hs = [0, 0]
else:
self._hs = None
self._effect = None
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
for tpl in self._templates.values():
@ -233,7 +207,7 @@ class MqttLightTemplate(
else:
_LOGGER.warning("Invalid state value received")
if self._brightness is not None:
if self._templates[CONF_BRIGHTNESS_TEMPLATE] is not None:
try:
self._brightness = int(
self._templates[
@ -243,7 +217,7 @@ class MqttLightTemplate(
except ValueError:
_LOGGER.warning("Invalid brightness value received")
if self._color_temp is not None:
if self._templates[CONF_COLOR_TEMP_TEMPLATE] is not None:
try:
self._color_temp = int(
self._templates[
@ -253,7 +227,11 @@ class MqttLightTemplate(
except ValueError:
_LOGGER.warning("Invalid color temperature value received")
if self._hs is not None:
if (
self._templates[CONF_RED_TEMPLATE] is not None
and self._templates[CONF_GREEN_TEMPLATE] is not None
and self._templates[CONF_BLUE_TEMPLATE] is not None
):
try:
red = int(
self._templates[
@ -274,7 +252,7 @@ class MqttLightTemplate(
except ValueError:
_LOGGER.warning("Invalid color value received")
if self._white_value is not None:
if self._templates[CONF_COLOR_TEMP_TEMPLATE] is not None:
try:
self._white_value = int(
self._templates[
@ -429,7 +407,8 @@ class MqttLightTemplate(
brightness = 255
else:
brightness = kwargs.get(
ATTR_BRIGHTNESS, self._brightness if self._brightness else 255
ATTR_BRIGHTNESS,
self._brightness if self._brightness is not None else 255,
)
rgb = color_util.color_hsv_to_RGB(
hs_color[0], hs_color[1], brightness / 255 * 100
@ -497,15 +476,19 @@ class MqttLightTemplate(
def supported_features(self):
"""Flag supported features."""
features = SUPPORT_FLASH | SUPPORT_TRANSITION
if self._brightness is not None:
if self._templates[CONF_BRIGHTNESS_TEMPLATE] is not None:
features = features | SUPPORT_BRIGHTNESS
if self._hs is not None:
if (
self._templates[CONF_RED_TEMPLATE] is not None
and self._templates[CONF_GREEN_TEMPLATE] is not None
and self._templates[CONF_BLUE_TEMPLATE] is not None
):
features = features | SUPPORT_COLOR
if self._config.get(CONF_EFFECT_LIST) is not None:
features = features | SUPPORT_EFFECT
if self._color_temp is not None:
if self._templates[CONF_COLOR_TEMP_TEMPLATE] is not None:
features = features | SUPPORT_COLOR_TEMP
if self._white_value is not None:
if self._templates[CONF_WHITE_VALUE_TEMPLATE] is not None:
features = features | SUPPORT_WHITE_VALUE
return features

View File

@ -289,13 +289,13 @@ async def test_controlling_state_via_topic(hass, mqtt_mock):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (255, 255, 255)
assert state.attributes.get("brightness") == 255
assert state.attributes.get("color_temp") == 150
assert state.attributes.get("effect") == "none"
assert state.attributes.get("hs_color") == (0, 0)
assert state.attributes.get("white_value") == 255
assert state.attributes.get("xy_color") == (0.323, 0.329)
assert state.attributes.get("rgb_color") is None
assert state.attributes.get("brightness") is None
assert state.attributes.get("color_temp") is None
assert state.attributes.get("effect") is None
assert state.attributes.get("hs_color") is None
assert state.attributes.get("white_value") is None
assert state.attributes.get("xy_color") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "0")
@ -383,12 +383,17 @@ async def test_invalid_state_via_topic(hass, mqtt_mock, caplog):
assert not state.attributes.get(ATTR_ASSUMED_STATE)
async_fire_mqtt_message(hass, "test_light_rgb/status", "1")
async_fire_mqtt_message(hass, "test_light_rgb/rgb/status", "255,255,255")
async_fire_mqtt_message(hass, "test_light_rgb/brightness/status", "255")
async_fire_mqtt_message(hass, "test_light_rgb/color_temp/status", "153")
async_fire_mqtt_message(hass, "test_light_rgb/effect/status", "none")
async_fire_mqtt_message(hass, "test_light_rgb/white_value/status", "255")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (255, 255, 255)
assert state.attributes.get("brightness") == 255
assert state.attributes.get("color_temp") == 150
assert state.attributes.get("color_temp") == 153
assert state.attributes.get("effect") == "none"
assert state.attributes.get("hs_color") == (0, 0)
assert state.attributes.get("white_value") == 255
@ -407,7 +412,7 @@ async def test_invalid_state_via_topic(hass, mqtt_mock, caplog):
async_fire_mqtt_message(hass, "test_light_rgb/color_temp/status", "")
assert "Ignoring empty color temp message" in caplog.text
light_state = hass.states.get("light.test")
assert light_state.attributes["color_temp"] == 150
assert light_state.attributes["color_temp"] == 153
async_fire_mqtt_message(hass, "test_light_rgb/effect/status", "")
assert "Ignoring empty effect message" in caplog.text
@ -472,7 +477,7 @@ async def test_brightness_controlling_scale(hass, mqtt_mock):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 255
assert state.attributes.get("brightness") is None
async_fire_mqtt_message(hass, "test_scale/status", "off")
@ -558,7 +563,7 @@ async def test_white_value_controlling_scale(hass, mqtt_mock):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("white_value") == 255
assert state.attributes.get("white_value") is None
async_fire_mqtt_message(hass, "test_scale/status", "off")
@ -846,162 +851,6 @@ async def test_sending_mqtt_color_temp_command_with_template(hass, mqtt_mock):
assert state.attributes["color_temp"] == 100
async def test_show_brightness_if_only_command_topic(hass, mqtt_mock):
"""Test the brightness if only a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"brightness_command_topic": "test_light_rgb/brightness/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("brightness") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 255
async def test_show_color_temp_only_if_command_topic(hass, mqtt_mock):
"""Test the color temp only if a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"color_temp_command_topic": "test_light_rgb/brightness/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("color_temp") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("color_temp") == 150
async def test_show_effect_only_if_command_topic(hass, mqtt_mock):
"""Test the effect only if a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"effect_command_topic": "test_light_rgb/effect/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("effect") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("effect") == "none"
async def test_show_hs_if_only_command_topic(hass, mqtt_mock):
"""Test the hs if only a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"hs_command_topic": "test_light_rgb/hs/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("hs_color") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("hs_color") == (0, 0)
async def test_show_white_value_if_only_command_topic(hass, mqtt_mock):
"""Test the white_value if only a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"white_value_command_topic": "test_light_rgb/white_value/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("white_value") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("white_value") == 255
async def test_show_xy_if_only_command_topic(hass, mqtt_mock):
"""Test the xy if only a command topic is present."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"xy_command_topic": "test_light_rgb/xy/set",
"command_topic": "test_light_rgb/set",
"state_topic": "test_light_rgb/status",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
state = hass.states.get("light.test")
assert state.state == STATE_OFF
assert state.attributes.get("xy_color") is None
async_fire_mqtt_message(hass, "test_light_rgb/status", "ON")
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("xy_color") == (0.323, 0.329)
async def test_on_command_first(hass, mqtt_mock):
"""Test on command being sent before brightness."""
config = {

View File

@ -796,7 +796,7 @@ async def test_effect(hass, mqtt_mock):
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("effect") == "none"
assert state.attributes.get("effect") is None
await common.async_turn_on(hass, "light.test", effect="rainbow")
@ -942,7 +942,7 @@ async def test_brightness_scale(hass, mqtt_mock):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 255
assert state.attributes.get("brightness") is None
# Turn on the light with brightness
async_fire_mqtt_message(

View File

@ -317,6 +317,14 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
"{{ blue|d }}",
"command_off_template": "off",
"effect_list": ["colorloop", "random"],
"optimistic": True,
"state_template": '{{ value.split(",")[0] }}',
"color_temp_template": '{{ value.split(",")[2] }}',
"white_value_template": '{{ value.split(",")[3] }}',
"red_template": '{{ value.split(",")[4].' 'split("-")[0] }}',
"green_template": '{{ value.split(",")[4].' 'split("-")[1] }}',
"blue_template": '{{ value.split(",")[4].' 'split("-")[2] }}',
"effect_template": '{{ value.split(",")[5] }}',
"qos": 2,
}
},
@ -325,7 +333,6 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 95
assert state.attributes.get("hs_color") == (100, 100)
assert state.attributes.get("effect") == "random"
assert state.attributes.get("color_temp") == 100
@ -366,7 +373,6 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 255
# Full brightness - no scaling of RGB values sent over MQTT
await common.async_turn_on(
@ -399,7 +405,6 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("brightness") == 128
# Half brightness - scaling of RGB values sent over MQTT
await common.async_turn_on(