Additional MQTT light command templates (#63361)
Co-authored-by: jbouwh <jan@jbsoft.nl>
This commit is contained in:
parent
8741ff0684
commit
95de1dd446
3 changed files with 128 additions and 7 deletions
|
@ -16,6 +16,7 @@ ABBREVIATIONS = {
|
||||||
"away_mode_stat_tpl": "away_mode_state_template",
|
"away_mode_stat_tpl": "away_mode_state_template",
|
||||||
"away_mode_stat_t": "away_mode_state_topic",
|
"away_mode_stat_t": "away_mode_state_topic",
|
||||||
"b_tpl": "blue_template",
|
"b_tpl": "blue_template",
|
||||||
|
"bri_cmd_tpl": "brightness_command_template",
|
||||||
"bri_cmd_t": "brightness_command_topic",
|
"bri_cmd_t": "brightness_command_topic",
|
||||||
"bri_scl": "brightness_scale",
|
"bri_scl": "brightness_scale",
|
||||||
"bri_stat_t": "brightness_state_topic",
|
"bri_stat_t": "brightness_state_topic",
|
||||||
|
@ -58,6 +59,7 @@ ABBREVIATIONS = {
|
||||||
"fanspd_lst": "fan_speed_list",
|
"fanspd_lst": "fan_speed_list",
|
||||||
"flsh_tlng": "flash_time_long",
|
"flsh_tlng": "flash_time_long",
|
||||||
"flsh_tsht": "flash_time_short",
|
"flsh_tsht": "flash_time_short",
|
||||||
|
"fx_cmd_tpl": "effect_command_template",
|
||||||
"fx_cmd_t": "effect_command_topic",
|
"fx_cmd_t": "effect_command_topic",
|
||||||
"fx_list": "effect_list",
|
"fx_list": "effect_list",
|
||||||
"fx_stat_t": "effect_state_topic",
|
"fx_stat_t": "effect_state_topic",
|
||||||
|
|
|
@ -68,6 +68,7 @@ from .schema import MQTT_LIGHT_SCHEMA_SCHEMA
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CONF_BRIGHTNESS_COMMAND_TEMPLATE = "brightness_command_template"
|
||||||
CONF_BRIGHTNESS_COMMAND_TOPIC = "brightness_command_topic"
|
CONF_BRIGHTNESS_COMMAND_TOPIC = "brightness_command_topic"
|
||||||
CONF_BRIGHTNESS_SCALE = "brightness_scale"
|
CONF_BRIGHTNESS_SCALE = "brightness_scale"
|
||||||
CONF_BRIGHTNESS_STATE_TOPIC = "brightness_state_topic"
|
CONF_BRIGHTNESS_STATE_TOPIC = "brightness_state_topic"
|
||||||
|
@ -78,6 +79,7 @@ CONF_COLOR_TEMP_COMMAND_TEMPLATE = "color_temp_command_template"
|
||||||
CONF_COLOR_TEMP_COMMAND_TOPIC = "color_temp_command_topic"
|
CONF_COLOR_TEMP_COMMAND_TOPIC = "color_temp_command_topic"
|
||||||
CONF_COLOR_TEMP_STATE_TOPIC = "color_temp_state_topic"
|
CONF_COLOR_TEMP_STATE_TOPIC = "color_temp_state_topic"
|
||||||
CONF_COLOR_TEMP_VALUE_TEMPLATE = "color_temp_value_template"
|
CONF_COLOR_TEMP_VALUE_TEMPLATE = "color_temp_value_template"
|
||||||
|
CONF_EFFECT_COMMAND_TEMPLATE = "effect_command_template"
|
||||||
CONF_EFFECT_COMMAND_TOPIC = "effect_command_topic"
|
CONF_EFFECT_COMMAND_TOPIC = "effect_command_topic"
|
||||||
CONF_EFFECT_LIST = "effect_list"
|
CONF_EFFECT_LIST = "effect_list"
|
||||||
CONF_EFFECT_STATE_TOPIC = "effect_state_topic"
|
CONF_EFFECT_STATE_TOPIC = "effect_state_topic"
|
||||||
|
@ -141,7 +143,9 @@ DEFAULT_ON_COMMAND_TYPE = "last"
|
||||||
VALUES_ON_COMMAND_TYPE = ["first", "last", "brightness"]
|
VALUES_ON_COMMAND_TYPE = ["first", "last", "brightness"]
|
||||||
|
|
||||||
COMMAND_TEMPLATE_KEYS = [
|
COMMAND_TEMPLATE_KEYS = [
|
||||||
|
CONF_BRIGHTNESS_COMMAND_TEMPLATE,
|
||||||
CONF_COLOR_TEMP_COMMAND_TEMPLATE,
|
CONF_COLOR_TEMP_COMMAND_TEMPLATE,
|
||||||
|
CONF_EFFECT_COMMAND_TEMPLATE,
|
||||||
CONF_RGB_COMMAND_TEMPLATE,
|
CONF_RGB_COMMAND_TEMPLATE,
|
||||||
CONF_RGBW_COMMAND_TEMPLATE,
|
CONF_RGBW_COMMAND_TEMPLATE,
|
||||||
CONF_RGBWW_COMMAND_TEMPLATE,
|
CONF_RGBWW_COMMAND_TEMPLATE,
|
||||||
|
@ -163,6 +167,7 @@ VALUE_TEMPLATE_KEYS = [
|
||||||
_PLATFORM_SCHEMA_BASE = (
|
_PLATFORM_SCHEMA_BASE = (
|
||||||
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
|
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
|
vol.Optional(CONF_BRIGHTNESS_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_BRIGHTNESS_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
vol.Optional(CONF_BRIGHTNESS_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_BRIGHTNESS_SCALE, default=DEFAULT_BRIGHTNESS_SCALE
|
CONF_BRIGHTNESS_SCALE, default=DEFAULT_BRIGHTNESS_SCALE
|
||||||
|
@ -175,6 +180,7 @@ _PLATFORM_SCHEMA_BASE = (
|
||||||
vol.Optional(CONF_COLOR_TEMP_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
vol.Optional(CONF_COLOR_TEMP_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
vol.Optional(CONF_COLOR_TEMP_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
vol.Optional(CONF_COLOR_TEMP_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
vol.Optional(CONF_COLOR_TEMP_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_COLOR_TEMP_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_EFFECT_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_EFFECT_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
vol.Optional(CONF_EFFECT_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
vol.Optional(CONF_EFFECT_LIST): vol.All(cv.ensure_list, [cv.string]),
|
vol.Optional(CONF_EFFECT_LIST): vol.All(cv.ensure_list, [cv.string]),
|
||||||
vol.Optional(CONF_EFFECT_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
vol.Optional(CONF_EFFECT_STATE_TOPIC): mqtt.valid_subscribe_topic,
|
||||||
|
@ -970,6 +976,8 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
||||||
)
|
)
|
||||||
# Make sure the brightness is not rounded down to 0
|
# Make sure the brightness is not rounded down to 0
|
||||||
device_brightness = max(device_brightness, 1)
|
device_brightness = max(device_brightness, 1)
|
||||||
|
if tpl := self._command_templates[CONF_BRIGHTNESS_COMMAND_TEMPLATE]:
|
||||||
|
device_brightness = tpl(variables={"value": device_brightness})
|
||||||
await publish(CONF_BRIGHTNESS_COMMAND_TOPIC, device_brightness)
|
await publish(CONF_BRIGHTNESS_COMMAND_TOPIC, device_brightness)
|
||||||
should_update |= set_optimistic(ATTR_BRIGHTNESS, kwargs[ATTR_BRIGHTNESS])
|
should_update |= set_optimistic(ATTR_BRIGHTNESS, kwargs[ATTR_BRIGHTNESS])
|
||||||
elif (
|
elif (
|
||||||
|
@ -1038,8 +1046,10 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
||||||
if ATTR_EFFECT in kwargs and self._topic[CONF_EFFECT_COMMAND_TOPIC] is not None:
|
if ATTR_EFFECT in kwargs and self._topic[CONF_EFFECT_COMMAND_TOPIC] is not None:
|
||||||
effect = kwargs[ATTR_EFFECT]
|
effect = kwargs[ATTR_EFFECT]
|
||||||
if effect in self._config.get(CONF_EFFECT_LIST):
|
if effect in self._config.get(CONF_EFFECT_LIST):
|
||||||
|
if tpl := self._command_templates[CONF_EFFECT_COMMAND_TEMPLATE]:
|
||||||
|
effect = tpl(variables={"value": effect})
|
||||||
await publish(CONF_EFFECT_COMMAND_TOPIC, effect)
|
await publish(CONF_EFFECT_COMMAND_TOPIC, effect)
|
||||||
should_update |= set_optimistic(ATTR_EFFECT, effect)
|
should_update |= set_optimistic(ATTR_EFFECT, kwargs[ATTR_EFFECT])
|
||||||
|
|
||||||
if ATTR_WHITE in kwargs and self._topic[CONF_WHITE_COMMAND_TOPIC] is not None:
|
if ATTR_WHITE in kwargs and self._topic[CONF_WHITE_COMMAND_TOPIC] is not None:
|
||||||
percent_white = float(kwargs[ATTR_WHITE]) / 255
|
percent_white = float(kwargs[ATTR_WHITE]) / 255
|
||||||
|
|
|
@ -152,6 +152,37 @@ light:
|
||||||
payload_on: "on"
|
payload_on: "on"
|
||||||
payload_off: "off"
|
payload_off: "off"
|
||||||
|
|
||||||
|
Configuration with brightness command template:
|
||||||
|
|
||||||
|
light:
|
||||||
|
platform: mqtt
|
||||||
|
name: "Office Light"
|
||||||
|
state_topic: "office/rgb1/light/status"
|
||||||
|
command_topic: "office/rgb1/light/switch"
|
||||||
|
brightness_state_topic: "office/rgb1/brightness/status"
|
||||||
|
brightness_command_topic: "office/rgb1/brightness/set"
|
||||||
|
brightness_command_template: '{ "brightness": "{{ value }}" }'
|
||||||
|
qos: 0
|
||||||
|
payload_on: "on"
|
||||||
|
payload_off: "off"
|
||||||
|
|
||||||
|
Configuration with effect command template:
|
||||||
|
|
||||||
|
light:
|
||||||
|
platform: mqtt
|
||||||
|
name: "Office Light Color Temp"
|
||||||
|
state_topic: "office/rgb1/light/status"
|
||||||
|
command_topic: "office/rgb1/light/switch"
|
||||||
|
effect_state_topic: "office/rgb1/effect/status"
|
||||||
|
effect_command_topic: "office/rgb1/effect/set"
|
||||||
|
effect_command_template: '{ "effect": "{{ value }}" }'
|
||||||
|
effect_list:
|
||||||
|
- rainbow
|
||||||
|
- colorloop
|
||||||
|
qos: 0
|
||||||
|
payload_on: "on"
|
||||||
|
payload_off: "off"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
from unittest.mock import call, patch
|
from unittest.mock import call, patch
|
||||||
|
@ -3394,18 +3425,18 @@ async def test_max_mireds(hass, mqtt_mock):
|
||||||
"brightness_command_topic",
|
"brightness_command_topic",
|
||||||
{"color_temp": "200", "brightness": "50"},
|
{"color_temp": "200", "brightness": "50"},
|
||||||
50,
|
50,
|
||||||
None,
|
"brightness_command_template",
|
||||||
None,
|
"value",
|
||||||
None,
|
b"5",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
light.SERVICE_TURN_ON,
|
light.SERVICE_TURN_ON,
|
||||||
"effect_command_topic",
|
"effect_command_topic",
|
||||||
{"rgb_color": [255, 128, 0], "effect": "color_loop"},
|
{"rgb_color": [255, 128, 0], "effect": "color_loop"},
|
||||||
"color_loop",
|
"color_loop",
|
||||||
None,
|
"effect_command_template",
|
||||||
None,
|
"value",
|
||||||
None,
|
b"c",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
light.SERVICE_TURN_ON,
|
light.SERVICE_TURN_ON,
|
||||||
|
@ -3565,3 +3596,81 @@ async def test_encoding_subscribable_topics(
|
||||||
attribute_value,
|
attribute_value,
|
||||||
init_payload,
|
init_payload,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_sending_mqtt_brightness_command_with_template(hass, mqtt_mock):
|
||||||
|
"""Test the sending of Brightness command with template."""
|
||||||
|
config = {
|
||||||
|
light.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "test_light_brightness/set",
|
||||||
|
"brightness_command_topic": "test_light_brightness/brightness/set",
|
||||||
|
"brightness_command_template": "{{ (1000 / value) | round(0) }}",
|
||||||
|
"payload_on": "on",
|
||||||
|
"payload_off": "off",
|
||||||
|
"qos": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
await common.async_turn_on(hass, "light.test", brightness=100)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_has_calls(
|
||||||
|
[
|
||||||
|
call("test_light_brightness/set", "on", 0, False),
|
||||||
|
call("test_light_brightness/brightness/set", "10", 0, False),
|
||||||
|
],
|
||||||
|
any_order=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("light.test")
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
assert state.attributes["brightness"] == 100
|
||||||
|
|
||||||
|
|
||||||
|
async def test_sending_mqtt_effect_command_with_template(hass, mqtt_mock):
|
||||||
|
"""Test the sending of Effect command with template."""
|
||||||
|
config = {
|
||||||
|
light.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "test_light_brightness/set",
|
||||||
|
"brightness_command_topic": "test_light_brightness/brightness/set",
|
||||||
|
"effect_command_topic": "test_light_brightness/effect/set",
|
||||||
|
"effect_command_template": '{ "effect": "{{ value }}" }',
|
||||||
|
"effect_list": ["colorloop", "random"],
|
||||||
|
"payload_on": "on",
|
||||||
|
"payload_off": "off",
|
||||||
|
"qos": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
await common.async_turn_on(hass, "light.test", effect="colorloop")
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_has_calls(
|
||||||
|
[
|
||||||
|
call("test_light_brightness/set", "on", 0, False),
|
||||||
|
call(
|
||||||
|
"test_light_brightness/effect/set",
|
||||||
|
'{ "effect": "colorloop" }',
|
||||||
|
0,
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
any_order=True,
|
||||||
|
)
|
||||||
|
state = hass.states.get("light.test")
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
assert state.attributes.get("effect") == "colorloop"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue