From c2365b8c0f7e66a53bf1e11720c8c021cb6d02a5 Mon Sep 17 00:00:00 2001 From: Charles Garwood Date: Thu, 27 Aug 2020 14:00:22 -0400 Subject: [PATCH] Add get_nodes command to OZW websocket api (#39317) * Add get_nodes command to OZW websocket api * Fix black * Use constants for get_nodes and get_node * Missed a couple constants --- homeassistant/components/ozw/websocket_api.py | 91 +++++++++++++++---- tests/components/ozw/test_websocket_api.py | 54 ++++++++--- 2 files changed, 115 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/ozw/websocket_api.py b/homeassistant/components/ozw/websocket_api.py index 6e1a725b7a7..a71723ed086 100644 --- a/homeassistant/components/ozw/websocket_api.py +++ b/homeassistant/components/ozw/websocket_api.py @@ -17,11 +17,28 @@ ID = "id" OZW_INSTANCE = "ozw_instance" NODE_ID = "node_id" +ATTR_NODE_QUERY_STAGE = "node_query_stage" +ATTR_IS_ZWAVE_PLUS = "is_zwave_plus" +ATTR_IS_AWAKE = "is_awake" +ATTR_IS_FAILED = "is_failed" +ATTR_NODE_BAUD_RATE = "node_baud_rate" +ATTR_IS_BEAMING = "is_beaming" +ATTR_IS_FLIRS = "is_flirs" +ATTR_IS_ROUTING = "is_routing" +ATTR_IS_SECURITYV1 = "is_securityv1" +ATTR_NODE_BASIC_STRING = "node_basic_string" +ATTR_NODE_GENERIC_STRING = "node_generic_string" +ATTR_NODE_SPECIFIC_STRING = "node_specific_string" +ATTR_NODE_MANUFACTURER_NAME = "node_manufacturer_name" +ATTR_NODE_PRODUCT_NAME = "node_product_name" +ATTR_NEIGHBORS = "neighbors" + @callback def async_register_api(hass): """Register all of our api endpoints.""" websocket_api.async_register_command(hass, websocket_get_instances) + websocket_api.async_register_command(hass, websocket_get_nodes) websocket_api.async_register_command(hass, websocket_network_status) websocket_api.async_register_command(hass, websocket_network_statistics) websocket_api.async_register_command(hass, websocket_node_metadata) @@ -45,6 +62,46 @@ def websocket_get_instances(hass, connection, msg): ) +@websocket_api.websocket_command( + { + vol.Required(TYPE): "ozw/get_nodes", + vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int), + } +) +def websocket_get_nodes(hass, connection, msg): + """Get a list of nodes for an OZW instance.""" + manager = hass.data[DOMAIN][MANAGER] + nodes = [] + + for node in manager.get_instance(msg[OZW_INSTANCE]).collections["node"]: + nodes.append( + { + ATTR_NODE_QUERY_STAGE: node.node_query_stage, + NODE_ID: node.node_id, + ATTR_IS_ZWAVE_PLUS: node.is_zwave_plus, + ATTR_IS_AWAKE: node.is_awake, + ATTR_IS_FAILED: node.is_failed, + ATTR_NODE_BAUD_RATE: node.node_baud_rate, + ATTR_IS_BEAMING: node.is_beaming, + ATTR_IS_FLIRS: node.is_flirs, + ATTR_IS_ROUTING: node.is_routing, + ATTR_IS_SECURITYV1: node.is_securityv1, + ATTR_NODE_BASIC_STRING: node.node_basic_string, + ATTR_NODE_GENERIC_STRING: node.node_generic_string, + ATTR_NODE_SPECIFIC_STRING: node.node_specific_string, + ATTR_NODE_MANUFACTURER_NAME: node.node_manufacturer_name, + ATTR_NODE_PRODUCT_NAME: node.node_product_name, + ATTR_NEIGHBORS: node.neighbors, + OZW_INSTANCE: msg[OZW_INSTANCE], + } + ) + + connection.send_result( + msg[ID], + nodes, + ) + + @websocket_api.websocket_command( { vol.Required(TYPE): "ozw/network_status", @@ -96,20 +153,22 @@ def websocket_node_status(hass, connection, msg): connection.send_result( msg[ID], { - "node_query_stage": node.node_query_stage, - "node_id": node.node_id, - "is_zwave_plus": node.is_zwave_plus, - "is_awake": node.is_awake, - "is_failed": node.is_failed, - "node_baud_rate": node.node_baud_rate, - "is_beaming": node.is_beaming, - "is_flirs": node.is_flirs, - "is_routing": node.is_routing, - "is_securityv1": node.is_securityv1, - "node_basic_string": node.node_basic_string, - "node_generic_string": node.node_generic_string, - "node_specific_string": node.node_specific_string, - "neighbors": node.neighbors, + ATTR_NODE_QUERY_STAGE: node.node_query_stage, + NODE_ID: node.node_id, + ATTR_IS_ZWAVE_PLUS: node.is_zwave_plus, + ATTR_IS_AWAKE: node.is_awake, + ATTR_IS_FAILED: node.is_failed, + ATTR_NODE_BAUD_RATE: node.node_baud_rate, + ATTR_IS_BEAMING: node.is_beaming, + ATTR_IS_FLIRS: node.is_flirs, + ATTR_IS_ROUTING: node.is_routing, + ATTR_IS_SECURITYV1: node.is_securityv1, + ATTR_NODE_BASIC_STRING: node.node_basic_string, + ATTR_NODE_GENERIC_STRING: node.node_generic_string, + ATTR_NODE_SPECIFIC_STRING: node.node_specific_string, + ATTR_NODE_MANUFACTURER_NAME: node.node_manufacturer_name, + ATTR_NODE_PRODUCT_NAME: node.node_product_name, + ATTR_NEIGHBORS: node.neighbors, OZW_INSTANCE: msg[OZW_INSTANCE], }, ) @@ -152,7 +211,7 @@ def websocket_node_statistics(hass, connection, msg): connection.send_result( msg[ID], { - "node_id": msg[NODE_ID], + NODE_ID: msg[NODE_ID], "send_count": stats.send_count, "sent_failed": stats.sent_failed, "retries": stats.retries, @@ -190,7 +249,7 @@ def websocket_refresh_node_info(hass, connection, msg): forward_data = { "type": "node_updated", - "node_query_stage": node.node_query_stage, + ATTR_NODE_QUERY_STAGE: node.node_query_stage, } connection.send_message(websocket_api.event_message(msg["id"], forward_data)) diff --git a/tests/components/ozw/test_websocket_api.py b/tests/components/ozw/test_websocket_api.py index 7affe62cfb4..5a8e11a77c8 100644 --- a/tests/components/ozw/test_websocket_api.py +++ b/tests/components/ozw/test_websocket_api.py @@ -1,6 +1,24 @@ """Test OpenZWave Websocket API.""" -from homeassistant.components.ozw.websocket_api import ID, NODE_ID, OZW_INSTANCE, TYPE +from homeassistant.components.ozw.websocket_api import ( + ATTR_IS_AWAKE, + ATTR_IS_BEAMING, + ATTR_IS_FAILED, + ATTR_IS_FLIRS, + ATTR_IS_ROUTING, + ATTR_IS_SECURITYV1, + ATTR_IS_ZWAVE_PLUS, + ATTR_NEIGHBORS, + ATTR_NODE_BASIC_STRING, + ATTR_NODE_BAUD_RATE, + ATTR_NODE_GENERIC_STRING, + ATTR_NODE_QUERY_STAGE, + ATTR_NODE_SPECIFIC_STRING, + ID, + NODE_ID, + OZW_INSTANCE, + TYPE, +) from .common import MQTTMessage, setup_ozw @@ -36,19 +54,19 @@ async def test_websocket_api(hass, generic_data, hass_ws_client): assert result[OZW_INSTANCE] == 1 assert result[NODE_ID] == 32 - assert result["node_query_stage"] == "Complete" - assert result["is_zwave_plus"] - assert result["is_awake"] - assert not result["is_failed"] - assert result["node_baud_rate"] == 100000 - assert result["is_beaming"] - assert not result["is_flirs"] - assert result["is_routing"] - assert not result["is_securityv1"] - assert result["node_basic_string"] == "Routing Slave" - assert result["node_generic_string"] == "Binary Switch" - assert result["node_specific_string"] == "Binary Power Switch" - assert result["neighbors"] == [1, 33, 36, 37, 39] + assert result[ATTR_NODE_QUERY_STAGE] == "Complete" + assert result[ATTR_IS_ZWAVE_PLUS] + assert result[ATTR_IS_AWAKE] + assert not result[ATTR_IS_FAILED] + assert result[ATTR_NODE_BAUD_RATE] == 100000 + assert result[ATTR_IS_BEAMING] + assert not result[ATTR_IS_FLIRS] + assert result[ATTR_IS_ROUTING] + assert not result[ATTR_IS_SECURITYV1] + assert result[ATTR_NODE_BASIC_STRING] == "Routing Slave" + assert result[ATTR_NODE_GENERIC_STRING] == "Binary Switch" + assert result[ATTR_NODE_SPECIFIC_STRING] == "Binary Power Switch" + assert result[ATTR_NEIGHBORS] == [1, 33, 36, 37, 39] # Test node statistics await client.send_json({ID: 7, TYPE: "ozw/node_statistics", NODE_ID: 39}) @@ -82,6 +100,14 @@ async def test_websocket_api(hass, generic_data, hass_ws_client): assert result[OZW_INSTANCE] == 1 assert result["node_count"] == 5 + # Test get nodes + await client.send_json({ID: 10, TYPE: "ozw/get_nodes"}) + msg = await client.receive_json() + result = msg["result"] + assert len(result) == 5 + assert result[2][ATTR_IS_AWAKE] + assert not result[1][ATTR_IS_FAILED] + async def test_refresh_node(hass, generic_data, sent_messages, hass_ws_client): """Test the ozw refresh node api."""