Add zwave_js set_config_parameter WS API command (#46910)
* add WS API command * handle error scenario better * fixes and remove duplicate catch * make elif statement more compact * fix conflict * switch to str(err)
This commit is contained in:
parent
580d25c622
commit
1cecf229b9
2 changed files with 182 additions and 1 deletions
|
@ -7,11 +7,18 @@ from aiohttp import hdrs, web, web_exceptions
|
|||
import voluptuous as vol
|
||||
from zwave_js_server import dump
|
||||
from zwave_js_server.const import LogLevel
|
||||
from zwave_js_server.exceptions import InvalidNewValue, NotFoundError, SetValueFailed
|
||||
from zwave_js_server.model.log_config import LogConfig
|
||||
from zwave_js_server.util.node import async_set_config_parameter
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.http.view import HomeAssistantView
|
||||
from homeassistant.components.websocket_api.connection import ActiveConnection
|
||||
from homeassistant.components.websocket_api.const import (
|
||||
ERR_NOT_FOUND,
|
||||
ERR_NOT_SUPPORTED,
|
||||
ERR_UNKNOWN_ERROR,
|
||||
)
|
||||
from homeassistant.const import CONF_URL
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
@ -26,6 +33,9 @@ ID = "id"
|
|||
ENTRY_ID = "entry_id"
|
||||
NODE_ID = "node_id"
|
||||
TYPE = "type"
|
||||
PROPERTY = "property"
|
||||
PROPERTY_KEY = "property_key"
|
||||
VALUE = "value"
|
||||
|
||||
# constants for log config commands
|
||||
CONFIG = "config"
|
||||
|
@ -45,9 +55,10 @@ def async_register_api(hass: HomeAssistant) -> None:
|
|||
websocket_api.async_register_command(hass, websocket_stop_inclusion)
|
||||
websocket_api.async_register_command(hass, websocket_remove_node)
|
||||
websocket_api.async_register_command(hass, websocket_stop_exclusion)
|
||||
websocket_api.async_register_command(hass, websocket_get_config_parameters)
|
||||
websocket_api.async_register_command(hass, websocket_update_log_config)
|
||||
websocket_api.async_register_command(hass, websocket_get_log_config)
|
||||
websocket_api.async_register_command(hass, websocket_get_config_parameters)
|
||||
websocket_api.async_register_command(hass, websocket_set_config_parameter)
|
||||
hass.http.register_view(DumpView) # type: ignore
|
||||
|
||||
|
||||
|
@ -280,6 +291,53 @@ async def websocket_remove_node(
|
|||
)
|
||||
|
||||
|
||||
@websocket_api.require_admin # type:ignore
|
||||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "zwave_js/set_config_parameter",
|
||||
vol.Required(ENTRY_ID): str,
|
||||
vol.Required(NODE_ID): int,
|
||||
vol.Required(PROPERTY): int,
|
||||
vol.Optional(PROPERTY_KEY): int,
|
||||
vol.Required(VALUE): int,
|
||||
}
|
||||
)
|
||||
async def websocket_set_config_parameter(
|
||||
hass: HomeAssistant, connection: ActiveConnection, msg: dict
|
||||
) -> None:
|
||||
"""Set a config parameter value for a Z-Wave node."""
|
||||
entry_id = msg[ENTRY_ID]
|
||||
node_id = msg[NODE_ID]
|
||||
property_ = msg[PROPERTY]
|
||||
property_key = msg.get(PROPERTY_KEY)
|
||||
value = msg[VALUE]
|
||||
client = hass.data[DOMAIN][entry_id][DATA_CLIENT]
|
||||
node = client.driver.controller.nodes[node_id]
|
||||
try:
|
||||
result = await async_set_config_parameter(
|
||||
node, value, property_, property_key=property_key
|
||||
)
|
||||
except (InvalidNewValue, NotFoundError, NotImplementedError, SetValueFailed) as err:
|
||||
code = ERR_UNKNOWN_ERROR
|
||||
if isinstance(err, NotFoundError):
|
||||
code = ERR_NOT_FOUND
|
||||
elif isinstance(err, (InvalidNewValue, NotImplementedError)):
|
||||
code = ERR_NOT_SUPPORTED
|
||||
|
||||
connection.send_error(
|
||||
msg[ID],
|
||||
code,
|
||||
str(err),
|
||||
)
|
||||
return
|
||||
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
str(result),
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ from unittest.mock import patch
|
|||
|
||||
from zwave_js_server.const import LogLevel
|
||||
from zwave_js_server.event import Event
|
||||
from zwave_js_server.exceptions import InvalidNewValue, NotFoundError, SetValueFailed
|
||||
|
||||
from homeassistant.components.zwave_js.api import (
|
||||
CONFIG,
|
||||
|
@ -15,7 +16,10 @@ from homeassistant.components.zwave_js.api import (
|
|||
LEVEL,
|
||||
LOG_TO_FILE,
|
||||
NODE_ID,
|
||||
PROPERTY,
|
||||
PROPERTY_KEY,
|
||||
TYPE,
|
||||
VALUE,
|
||||
)
|
||||
from homeassistant.components.zwave_js.const import DOMAIN
|
||||
from homeassistant.helpers.device_registry import async_get_registry
|
||||
|
@ -186,6 +190,125 @@ async def test_remove_node(
|
|||
assert device is None
|
||||
|
||||
|
||||
async def test_set_config_parameter(
|
||||
hass, client, hass_ws_client, multisensor_6, integration
|
||||
):
|
||||
"""Test the set_config_parameter service."""
|
||||
entry = integration
|
||||
ws_client = await hass_ws_client(hass)
|
||||
|
||||
client.async_send_command.return_value = {"success": True}
|
||||
|
||||
await ws_client.send_json(
|
||||
{
|
||||
ID: 1,
|
||||
TYPE: "zwave_js/set_config_parameter",
|
||||
ENTRY_ID: entry.entry_id,
|
||||
NODE_ID: 52,
|
||||
PROPERTY: 102,
|
||||
PROPERTY_KEY: 1,
|
||||
VALUE: 1,
|
||||
}
|
||||
)
|
||||
|
||||
msg = await ws_client.receive_json()
|
||||
assert msg["result"]
|
||||
|
||||
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"] == 52
|
||||
assert args["valueId"] == {
|
||||
"commandClassName": "Configuration",
|
||||
"commandClass": 112,
|
||||
"endpoint": 0,
|
||||
"property": 102,
|
||||
"propertyName": "Group 2: Send battery reports",
|
||||
"propertyKey": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"valueSize": 4,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"default": 1,
|
||||
"format": 0,
|
||||
"allowManualEntry": True,
|
||||
"label": "Group 2: Send battery reports",
|
||||
"description": "Include battery information in periodic reports to Group 2",
|
||||
"isFromConfig": True,
|
||||
},
|
||||
"value": 0,
|
||||
}
|
||||
assert args["value"] == 1
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.zwave_js.api.async_set_config_parameter",
|
||||
) as set_param_mock:
|
||||
set_param_mock.side_effect = InvalidNewValue("test")
|
||||
await ws_client.send_json(
|
||||
{
|
||||
ID: 2,
|
||||
TYPE: "zwave_js/set_config_parameter",
|
||||
ENTRY_ID: entry.entry_id,
|
||||
NODE_ID: 52,
|
||||
PROPERTY: 102,
|
||||
PROPERTY_KEY: 1,
|
||||
VALUE: 1,
|
||||
}
|
||||
)
|
||||
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 0
|
||||
assert not msg["success"]
|
||||
assert msg["error"]["code"] == "not_supported"
|
||||
assert msg["error"]["message"] == "test"
|
||||
|
||||
set_param_mock.side_effect = NotFoundError("test")
|
||||
await ws_client.send_json(
|
||||
{
|
||||
ID: 3,
|
||||
TYPE: "zwave_js/set_config_parameter",
|
||||
ENTRY_ID: entry.entry_id,
|
||||
NODE_ID: 52,
|
||||
PROPERTY: 102,
|
||||
PROPERTY_KEY: 1,
|
||||
VALUE: 1,
|
||||
}
|
||||
)
|
||||
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 0
|
||||
assert not msg["success"]
|
||||
assert msg["error"]["code"] == "not_found"
|
||||
assert msg["error"]["message"] == "test"
|
||||
|
||||
set_param_mock.side_effect = SetValueFailed("test")
|
||||
await ws_client.send_json(
|
||||
{
|
||||
ID: 4,
|
||||
TYPE: "zwave_js/set_config_parameter",
|
||||
ENTRY_ID: entry.entry_id,
|
||||
NODE_ID: 52,
|
||||
PROPERTY: 102,
|
||||
PROPERTY_KEY: 1,
|
||||
VALUE: 1,
|
||||
}
|
||||
)
|
||||
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 0
|
||||
assert not msg["success"]
|
||||
assert msg["error"]["code"] == "unknown_error"
|
||||
assert msg["error"]["message"] == "test"
|
||||
|
||||
|
||||
async def test_dump_view(integration, hass_client):
|
||||
"""Test the HTTP dump view."""
|
||||
client = await hass_client()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue