Remove zwave_js devices that the controller is no longer connected to on initialization (#45853)

* Remove zwave_js devices that the controller is no longer connected to on initialization

* remove extra line break

* fix test

* Clean up

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Lint

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
pull/45863/head
Raman Gupta 2021-02-02 03:30:12 -06:00 committed by GitHub
parent 0e3ba532c7
commit a64ad50b27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 0 deletions

View File

@ -102,6 +102,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# update entity availability
async_dispatcher_send(hass, f"{DOMAIN}_{entry.entry_id}_connection_state")
# Check for nodes that no longer exist and remove them
stored_devices = device_registry.async_entries_for_config_entry(
dev_reg, entry.entry_id
)
known_devices = [
dev_reg.async_get_device({get_device_id(client, node)})
for node in client.driver.controller.nodes.values()
]
# Devices that are in the device registry that are not known by the controller can be removed
for device in stored_devices:
if device not in known_devices:
dev_reg.async_remove_device(device.id)
@callback
def async_on_node_ready(node: ZwaveNode) -> None:
"""Handle node ready event."""

View File

@ -308,3 +308,15 @@ def in_wall_smart_fan_control_fixture(client, in_wall_smart_fan_control_state):
node = Node(client, in_wall_smart_fan_control_state)
client.driver.controller.nodes[node.node_id] = node
return node
@pytest.fixture(name="multiple_devices")
def multiple_devices_fixture(
client, climate_radio_thermostat_ct100_plus_state, lock_schlage_be469_state
):
"""Mock a client with multiple devices."""
node = Node(client, climate_radio_thermostat_ct100_plus_state)
client.driver.controller.nodes[node.node_id] = node
node = Node(client, lock_schlage_be469_state)
client.driver.controller.nodes[node.node_id] = node
return client.driver.controller.nodes

View File

@ -7,6 +7,7 @@ from zwave_js_server.model.node import Node
from homeassistant.components.hassio.handler import HassioAPIError
from homeassistant.components.zwave_js.const import DOMAIN
from homeassistant.components.zwave_js.entity import get_device_id
from homeassistant.config_entries import (
CONN_CLASS_LOCAL_PUSH,
ENTRY_STATE_LOADED,
@ -14,6 +15,7 @@ from homeassistant.config_entries import (
ENTRY_STATE_SETUP_RETRY,
)
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.helpers import device_registry, entity_registry
from .common import AIR_TEMPERATURE_SENSOR
@ -290,3 +292,42 @@ async def test_remove_entry(hass, stop_addon, uninstall_addon, caplog):
assert entry.state == ENTRY_STATE_NOT_LOADED
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
assert "Failed to uninstall the Z-Wave JS add-on" in caplog.text
async def test_removed_device(hass, client, multiple_devices, integration):
"""Test that the device registry gets updated when a device gets removed."""
nodes = multiple_devices
# Verify how many nodes are available
assert len(client.driver.controller.nodes) == 2
# Make sure there are the same number of devices
dev_reg = await device_registry.async_get_registry(hass)
device_entries = device_registry.async_entries_for_config_entry(
dev_reg, integration.entry_id
)
assert len(device_entries) == 2
# Check how many entities there are
ent_reg = await entity_registry.async_get_registry(hass)
entity_entries = entity_registry.async_entries_for_config_entry(
ent_reg, integration.entry_id
)
assert len(entity_entries) == 18
# Remove a node and reload the entry
old_node = nodes.pop(13)
await hass.config_entries.async_reload(integration.entry_id)
await hass.async_block_till_done()
# Assert that the node and all of it's entities were removed from the device and
# entity registry
device_entries = device_registry.async_entries_for_config_entry(
dev_reg, integration.entry_id
)
assert len(device_entries) == 1
entity_entries = entity_registry.async_entries_for_config_entry(
ent_reg, integration.entry_id
)
assert len(entity_entries) == 9
assert dev_reg.async_get_device({get_device_id(client, old_node)}) is None