mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 09:47:52 +00:00
Resume adding Z-Wave device if the page is refreshed (#129081)
* ZwaveJS: Resume adding a device if the page is refreshed * add test * address PR comments
This commit is contained in:
parent
0acb95bbd5
commit
47bf0ebb47
@ -13,8 +13,10 @@ from zwave_js_server.client import Client
|
||||
from zwave_js_server.const import (
|
||||
CommandClass,
|
||||
ExclusionStrategy,
|
||||
InclusionState,
|
||||
InclusionStrategy,
|
||||
LogLevel,
|
||||
NodeStatus,
|
||||
Protocols,
|
||||
ProvisioningEntryStatus,
|
||||
QRCodeVersion,
|
||||
@ -693,6 +695,30 @@ async def websocket_add_node(
|
||||
)
|
||||
)
|
||||
|
||||
@callback
|
||||
def forward_node_added(
|
||||
node: Node, low_security: bool, low_security_reason: str | None
|
||||
) -> None:
|
||||
interview_unsubs = [
|
||||
node.on("interview started", forward_event),
|
||||
node.on("interview completed", forward_event),
|
||||
node.on("interview stage completed", forward_stage),
|
||||
node.on("interview failed", forward_event),
|
||||
]
|
||||
unsubs.extend(interview_unsubs)
|
||||
node_details = {
|
||||
"node_id": node.node_id,
|
||||
"status": node.status,
|
||||
"ready": node.ready,
|
||||
"low_security": low_security,
|
||||
"low_security_reason": low_security_reason,
|
||||
}
|
||||
connection.send_message(
|
||||
websocket_api.event_message(
|
||||
msg[ID], {"event": "node added", "node": node_details}
|
||||
)
|
||||
)
|
||||
|
||||
@callback
|
||||
def forward_requested_grant(event: dict) -> None:
|
||||
connection.send_message(
|
||||
@ -727,25 +753,10 @@ async def websocket_add_node(
|
||||
|
||||
@callback
|
||||
def node_added(event: dict) -> None:
|
||||
node = event["node"]
|
||||
interview_unsubs = [
|
||||
node.on("interview started", forward_event),
|
||||
node.on("interview completed", forward_event),
|
||||
node.on("interview stage completed", forward_stage),
|
||||
node.on("interview failed", forward_event),
|
||||
]
|
||||
unsubs.extend(interview_unsubs)
|
||||
node_details = {
|
||||
"node_id": node.node_id,
|
||||
"status": node.status,
|
||||
"ready": node.ready,
|
||||
"low_security": event["result"].get("lowSecurity", False),
|
||||
"low_security_reason": event["result"].get("lowSecurityReason"),
|
||||
}
|
||||
connection.send_message(
|
||||
websocket_api.event_message(
|
||||
msg[ID], {"event": "node added", "node": node_details}
|
||||
)
|
||||
forward_node_added(
|
||||
event["node"],
|
||||
event["result"].get("lowSecurity", False),
|
||||
event["result"].get("lowSecurityReason"),
|
||||
)
|
||||
|
||||
@callback
|
||||
@ -777,25 +788,39 @@ async def websocket_add_node(
|
||||
]
|
||||
msg[DATA_UNSUBSCRIBE] = unsubs
|
||||
|
||||
try:
|
||||
result = await controller.async_begin_inclusion(
|
||||
INCLUSION_STRATEGY_NOT_SMART_START[inclusion_strategy.value],
|
||||
force_security=force_security,
|
||||
provisioning=provisioning,
|
||||
dsk=dsk,
|
||||
)
|
||||
except ValueError as err:
|
||||
connection.send_error(
|
||||
if controller.inclusion_state == InclusionState.INCLUDING:
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
ERR_INVALID_FORMAT,
|
||||
err.args[0],
|
||||
True, # Inclusion is already in progress
|
||||
)
|
||||
return
|
||||
# Check for nodes that have been added but not fully included
|
||||
for node in controller.nodes.values():
|
||||
if node.status != NodeStatus.DEAD and not node.ready:
|
||||
forward_node_added(
|
||||
node,
|
||||
not node.is_secure,
|
||||
None,
|
||||
)
|
||||
else:
|
||||
try:
|
||||
result = await controller.async_begin_inclusion(
|
||||
INCLUSION_STRATEGY_NOT_SMART_START[inclusion_strategy.value],
|
||||
force_security=force_security,
|
||||
provisioning=provisioning,
|
||||
dsk=dsk,
|
||||
)
|
||||
except ValueError as err:
|
||||
connection.send_error(
|
||||
msg[ID],
|
||||
ERR_INVALID_FORMAT,
|
||||
err.args[0],
|
||||
)
|
||||
return
|
||||
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
result,
|
||||
)
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
result,
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
|
@ -5,7 +5,7 @@ from http import HTTPStatus
|
||||
from io import BytesIO
|
||||
import json
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import PropertyMock, patch
|
||||
|
||||
import pytest
|
||||
from zwave_js_server.const import (
|
||||
@ -489,6 +489,7 @@ async def test_node_alerts(
|
||||
|
||||
async def test_add_node(
|
||||
hass: HomeAssistant,
|
||||
nortek_thermostat,
|
||||
nortek_thermostat_added_event,
|
||||
integration,
|
||||
client,
|
||||
@ -936,12 +937,46 @@ async def test_add_node(
|
||||
assert msg["error"]["code"] == "zwave_error"
|
||||
assert msg["error"]["message"] == "zwave_error: Z-Wave error 1 - error message"
|
||||
|
||||
# Test inclusion already in progress
|
||||
client.async_send_command.reset_mock()
|
||||
type(client.driver.controller).inclusion_state = PropertyMock(
|
||||
return_value=InclusionState.INCLUDING
|
||||
)
|
||||
|
||||
# Create a node that's not ready
|
||||
node_data = deepcopy(nortek_thermostat.data) # Copy to allow modification in tests.
|
||||
node_data["ready"] = False
|
||||
node_data["values"] = {}
|
||||
node_data["endpoints"] = {}
|
||||
node = Node(client, node_data)
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
|
||||
await ws_client.send_json(
|
||||
{
|
||||
ID: 11,
|
||||
TYPE: "zwave_js/add_node",
|
||||
ENTRY_ID: entry.entry_id,
|
||||
INCLUSION_STRATEGY: InclusionStrategy.DEFAULT.value,
|
||||
}
|
||||
)
|
||||
|
||||
msg = await ws_client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
# Verify no command was sent since inclusion is already in progress
|
||||
assert len(client.async_send_command.call_args_list) == 0
|
||||
|
||||
# Verify we got a node added event
|
||||
msg = await ws_client.receive_json()
|
||||
assert msg["event"]["event"] == "node added"
|
||||
assert msg["event"]["node"]["node_id"] == node.node_id
|
||||
|
||||
# Test sending command with not loaded entry fails
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await ws_client.send_json(
|
||||
{ID: 11, TYPE: "zwave_js/add_node", ENTRY_ID: entry.entry_id}
|
||||
{ID: 12, TYPE: "zwave_js/add_node", ENTRY_ID: entry.entry_id}
|
||||
)
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user