diff --git a/homeassistant/components/zwave_js/const.py b/homeassistant/components/zwave_js/const.py index d1b9ecaaa15..4687110e208 100644 --- a/homeassistant/components/zwave_js/const.py +++ b/homeassistant/components/zwave_js/const.py @@ -43,6 +43,7 @@ ATTR_EVENT_TYPE = "event_type" ATTR_EVENT_DATA = "event_data" ATTR_DATA_TYPE = "data_type" ATTR_WAIT_FOR_RESULT = "wait_for_result" +ATTR_OPTIONS = "options" ATTR_NODE = "node" ATTR_ZWAVE_VALUE = "zwave_value" diff --git a/homeassistant/components/zwave_js/services.py b/homeassistant/components/zwave_js/services.py index 00f991433f4..e09b0fb0c5e 100644 --- a/homeassistant/components/zwave_js/services.py +++ b/homeassistant/components/zwave_js/services.py @@ -254,6 +254,7 @@ class ZWaveServices: vol.Optional(const.ATTR_ENDPOINT): vol.Coerce(int), vol.Required(const.ATTR_VALUE): VALUE_SCHEMA, vol.Optional(const.ATTR_WAIT_FOR_RESULT): cv.boolean, + vol.Optional(const.ATTR_OPTIONS): {cv.string: VALUE_SCHEMA}, }, cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), get_nodes_from_service_data, @@ -381,6 +382,7 @@ class ZWaveServices: endpoint = service.data.get(const.ATTR_ENDPOINT) new_value = service.data[const.ATTR_VALUE] wait_for_result = service.data.get(const.ATTR_WAIT_FOR_RESULT) + options = service.data.get(const.ATTR_OPTIONS) for node in nodes: success = await node.async_set_value( @@ -392,6 +394,7 @@ class ZWaveServices: property_key=property_key, ), new_value, + options=options, wait_for_result=wait_for_result, ) diff --git a/homeassistant/components/zwave_js/services.yaml b/homeassistant/components/zwave_js/services.yaml index c24fa4694cf..7d88f5f7830 100644 --- a/homeassistant/components/zwave_js/services.yaml +++ b/homeassistant/components/zwave_js/services.yaml @@ -154,6 +154,12 @@ set_value: required: true selector: object: + options: + name: Options + description: Set value options. Refer to the Z-Wave JS documentation for more information on what options can be set. + required: false + selector: + object: wait_for_result: name: Wait for result? description: Whether or not to wait for a response from the node. If not included in the payload, the integration will decide whether to wait or not. If set to `true`, note that the service call can take a while if setting a value on an asleep battery device. diff --git a/tests/components/zwave_js/test_services.py b/tests/components/zwave_js/test_services.py index 25373bcb026..92ead72e2ad 100644 --- a/tests/components/zwave_js/test_services.py +++ b/tests/components/zwave_js/test_services.py @@ -11,6 +11,7 @@ from homeassistant.components.zwave_js.const import ( ATTR_CONFIG_PARAMETER, ATTR_CONFIG_PARAMETER_BITMASK, ATTR_CONFIG_VALUE, + ATTR_OPTIONS, ATTR_PROPERTY, ATTR_REFRESH_ALL_VALUES, ATTR_VALUE, @@ -31,6 +32,7 @@ from homeassistant.helpers.device_registry import ( from homeassistant.helpers.entity_registry import async_get as async_get_ent_reg from .common import ( + AEON_SMART_SWITCH_LIGHT_ENTITY, AIR_TEMPERATURE_SENSOR, CLIMATE_DANFOSS_LC13_ENTITY, CLIMATE_RADIO_THERMOSTAT_ENTITY, @@ -759,6 +761,46 @@ async def test_set_value(hass, client, climate_danfoss_lc_13, integration): ) +async def test_set_value_options(hass, client, aeon_smart_switch_6, integration): + """Test set_value service with options.""" + await hass.services.async_call( + DOMAIN, + SERVICE_SET_VALUE, + { + ATTR_ENTITY_ID: AEON_SMART_SWITCH_LIGHT_ENTITY, + ATTR_COMMAND_CLASS: 37, + ATTR_PROPERTY: "targetValue", + ATTR_VALUE: 2, + ATTR_OPTIONS: {"transitionDuration": 1}, + }, + 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"] == aeon_smart_switch_6.node_id + assert args["valueId"] == { + "endpoint": 0, + "commandClass": 37, + "commandClassName": "Binary Switch", + "property": "targetValue", + "propertyName": "targetValue", + "ccVersion": 1, + "metadata": { + "type": "boolean", + "readable": True, + "writeable": True, + "label": "Target value", + "valueChangeOptions": ["transitionDuration"], + }, + } + assert args["value"] == 2 + assert args["options"] == {"transitionDuration": 1} + + client.async_send_command.reset_mock() + + async def test_multicast_set_value( hass, client, diff --git a/tests/fixtures/zwave_js/aeon_smart_switch_6_state.json b/tests/fixtures/zwave_js/aeon_smart_switch_6_state.json index 36db78faace..c8d8f878c0b 100644 --- a/tests/fixtures/zwave_js/aeon_smart_switch_6_state.json +++ b/tests/fixtures/zwave_js/aeon_smart_switch_6_state.json @@ -81,7 +81,8 @@ "type": "boolean", "readable": true, "writeable": true, - "label": "Target value" + "label": "Target value", + "valueChangeOptions": ["transitionDuration"] } }, {