Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional data to zwave_js device statistics WS API #72520

Merged
merged 6 commits into from
May 26, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions homeassistant/components/zwave_js/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
from .helpers import (
async_enable_statistics,
async_get_node_from_device_id,
get_device_id,
update_data_collection_preference,
)

Expand Down Expand Up @@ -2110,15 +2111,42 @@ def forward_stats(event: dict) -> None:
)


def _get_node_statistics_dict(statistics: NodeStatistics) -> dict[str, int]:
def _get_node_statistics_dict(
hass: HomeAssistant, statistics: NodeStatistics
) -> dict[str, int]:
raman325 marked this conversation as resolved.
Show resolved Hide resolved
"""Get dictionary of node statistics."""
return {
dev_reg = dr.async_get(hass)

def _convert_node_to_device_id(node: Node) -> str:
"""Convert a node to a device id."""
driver = node.client.driver
assert driver
device = dev_reg.async_get_device({get_device_id(driver, node)})
assert device
return device.id

data: dict = {
"commands_tx": statistics.commands_tx,
"commands_rx": statistics.commands_rx,
"commands_dropped_tx": statistics.commands_dropped_tx,
"commands_dropped_rx": statistics.commands_dropped_rx,
"timeout_response": statistics.timeout_response,
"rtt": statistics.rtt,
"rssi": statistics.rssi,
"lwr": statistics.lwr.as_dict() if statistics.lwr else None,
"nlwr": statistics.nlwr.as_dict() if statistics.nlwr else None,
}
for key in ("lwr", "nlwr"):
if not data[key]:
continue
for key_2 in ("repeaters", "route_failed_between"):
if not data[key][key_2]:
continue
data[key][key_2] = [
_convert_node_to_device_id(node) for node in data[key][key_2]
]

return data


@websocket_api.require_admin
Expand Down Expand Up @@ -2154,7 +2182,7 @@ def forward_stats(event: dict) -> None:
"event": event["event"],
"source": "node",
"node_id": node.node_id,
**_get_node_statistics_dict(statistics),
**_get_node_statistics_dict(hass, statistics),
},
)
)
Expand All @@ -2170,7 +2198,7 @@ def forward_stats(event: dict) -> None:
"event": "statistics updated",
"source": "node",
"nodeId": node.node_id,
**_get_node_statistics_dict(node.statistics),
**_get_node_statistics_dict(hass, node.statistics),
},
)
)
80 changes: 68 additions & 12 deletions tests/components/zwave_js/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3768,18 +3768,26 @@ async def test_subscribe_controller_statistics(


async def test_subscribe_node_statistics(
hass, multisensor_6, integration, client, hass_ws_client
hass,
multisensor_6,
wallmote_central_scene,
zen_31,
integration,
client,
hass_ws_client,
):
"""Test the subscribe_node_statistics command."""
entry = integration
ws_client = await hass_ws_client(hass)
device = get_device(hass, multisensor_6)
multisensor_6_device = get_device(hass, multisensor_6)
zen_31_device = get_device(hass, zen_31)
wallmote_central_scene_device = get_device(hass, wallmote_central_scene)

await ws_client.send_json(
{
ID: 1,
TYPE: "zwave_js/subscribe_node_statistics",
DEVICE_ID: device.id,
DEVICE_ID: multisensor_6_device.id,
}
)

Expand All @@ -3797,6 +3805,10 @@ async def test_subscribe_node_statistics(
"commands_dropped_tx": 0,
"commands_dropped_rx": 0,
"timeout_response": 0,
"rtt": None,
"rssi": None,
"lwr": None,
"nlwr": None,
}

# Fire statistics updated
Expand All @@ -3808,10 +3820,32 @@ async def test_subscribe_node_statistics(
"nodeId": multisensor_6.node_id,
"statistics": {
"commandsTX": 1,
"commandsRX": 1,
"commandsDroppedTX": 1,
"commandsDroppedRX": 1,
"timeoutResponse": 1,
"commandsRX": 2,
"commandsDroppedTX": 3,
"commandsDroppedRX": 4,
"timeoutResponse": 5,
"rtt": 6,
"rssi": 7,
"lwr": {
"protocolDataRate": 1,
"rssi": 1,
"repeaters": [wallmote_central_scene.node_id],
"repeaterRSSI": [1],
"routeFailedBetween": [
zen_31.node_id,
multisensor_6.node_id,
],
},
"nlwr": {
"protocolDataRate": 2,
"rssi": 2,
"repeaters": [],
"repeaterRSSI": [127],
"routeFailedBetween": [
multisensor_6.node_id,
zen_31.node_id,
],
},
},
},
)
Expand All @@ -3822,10 +3856,32 @@ async def test_subscribe_node_statistics(
"source": "node",
"node_id": multisensor_6.node_id,
"commands_tx": 1,
"commands_rx": 1,
"commands_dropped_tx": 1,
"commands_dropped_rx": 1,
"timeout_response": 1,
"commands_rx": 2,
"commands_dropped_tx": 3,
"commands_dropped_rx": 4,
"timeout_response": 5,
"rtt": 6,
"rssi": 7,
"lwr": {
"protocol_data_rate": 1,
"rssi": 1,
"repeaters": [wallmote_central_scene_device.id],
"repeater_rssi": [1],
"route_failed_between": [
zen_31_device.id,
multisensor_6_device.id,
],
},
"nlwr": {
"protocol_data_rate": 2,
"rssi": 2,
"repeaters": [],
"repeater_rssi": [127],
"route_failed_between": [
multisensor_6_device.id,
zen_31_device.id,
],
},
}

# Test sending command with improper entry ID fails
Expand All @@ -3849,7 +3905,7 @@ async def test_subscribe_node_statistics(
{
ID: 4,
TYPE: "zwave_js/subscribe_node_statistics",
DEVICE_ID: device.id,
DEVICE_ID: multisensor_6_device.id,
}
)
msg = await ws_client.receive_json()
Expand Down