177 lines
5.5 KiB
Python
177 lines
5.5 KiB
Python
"""Web socket API for OpenZWave."""
|
|
|
|
import logging
|
|
|
|
from openzwavemqtt.const import EVENT_NODE_ADDED, EVENT_NODE_CHANGED
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components import websocket_api
|
|
from homeassistant.core import callback
|
|
|
|
from .const import DOMAIN, MANAGER, OPTIONS
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
TYPE = "type"
|
|
ID = "id"
|
|
OZW_INSTANCE = "ozw_instance"
|
|
NODE_ID = "node_id"
|
|
|
|
|
|
@callback
|
|
def async_register_api(hass):
|
|
"""Register all of our api endpoints."""
|
|
websocket_api.async_register_command(hass, websocket_network_status)
|
|
websocket_api.async_register_command(hass, websocket_node_metadata)
|
|
websocket_api.async_register_command(hass, websocket_node_status)
|
|
websocket_api.async_register_command(hass, websocket_node_statistics)
|
|
websocket_api.async_register_command(hass, websocket_refresh_node_info)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "ozw/network_status",
|
|
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
|
}
|
|
)
|
|
def websocket_network_status(hass, connection, msg):
|
|
"""Get Z-Wave network status."""
|
|
|
|
manager = hass.data[DOMAIN][MANAGER]
|
|
connection.send_result(
|
|
msg[ID],
|
|
{
|
|
"state": manager.get_instance(msg[OZW_INSTANCE]).get_status().status,
|
|
OZW_INSTANCE: msg[OZW_INSTANCE],
|
|
},
|
|
)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "ozw/node_status",
|
|
vol.Required(NODE_ID): vol.Coerce(int),
|
|
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
|
}
|
|
)
|
|
def websocket_node_status(hass, connection, msg):
|
|
"""Get the status for a Z-Wave node."""
|
|
manager = hass.data[DOMAIN][MANAGER]
|
|
node = manager.get_instance(msg[OZW_INSTANCE]).get_node(msg[NODE_ID])
|
|
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,
|
|
OZW_INSTANCE: msg[OZW_INSTANCE],
|
|
},
|
|
)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "ozw/node_metadata",
|
|
vol.Required(NODE_ID): vol.Coerce(int),
|
|
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
|
}
|
|
)
|
|
def websocket_node_metadata(hass, connection, msg):
|
|
"""Get the metadata for a Z-Wave node."""
|
|
manager = hass.data[DOMAIN][MANAGER]
|
|
node = manager.get_instance(msg[OZW_INSTANCE]).get_node(msg[NODE_ID])
|
|
connection.send_result(
|
|
msg[ID],
|
|
{
|
|
"metadata": node.meta_data,
|
|
NODE_ID: node.node_id,
|
|
OZW_INSTANCE: msg[OZW_INSTANCE],
|
|
},
|
|
)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "ozw/node_statistics",
|
|
vol.Required(NODE_ID): vol.Coerce(int),
|
|
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
|
}
|
|
)
|
|
def websocket_node_statistics(hass, connection, msg):
|
|
"""Get the statistics for a Z-Wave node."""
|
|
manager = hass.data[DOMAIN][MANAGER]
|
|
stats = (
|
|
manager.get_instance(msg[OZW_INSTANCE]).get_node(msg[NODE_ID]).get_statistics()
|
|
)
|
|
connection.send_result(
|
|
msg[ID],
|
|
{
|
|
"node_id": msg[NODE_ID],
|
|
"send_count": stats.send_count,
|
|
"sent_failed": stats.sent_failed,
|
|
"retries": stats.retries,
|
|
"last_request_rtt": stats.last_request_rtt,
|
|
"last_response_rtt": stats.last_response_rtt,
|
|
"average_request_rtt": stats.average_request_rtt,
|
|
"average_response_rtt": stats.average_response_rtt,
|
|
"received_packets": stats.received_packets,
|
|
"received_dup_packets": stats.received_dup_packets,
|
|
"received_unsolicited": stats.received_unsolicited,
|
|
OZW_INSTANCE: msg[OZW_INSTANCE],
|
|
},
|
|
)
|
|
|
|
|
|
@websocket_api.require_admin
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "ozw/refresh_node_info",
|
|
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
|
vol.Required(NODE_ID): vol.Coerce(int),
|
|
}
|
|
)
|
|
def websocket_refresh_node_info(hass, connection, msg):
|
|
"""Tell OpenZWave to re-interview a node."""
|
|
|
|
manager = hass.data[DOMAIN][MANAGER]
|
|
options = hass.data[DOMAIN][OPTIONS]
|
|
|
|
@callback
|
|
def forward_node(node):
|
|
"""Forward node events to websocket."""
|
|
if node.node_id != msg[NODE_ID]:
|
|
return
|
|
|
|
forward_data = {
|
|
"type": "node_updated",
|
|
"node_query_stage": node.node_query_stage,
|
|
}
|
|
connection.send_message(websocket_api.event_message(msg["id"], forward_data))
|
|
|
|
@callback
|
|
def async_cleanup() -> None:
|
|
"""Remove signal listeners."""
|
|
for unsub in unsubs:
|
|
unsub()
|
|
|
|
connection.subscriptions[msg["id"]] = async_cleanup
|
|
unsubs = [
|
|
options.listen(EVENT_NODE_CHANGED, forward_node),
|
|
options.listen(EVENT_NODE_ADDED, forward_node),
|
|
]
|
|
|
|
instance = manager.get_instance(msg[OZW_INSTANCE])
|
|
instance.refresh_node(msg[NODE_ID])
|
|
connection.send_result(msg["id"])
|