Allow to process kelvin as color_temp for mqtt template light (#133957)

This commit is contained in:
Jan Bouwhuis 2025-01-10 11:43:36 +01:00 committed by GitHub
parent b5971ec55d
commit eba090c9ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 137 additions and 53 deletions

View File

@ -39,7 +39,14 @@ import homeassistant.util.color as color_util
from .. import subscription
from ..config import MQTT_RW_SCHEMA
from ..const import CONF_COMMAND_TOPIC, CONF_STATE_TOPIC, PAYLOAD_NONE
from ..const import (
CONF_COLOR_TEMP_KELVIN,
CONF_COMMAND_TOPIC,
CONF_MAX_KELVIN,
CONF_MIN_KELVIN,
CONF_STATE_TOPIC,
PAYLOAD_NONE,
)
from ..entity import MqttEntity
from ..models import (
MqttCommandTemplate,
@ -85,12 +92,15 @@ PLATFORM_SCHEMA_MODERN_TEMPLATE = (
{
vol.Optional(CONF_BLUE_TEMPLATE): cv.template,
vol.Optional(CONF_BRIGHTNESS_TEMPLATE): cv.template,
vol.Optional(CONF_COLOR_TEMP_KELVIN, default=False): cv.boolean,
vol.Optional(CONF_COLOR_TEMP_TEMPLATE): cv.template,
vol.Required(CONF_COMMAND_OFF_TEMPLATE): cv.template,
vol.Required(CONF_COMMAND_ON_TEMPLATE): cv.template,
vol.Optional(CONF_EFFECT_LIST): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_EFFECT_TEMPLATE): cv.template,
vol.Optional(CONF_GREEN_TEMPLATE): cv.template,
vol.Optional(CONF_MAX_KELVIN): cv.positive_int,
vol.Optional(CONF_MIN_KELVIN): cv.positive_int,
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
@ -128,15 +138,16 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
def _setup_from_config(self, config: ConfigType) -> None:
"""(Re)Setup the entity."""
self._color_temp_kelvin = config[CONF_COLOR_TEMP_KELVIN]
self._attr_min_color_temp_kelvin = (
color_util.color_temperature_mired_to_kelvin(max_mireds)
if (max_mireds := config.get(CONF_MAX_MIREDS))
else DEFAULT_MIN_KELVIN
else config.get(CONF_MIN_KELVIN, DEFAULT_MIN_KELVIN)
)
self._attr_max_color_temp_kelvin = (
color_util.color_temperature_mired_to_kelvin(min_mireds)
if (min_mireds := config.get(CONF_MIN_MIREDS))
else DEFAULT_MAX_KELVIN
else config.get(CONF_MAX_KELVIN, DEFAULT_MAX_KELVIN)
)
self._attr_effect_list = config.get(CONF_EFFECT_LIST)
@ -224,7 +235,9 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
msg.payload
)
self._attr_color_temp_kelvin = (
color_util.color_temperature_mired_to_kelvin(int(color_temp))
int(color_temp)
if self._color_temp_kelvin
else color_util.color_temperature_mired_to_kelvin(int(color_temp))
if color_temp != "None"
else None
)
@ -310,8 +323,12 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
self._attr_brightness = kwargs[ATTR_BRIGHTNESS]
if ATTR_COLOR_TEMP_KELVIN in kwargs:
values["color_temp"] = color_util.color_temperature_kelvin_to_mired(
values["color_temp"] = (
kwargs[ATTR_COLOR_TEMP_KELVIN]
if self._color_temp_kelvin
else color_util.color_temperature_kelvin_to_mired(
kwargs[ATTR_COLOR_TEMP_KELVIN]
)
)
if self._optimistic:

View File

@ -179,25 +179,50 @@ async def test_rgb_light(
@pytest.mark.parametrize(
"hass_config",
("hass_config", "kelvin", "payload"),
[
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light/set",
"command_on_template": "on,{{ brightness|d }},{{ color_temp|d }}",
"command_off_template": "off",
"brightness_template": "{{ value.split(',')[1] }}",
"color_temp_template": "{{ value.split(',')[2] }}",
(
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light/set",
"command_on_template": "on,{{ brightness|d }},{{ color_temp|d }}",
"command_off_template": "off",
"brightness_template": "{{ value.split(',')[1] }}",
"color_temp_template": "{{ value.split(',')[2] }}",
}
}
}
}
},
5208,
"192",
),
(
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light/set",
"command_on_template": "on,{{ brightness|d }},{{ color_temp|d }}",
"command_off_template": "off",
"brightness_template": "{{ value.split(',')[1] }}",
"color_temp_template": "{{ value.split(',')[2] }}",
}
}
},
5208,
"5208",
),
],
ids=["mireds", "kelvin"],
)
async def test_single_color_mode(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
kelvin: int,
payload: str,
) -> None:
"""Test the color mode when we only have one supported color_mode."""
await mqtt_mock_entry()
@ -206,15 +231,15 @@ async def test_single_color_mode(
assert state.state == STATE_UNKNOWN
await common.async_turn_on(
hass, "light.test", brightness=50, color_temp_kelvin=5208
hass, "light.test", brightness=50, color_temp_kelvin=kelvin
)
async_fire_mqtt_message(hass, "test_light", "on,50,192")
async_fire_mqtt_message(hass, "test_light", f"on,50,{payload}")
color_modes = [light.ColorMode.COLOR_TEMP]
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get(light.ATTR_SUPPORTED_COLOR_MODES) == color_modes
assert state.attributes.get(light.ATTR_COLOR_TEMP_KELVIN) == 5208
assert state.attributes.get(light.ATTR_COLOR_TEMP_KELVIN) == kelvin
assert state.attributes.get(light.ATTR_BRIGHTNESS) == 50
assert state.attributes.get(light.ATTR_COLOR_MODE) == color_modes[0]
@ -392,39 +417,80 @@ async def test_state_brightness_color_effect_temp_change_via_topic(
@pytest.mark.parametrize(
"hass_config",
("hass_config", "kelvin", "payload"),
[
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light_rgb/set",
"command_on_template": "on,"
"{{ brightness|d }},"
"{{ color_temp|d }},"
"{{ red|d }}-"
"{{ green|d }}-"
"{{ blue|d }},"
"{{ hue|d }}-"
"{{ sat|d }}",
"command_off_template": "off",
"effect_list": ["colorloop", "random"],
"optimistic": True,
"state_template": '{{ value.split(",")[0] }}',
"color_temp_template": '{{ value.split(",")[2] }}',
"red_template": '{{ value.split(",")[3].split("-")[0] }}',
"green_template": '{{ value.split(",")[3].split("-")[1] }}',
"blue_template": '{{ value.split(",")[3].split("-")[2] }}',
"effect_template": '{{ value.split(",")[4] }}',
"qos": 2,
(
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light_rgb/set",
"command_on_template": "on,"
"{{ brightness|d }},"
"{{ color_temp|d }},"
"{{ red|d }}-"
"{{ green|d }}-"
"{{ blue|d }},"
"{{ hue|d }}-"
"{{ sat|d }}",
"command_off_template": "off",
"effect_list": ["colorloop", "random"],
"optimistic": True,
"state_template": '{{ value.split(",")[0] }}',
"color_temp_kelvin": False,
"color_temp_template": '{{ value.split(",")[2] }}',
"red_template": '{{ value.split(",")[3].split("-")[0] }}',
"green_template": '{{ value.split(",")[3].split("-")[1] }}',
"blue_template": '{{ value.split(",")[3].split("-")[2] }}',
"effect_template": '{{ value.split(",")[4] }}',
"qos": 2,
}
}
}
}
},
14285,
"on,,70,--,-",
),
(
{
mqtt.DOMAIN: {
light.DOMAIN: {
"schema": "template",
"name": "test",
"command_topic": "test_light_rgb/set",
"command_on_template": "on,"
"{{ brightness|d }},"
"{{ color_temp|d }},"
"{{ red|d }}-"
"{{ green|d }}-"
"{{ blue|d }},"
"{{ hue|d }}-"
"{{ sat|d }}",
"command_off_template": "off",
"effect_list": ["colorloop", "random"],
"optimistic": True,
"state_template": '{{ value.split(",")[0] }}',
"color_temp_kelvin": True,
"color_temp_template": '{{ value.split(",")[2] }}',
"red_template": '{{ value.split(",")[3].split("-")[0] }}',
"green_template": '{{ value.split(",")[3].split("-")[1] }}',
"blue_template": '{{ value.split(",")[3].split("-")[2] }}',
"effect_template": '{{ value.split(",")[4] }}',
"qos": 2,
}
},
},
14285,
"on,,14285,--,-",
),
],
ids=["mireds", "kelvin"],
)
async def test_sending_mqtt_commands_and_optimistic(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
kelvin: int,
payload: str,
) -> None:
"""Test the sending of command in optimistic mode."""
fake_state = State(
@ -465,14 +531,15 @@ async def test_sending_mqtt_commands_and_optimistic(
assert state.state == STATE_ON
# Set color_temp
await common.async_turn_on(hass, "light.test", color_temp_kelvin=14285)
await common.async_turn_on(hass, "light.test", color_temp_kelvin=kelvin)
# Assert mireds or Kelvin as payload
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set", "on,,70,--,-", 2, False
"test_light_rgb/set", payload, 2, False
)
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test")
assert state.state == STATE_ON
assert state.attributes.get("color_temp_kelvin") == 14285
assert state.attributes.get("color_temp_kelvin") == kelvin
# Set full brightness
await common.async_turn_on(hass, "light.test", brightness=255)