diff --git a/homeassistant/components/zwave_js/services.py b/homeassistant/components/zwave_js/services.py index 48719063376..c2ebe965fdd 100644 --- a/homeassistant/components/zwave_js/services.py +++ b/homeassistant/components/zwave_js/services.py @@ -67,22 +67,26 @@ class ZWaveServices: const.DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, self.async_set_config_parameter, - schema=vol.All( - { - vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), - vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Any( - vol.Coerce(int), cv.string - ), - vol.Optional(const.ATTR_CONFIG_PARAMETER_BITMASK): vol.Any( - vol.Coerce(int), BITMASK_SCHEMA - ), - vol.Required(const.ATTR_CONFIG_VALUE): vol.Any( - vol.Coerce(int), cv.string - ), - }, - cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), - parameter_name_does_not_need_bitmask, + schema=vol.Schema( + vol.All( + { + vol.Optional(ATTR_DEVICE_ID): vol.All( + cv.ensure_list, [cv.string] + ), + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Any( + vol.Coerce(int), cv.string + ), + vol.Optional(const.ATTR_CONFIG_PARAMETER_BITMASK): vol.Any( + vol.Coerce(int), BITMASK_SCHEMA + ), + vol.Required(const.ATTR_CONFIG_VALUE): vol.Any( + vol.Coerce(int), cv.string + ), + }, + cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), + parameter_name_does_not_need_bitmask, + ), ), ) @@ -90,21 +94,25 @@ class ZWaveServices: const.DOMAIN, const.SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS, self.async_bulk_set_partial_config_parameters, - schema=vol.All( - { - vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), - vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Coerce(int), - vol.Required(const.ATTR_CONFIG_VALUE): vol.Any( - vol.Coerce(int), - { - vol.Any( - vol.Coerce(int), BITMASK_SCHEMA, cv.string - ): vol.Any(vol.Coerce(int), cv.string) - }, - ), - }, - cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), + schema=vol.Schema( + vol.All( + { + vol.Optional(ATTR_DEVICE_ID): vol.All( + cv.ensure_list, [cv.string] + ), + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Coerce(int), + vol.Required(const.ATTR_CONFIG_VALUE): vol.Any( + vol.Coerce(int), + { + vol.Any( + vol.Coerce(int), BITMASK_SCHEMA, cv.string + ): vol.Any(vol.Coerce(int), cv.string) + }, + ), + }, + cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), + ), ), ) @@ -125,21 +133,27 @@ class ZWaveServices: const.SERVICE_SET_VALUE, self.async_set_value, schema=vol.Schema( - { - vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), - vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(const.ATTR_COMMAND_CLASS): vol.Coerce(int), - vol.Required(const.ATTR_PROPERTY): vol.Any(vol.Coerce(int), str), - vol.Optional(const.ATTR_PROPERTY_KEY): vol.Any( - vol.Coerce(int), str - ), - vol.Optional(const.ATTR_ENDPOINT): vol.Coerce(int), - vol.Required(const.ATTR_VALUE): vol.Any( - bool, vol.Coerce(int), vol.Coerce(float), cv.string - ), - vol.Optional(const.ATTR_WAIT_FOR_RESULT): vol.Coerce(bool), - }, - cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), + vol.All( + { + vol.Optional(ATTR_DEVICE_ID): vol.All( + cv.ensure_list, [cv.string] + ), + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(const.ATTR_COMMAND_CLASS): vol.Coerce(int), + vol.Required(const.ATTR_PROPERTY): vol.Any( + vol.Coerce(int), str + ), + vol.Optional(const.ATTR_PROPERTY_KEY): vol.Any( + vol.Coerce(int), str + ), + vol.Optional(const.ATTR_ENDPOINT): vol.Coerce(int), + vol.Required(const.ATTR_VALUE): vol.Any( + bool, vol.Coerce(int), vol.Coerce(float), cv.string + ), + vol.Optional(const.ATTR_WAIT_FOR_RESULT): vol.Coerce(bool), + }, + cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID), + ), ), ) diff --git a/tests/components/zwave_js/test_services.py b/tests/components/zwave_js/test_services.py index 956361d3953..3c08c49a36f 100644 --- a/tests/components/zwave_js/test_services.py +++ b/tests/components/zwave_js/test_services.py @@ -599,6 +599,7 @@ async def test_set_value(hass, client, climate_danfoss_lc_13, integration): ) 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"] == 5 @@ -619,3 +620,17 @@ async def test_set_value(hass, client, climate_danfoss_lc_13, integration): "value": 0, } assert args["value"] == 2 + + # Test missing device and entities keys + with pytest.raises(vol.MultipleInvalid): + await hass.services.async_call( + DOMAIN, + SERVICE_SET_VALUE, + { + ATTR_COMMAND_CLASS: 117, + ATTR_PROPERTY: "local", + ATTR_VALUE: 2, + ATTR_WAIT_FOR_RESULT: True, + }, + blocking=True, + )