mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Add transition support to zwave_js lights (#52160)
* Add transition support to zwave_js lights * Add transition support to color_switch lights * simplify and add tests * fix logic * add check for color transition to add SUPPORT_TRANSITON supported features * Use new metadata property * Use new metadata property * update tests and device state dump json files * fix file perms * update tests and fixtures with new metadata * update test * update test * update tests for color transitions * check for color tansitions as well * more tests * fix color transtions * remove unneed default * set add_to_watched_value_ids to false * set transition default * properly set default * update tests * make sure transition is an int * suggested changes * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * formatting Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
1e6229dd7b
commit
92ab471f7b
@ -44,6 +44,8 @@ MULTI_COLOR_MAP = {
|
|||||||
ColorComponent.PURPLE: "purple",
|
ColorComponent.PURPLE: "purple",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRANSITION_DURATION = "transitionDuration"
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -109,8 +111,13 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
self._supported_color_modes = set()
|
self._supported_color_modes = set()
|
||||||
|
|
||||||
# get additional (optional) values and set features
|
# get additional (optional) values and set features
|
||||||
self._target_value = self.get_zwave_value("targetValue")
|
self._target_brightness = self.get_zwave_value(
|
||||||
self._dimming_duration = self.get_zwave_value("duration")
|
"targetValue", add_to_watched_value_ids=False
|
||||||
|
)
|
||||||
|
self._target_color = self.get_zwave_value(
|
||||||
|
"targetColor", CommandClass.SWITCH_COLOR, add_to_watched_value_ids=False
|
||||||
|
)
|
||||||
|
|
||||||
self._calculate_color_values()
|
self._calculate_color_values()
|
||||||
if self._supports_rgbw:
|
if self._supports_rgbw:
|
||||||
self._supported_color_modes.add(COLOR_MODE_RGBW)
|
self._supported_color_modes.add(COLOR_MODE_RGBW)
|
||||||
@ -123,7 +130,17 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
|
|
||||||
# Entity class attributes
|
# Entity class attributes
|
||||||
self._attr_supported_features = 0
|
self._attr_supported_features = 0
|
||||||
if self._dimming_duration is not None:
|
self.supports_brightness_transition = bool(
|
||||||
|
self._target_brightness is not None
|
||||||
|
and TRANSITION_DURATION
|
||||||
|
in self._target_brightness.metadata.value_change_options
|
||||||
|
)
|
||||||
|
self.supports_color_transition = bool(
|
||||||
|
self._target_color is not None
|
||||||
|
and TRANSITION_DURATION in self._target_color.metadata.value_change_options
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.supports_brightness_transition or self.supports_color_transition:
|
||||||
self._attr_supported_features |= SUPPORT_TRANSITION
|
self._attr_supported_features |= SUPPORT_TRANSITION
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -183,6 +200,9 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
|
|
||||||
|
transition = kwargs.get(ATTR_TRANSITION)
|
||||||
|
|
||||||
# RGB/HS color
|
# RGB/HS color
|
||||||
hs_color = kwargs.get(ATTR_HS_COLOR)
|
hs_color = kwargs.get(ATTR_HS_COLOR)
|
||||||
if hs_color is not None and self._supports_color:
|
if hs_color is not None and self._supports_color:
|
||||||
@ -196,7 +216,7 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
# turn of white leds when setting rgb
|
# turn of white leds when setting rgb
|
||||||
colors[ColorComponent.WARM_WHITE] = 0
|
colors[ColorComponent.WARM_WHITE] = 0
|
||||||
colors[ColorComponent.COLD_WHITE] = 0
|
colors[ColorComponent.COLD_WHITE] = 0
|
||||||
await self._async_set_colors(colors)
|
await self._async_set_colors(colors, transition)
|
||||||
|
|
||||||
# Color temperature
|
# Color temperature
|
||||||
color_temp = kwargs.get(ATTR_COLOR_TEMP)
|
color_temp = kwargs.get(ATTR_COLOR_TEMP)
|
||||||
@ -222,7 +242,8 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
ColorComponent.BLUE: 0,
|
ColorComponent.BLUE: 0,
|
||||||
ColorComponent.WARM_WHITE: warm,
|
ColorComponent.WARM_WHITE: warm,
|
||||||
ColorComponent.COLD_WHITE: cold,
|
ColorComponent.COLD_WHITE: cold,
|
||||||
}
|
},
|
||||||
|
transition,
|
||||||
)
|
)
|
||||||
|
|
||||||
# RGBW
|
# RGBW
|
||||||
@ -238,18 +259,18 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
|
|
||||||
if self._cold_white:
|
if self._cold_white:
|
||||||
rgbw_channels[ColorComponent.COLD_WHITE] = rgbw[3]
|
rgbw_channels[ColorComponent.COLD_WHITE] = rgbw[3]
|
||||||
await self._async_set_colors(rgbw_channels)
|
await self._async_set_colors(rgbw_channels, transition)
|
||||||
|
|
||||||
# set brightness
|
# set brightness
|
||||||
await self._async_set_brightness(
|
await self._async_set_brightness(kwargs.get(ATTR_BRIGHTNESS), transition)
|
||||||
kwargs.get(ATTR_BRIGHTNESS), kwargs.get(ATTR_TRANSITION)
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the light off."""
|
"""Turn the light off."""
|
||||||
await self._async_set_brightness(0, kwargs.get(ATTR_TRANSITION))
|
await self._async_set_brightness(0, kwargs.get(ATTR_TRANSITION))
|
||||||
|
|
||||||
async def _async_set_colors(self, colors: dict[ColorComponent, int]) -> None:
|
async def _async_set_colors(
|
||||||
|
self, colors: dict[ColorComponent, int], transition: float | None = None
|
||||||
|
) -> None:
|
||||||
"""Set (multiple) defined colors to given value(s)."""
|
"""Set (multiple) defined colors to given value(s)."""
|
||||||
# prefer the (new) combined color property
|
# prefer the (new) combined color property
|
||||||
# https://github.com/zwave-js/node-zwave-js/pull/1782
|
# https://github.com/zwave-js/node-zwave-js/pull/1782
|
||||||
@ -258,21 +279,36 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
CommandClass.SWITCH_COLOR,
|
CommandClass.SWITCH_COLOR,
|
||||||
value_property_key=None,
|
value_property_key=None,
|
||||||
)
|
)
|
||||||
|
zwave_transition = None
|
||||||
|
|
||||||
|
if self.supports_color_transition:
|
||||||
|
if transition is not None:
|
||||||
|
zwave_transition = {TRANSITION_DURATION: f"{int(transition)}s"}
|
||||||
|
else:
|
||||||
|
zwave_transition = {TRANSITION_DURATION: "default"}
|
||||||
|
|
||||||
if combined_color_val and isinstance(combined_color_val.value, dict):
|
if combined_color_val and isinstance(combined_color_val.value, dict):
|
||||||
colors_dict = {}
|
colors_dict = {}
|
||||||
for color, value in colors.items():
|
for color, value in colors.items():
|
||||||
color_name = MULTI_COLOR_MAP[color]
|
color_name = MULTI_COLOR_MAP[color]
|
||||||
colors_dict[color_name] = value
|
colors_dict[color_name] = value
|
||||||
# set updated color object
|
# set updated color object
|
||||||
await self.info.node.async_set_value(combined_color_val, colors_dict)
|
await self.info.node.async_set_value(
|
||||||
|
combined_color_val, colors_dict, zwave_transition
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# fallback to setting the color(s) one by one if multicolor fails
|
# fallback to setting the color(s) one by one if multicolor fails
|
||||||
# not sure this is needed at all, but just in case
|
# not sure this is needed at all, but just in case
|
||||||
for color, value in colors.items():
|
for color, value in colors.items():
|
||||||
await self._async_set_color(color, value)
|
await self._async_set_color(color, value, zwave_transition)
|
||||||
|
|
||||||
async def _async_set_color(self, color: ColorComponent, new_value: int) -> None:
|
async def _async_set_color(
|
||||||
|
self,
|
||||||
|
color: ColorComponent,
|
||||||
|
new_value: int,
|
||||||
|
transition: dict[str, str] | None = None,
|
||||||
|
) -> None:
|
||||||
"""Set defined color to given value."""
|
"""Set defined color to given value."""
|
||||||
# actually set the new color value
|
# actually set the new color value
|
||||||
target_zwave_value = self.get_zwave_value(
|
target_zwave_value = self.get_zwave_value(
|
||||||
@ -283,10 +319,10 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
if target_zwave_value is None:
|
if target_zwave_value is None:
|
||||||
# guard for unsupported color
|
# guard for unsupported color
|
||||||
return
|
return
|
||||||
await self.info.node.async_set_value(target_zwave_value, new_value)
|
await self.info.node.async_set_value(target_zwave_value, new_value, transition)
|
||||||
|
|
||||||
async def _async_set_brightness(
|
async def _async_set_brightness(
|
||||||
self, brightness: int | None, transition: int | None = None
|
self, brightness: int | None, transition: float | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set new brightness to light."""
|
"""Set new brightness to light."""
|
||||||
if brightness is None:
|
if brightness is None:
|
||||||
@ -297,40 +333,17 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
|||||||
zwave_brightness = byte_to_zwave_brightness(brightness)
|
zwave_brightness = byte_to_zwave_brightness(brightness)
|
||||||
|
|
||||||
# set transition value before sending new brightness
|
# set transition value before sending new brightness
|
||||||
await self._async_set_transition_duration(transition)
|
zwave_transition = None
|
||||||
# setting a value requires setting targetValue
|
if self.supports_brightness_transition:
|
||||||
await self.info.node.async_set_value(self._target_value, zwave_brightness)
|
if transition is not None:
|
||||||
|
zwave_transition = {TRANSITION_DURATION: f"{int(transition)}s"}
|
||||||
async def _async_set_transition_duration(self, duration: int | None = None) -> None:
|
|
||||||
"""Set the transition time for the brightness value."""
|
|
||||||
if self._dimming_duration is None:
|
|
||||||
return
|
|
||||||
# pylint: disable=fixme,unreachable
|
|
||||||
# TODO: setting duration needs to be fixed upstream
|
|
||||||
# https://github.com/zwave-js/node-zwave-js/issues/1321
|
|
||||||
return
|
|
||||||
|
|
||||||
if duration is None: # type: ignore
|
|
||||||
# no transition specified by user, use defaults
|
|
||||||
duration = 7621 # anything over 7620 uses the factory default
|
|
||||||
else: # pragma: no cover
|
|
||||||
# transition specified by user
|
|
||||||
transition = duration
|
|
||||||
if transition <= 127:
|
|
||||||
duration = transition
|
|
||||||
else:
|
else:
|
||||||
minutes = round(transition / 60)
|
zwave_transition = {TRANSITION_DURATION: "default"}
|
||||||
LOGGER.debug(
|
|
||||||
"Transition rounded to %d minutes for %s",
|
|
||||||
minutes,
|
|
||||||
self.entity_id,
|
|
||||||
)
|
|
||||||
duration = minutes + 128
|
|
||||||
|
|
||||||
# only send value if it differs from current
|
# setting a value requires setting targetValue
|
||||||
# this prevents sending a command for nothing
|
await self.info.node.async_set_value(
|
||||||
if self._dimming_duration.value != duration: # pragma: no cover
|
self._target_brightness, zwave_brightness, zwave_transition
|
||||||
await self.info.node.async_set_value(self._dimming_duration, duration)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _calculate_color_values(self) -> None:
|
def _calculate_color_values(self) -> None:
|
||||||
|
@ -12,6 +12,7 @@ from homeassistant.components.light import (
|
|||||||
ATTR_RGB_COLOR,
|
ATTR_RGB_COLOR,
|
||||||
ATTR_RGBW_COLOR,
|
ATTR_RGBW_COLOR,
|
||||||
ATTR_SUPPORTED_COLOR_MODES,
|
ATTR_SUPPORTED_COLOR_MODES,
|
||||||
|
ATTR_TRANSITION,
|
||||||
SUPPORT_TRANSITION,
|
SUPPORT_TRANSITION,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_OFF, STATE_ON
|
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_OFF, STATE_ON
|
||||||
@ -62,12 +63,47 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
|||||||
"readable": True,
|
"readable": True,
|
||||||
"writeable": True,
|
"writeable": True,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert args["value"] == 255
|
assert args["value"] == 255
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
# Test turning on with transition
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{"entity_id": BULB_6_MULTI_COLOR_LIGHT_ENTITY, ATTR_TRANSITION: 10},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command.call_args_list) == 1
|
||||||
|
args = client.async_send_command.call_args[0][0]
|
||||||
|
assert args["command"] == "node.set_value"
|
||||||
|
assert args["nodeId"] == 39
|
||||||
|
assert args["valueId"] == {
|
||||||
|
"commandClassName": "Multilevel Switch",
|
||||||
|
"commandClass": 38,
|
||||||
|
"endpoint": 0,
|
||||||
|
"property": "targetValue",
|
||||||
|
"propertyName": "targetValue",
|
||||||
|
"metadata": {
|
||||||
|
"label": "Target value",
|
||||||
|
"max": 99,
|
||||||
|
"min": 0,
|
||||||
|
"type": "number",
|
||||||
|
"readable": True,
|
||||||
|
"writeable": True,
|
||||||
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert args["value"] == 255
|
||||||
|
assert args["options"]["transitionDuration"] == "10s"
|
||||||
|
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test brightness update from value updated event
|
# Test brightness update from value updated event
|
||||||
event = Event(
|
event = Event(
|
||||||
type="value updated",
|
type="value updated",
|
||||||
@ -133,9 +169,49 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
|||||||
"readable": True,
|
"readable": True,
|
||||||
"writeable": True,
|
"writeable": True,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert args["value"] == 50
|
assert args["value"] == 50
|
||||||
|
assert args["options"]["transitionDuration"] == "default"
|
||||||
|
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
# Test turning on with brightness and transition
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{
|
||||||
|
"entity_id": BULB_6_MULTI_COLOR_LIGHT_ENTITY,
|
||||||
|
ATTR_BRIGHTNESS: 129,
|
||||||
|
ATTR_TRANSITION: 20,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command.call_args_list) == 1
|
||||||
|
args = client.async_send_command.call_args[0][0]
|
||||||
|
assert args["command"] == "node.set_value"
|
||||||
|
assert args["nodeId"] == 39
|
||||||
|
assert args["valueId"] == {
|
||||||
|
"commandClassName": "Multilevel Switch",
|
||||||
|
"commandClass": 38,
|
||||||
|
"endpoint": 0,
|
||||||
|
"property": "targetValue",
|
||||||
|
"propertyName": "targetValue",
|
||||||
|
"metadata": {
|
||||||
|
"label": "Target value",
|
||||||
|
"max": 99,
|
||||||
|
"min": 0,
|
||||||
|
"type": "number",
|
||||||
|
"readable": True,
|
||||||
|
"writeable": True,
|
||||||
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert args["value"] == 50
|
||||||
|
assert args["options"]["transitionDuration"] == "20s"
|
||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
@ -256,6 +332,23 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
|||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
# Test turning on with rgb color and transition
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{
|
||||||
|
"entity_id": BULB_6_MULTI_COLOR_LIGHT_ENTITY,
|
||||||
|
ATTR_RGB_COLOR: (128, 76, 255),
|
||||||
|
ATTR_TRANSITION: 20,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command.call_args_list) == 6
|
||||||
|
args = client.async_send_command.call_args_list[5][0][0]
|
||||||
|
assert args["options"]["transitionDuration"] == "20s"
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test turning on with color temp
|
# Test turning on with color temp
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light",
|
"light",
|
||||||
@ -377,6 +470,24 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
|||||||
|
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
# Test turning on with color temp and transition
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{
|
||||||
|
"entity_id": BULB_6_MULTI_COLOR_LIGHT_ENTITY,
|
||||||
|
ATTR_COLOR_TEMP: 170,
|
||||||
|
ATTR_TRANSITION: 35,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(client.async_send_command.call_args_list) == 6
|
||||||
|
args = client.async_send_command.call_args_list[5][0][0]
|
||||||
|
assert args["options"]["transitionDuration"] == "35s"
|
||||||
|
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
# Test turning off
|
# Test turning off
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light",
|
"light",
|
||||||
@ -403,6 +514,7 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
|||||||
"readable": True,
|
"readable": True,
|
||||||
"writeable": True,
|
"writeable": True,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert args["value"] == 0
|
assert args["value"] == 0
|
||||||
@ -480,6 +592,7 @@ async def test_rgbw_light(hass, client, zen_31, integration):
|
|||||||
"readable": True,
|
"readable": True,
|
||||||
"writeable": True,
|
"writeable": True,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": ["transitionDuration"],
|
||||||
},
|
},
|
||||||
"value": 59,
|
"value": 59,
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,12 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99,
|
"max": 99
|
||||||
"label": "Target value"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -339,6 +342,23 @@
|
|||||||
"description": "The target value of the Blue color."
|
"description": "The target value of the Blue color."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"endpoint": 0,
|
||||||
|
"commandClass": 51,
|
||||||
|
"commandClassName": "Color Switch",
|
||||||
|
"property": "targetColor",
|
||||||
|
"propertyName": "targetColor",
|
||||||
|
"ccVersion": 1,
|
||||||
|
"metadata": {
|
||||||
|
"type": "any",
|
||||||
|
"readable": true,
|
||||||
|
"writeable": true,
|
||||||
|
"label": "Target Color",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"commandClassName": "Configuration",
|
"commandClassName": "Configuration",
|
||||||
"commandClass": 112,
|
"commandClass": 112,
|
||||||
|
@ -99,6 +99,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
}
|
}
|
||||||
|
15
tests/fixtures/zwave_js/zen_31_state.json
vendored
15
tests/fixtures/zwave_js/zen_31_state.json
vendored
@ -1430,6 +1430,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
},
|
},
|
||||||
@ -1982,6 +1985,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
},
|
},
|
||||||
@ -2100,6 +2106,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
},
|
},
|
||||||
@ -2218,6 +2227,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
},
|
},
|
||||||
@ -2336,6 +2348,9 @@
|
|||||||
"readable": true,
|
"readable": true,
|
||||||
"writeable": true,
|
"writeable": true,
|
||||||
"label": "Target value",
|
"label": "Target value",
|
||||||
|
"valueChangeOptions": [
|
||||||
|
"transitionDuration"
|
||||||
|
],
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 99
|
"max": 99
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user