mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Entity Cleanup on Z-Wave node removal (#23633)
* Initial groundwork for entity cleanup on node removal * Connect node_removed to dispatcher * update docstring * Add node_removal test * Address review comments * Use hass.add_job instead of run_coroutine_threadsafe
This commit is contained in:
parent
eebd094423
commit
1282370ccb
@ -376,6 +376,25 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout,
|
hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout,
|
||||||
hass.loop)
|
hass.loop)
|
||||||
|
|
||||||
|
def node_removed(node):
|
||||||
|
node_id = node.node_id
|
||||||
|
node_key = 'node-{}'.format(node_id)
|
||||||
|
_LOGGER.info("Node Removed: %s",
|
||||||
|
hass.data[DATA_DEVICES][node_key])
|
||||||
|
for key in list(hass.data[DATA_DEVICES]):
|
||||||
|
if not key.startswith('{}-'.format(node_id)):
|
||||||
|
continue
|
||||||
|
|
||||||
|
entity = hass.data[DATA_DEVICES][key]
|
||||||
|
_LOGGER.info('Removing Entity - value: %s - entity_id: %s',
|
||||||
|
key, entity.entity_id)
|
||||||
|
hass.add_job(entity.node_removed())
|
||||||
|
del hass.data[DATA_DEVICES][key]
|
||||||
|
|
||||||
|
entity = hass.data[DATA_DEVICES][node_key]
|
||||||
|
hass.add_job(entity.node_removed())
|
||||||
|
del hass.data[DATA_DEVICES][node_key]
|
||||||
|
|
||||||
def network_ready():
|
def network_ready():
|
||||||
"""Handle the query of all awake nodes."""
|
"""Handle the query of all awake nodes."""
|
||||||
_LOGGER.info("Z-Wave network is ready for use. All awake nodes "
|
_LOGGER.info("Z-Wave network is ready for use. All awake nodes "
|
||||||
@ -399,6 +418,8 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False)
|
value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False)
|
||||||
dispatcher.connect(
|
dispatcher.connect(
|
||||||
node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False)
|
node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False)
|
||||||
|
dispatcher.connect(
|
||||||
|
node_removed, ZWaveNetwork.SIGNAL_NODE_REMOVED, weak=False)
|
||||||
dispatcher.connect(
|
dispatcher.connect(
|
||||||
network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False)
|
network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False)
|
||||||
dispatcher.connect(
|
dispatcher.connect(
|
||||||
|
@ -3,6 +3,7 @@ import logging
|
|||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.const import ATTR_BATTERY_LEVEL, ATTR_WAKEUP, ATTR_ENTITY_ID
|
from homeassistant.const import ATTR_BATTERY_LEVEL, ATTR_WAKEUP, ATTR_ENTITY_ID
|
||||||
|
from homeassistant.helpers.entity_registry import async_get_registry
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -74,6 +75,16 @@ class ZWaveBaseEntity(Entity):
|
|||||||
if self.hass and self.platform:
|
if self.hass and self.platform:
|
||||||
self.hass.add_job(_async_remove_and_add)
|
self.hass.add_job(_async_remove_and_add)
|
||||||
|
|
||||||
|
async def node_removed(self):
|
||||||
|
"""Call when a node is removed from the Z-Wave network."""
|
||||||
|
await self.async_remove()
|
||||||
|
|
||||||
|
registry = await async_get_registry(self.hass)
|
||||||
|
if self.entity_id not in registry.entities:
|
||||||
|
return
|
||||||
|
|
||||||
|
registry.async_remove(self.entity_id)
|
||||||
|
|
||||||
|
|
||||||
class ZWaveNodeEntity(ZWaveBaseEntity):
|
class ZWaveNodeEntity(ZWaveBaseEntity):
|
||||||
"""Representation of a Z-Wave node."""
|
"""Representation of a Z-Wave node."""
|
||||||
|
@ -226,6 +226,48 @@ async def test_device_entity(hass, mock_openzwave):
|
|||||||
assert device.device_state_attributes[zwave.ATTR_POWER] == 50.123
|
assert device.device_state_attributes[zwave.ATTR_POWER] == 50.123
|
||||||
|
|
||||||
|
|
||||||
|
async def test_node_removed(hass, mock_openzwave):
|
||||||
|
"""Test node removed in base class."""
|
||||||
|
# Create a mock node & node entity
|
||||||
|
node = MockNode(node_id='10', name='Mock Node')
|
||||||
|
value = MockValue(data=False, node=node, instance=2, object_id='11',
|
||||||
|
label='Sensor',
|
||||||
|
command_class=const.COMMAND_CLASS_SENSOR_BINARY)
|
||||||
|
power_value = MockValue(data=50.123456, node=node, precision=3,
|
||||||
|
command_class=const.COMMAND_CLASS_METER)
|
||||||
|
values = MockEntityValues(primary=value, power=power_value)
|
||||||
|
device = zwave.ZWaveDeviceEntity(values, 'zwave')
|
||||||
|
device.hass = hass
|
||||||
|
device.entity_id = 'zwave.mock_node'
|
||||||
|
device.value_added()
|
||||||
|
device.update_properties()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Save it to the entity registry
|
||||||
|
registry = mock_registry(hass)
|
||||||
|
registry.async_get_or_create('zwave', 'zwave', device.unique_id)
|
||||||
|
device.entity_id = registry.async_get_entity_id(
|
||||||
|
'zwave', 'zwave', device.unique_id)
|
||||||
|
|
||||||
|
# Create dummy entity registry entries for other integrations
|
||||||
|
hue_entity = registry.async_get_or_create('light', 'hue', 1234)
|
||||||
|
zha_entity = registry.async_get_or_create('sensor', 'zha', 5678)
|
||||||
|
|
||||||
|
# Verify our Z-Wave entity is registered
|
||||||
|
assert registry.async_is_registered(device.entity_id)
|
||||||
|
|
||||||
|
# Remove it
|
||||||
|
entity_id = device.entity_id
|
||||||
|
await device.node_removed()
|
||||||
|
|
||||||
|
# Verify registry entry for our Z-Wave node is gone
|
||||||
|
assert not registry.async_is_registered(entity_id)
|
||||||
|
|
||||||
|
# Verify registry entries for our other entities remain
|
||||||
|
assert registry.async_is_registered(hue_entity.entity_id)
|
||||||
|
assert registry.async_is_registered(zha_entity.entity_id)
|
||||||
|
|
||||||
|
|
||||||
async def test_node_discovery(hass, mock_openzwave):
|
async def test_node_discovery(hass, mock_openzwave):
|
||||||
"""Test discovery of a node."""
|
"""Test discovery of a node."""
|
||||||
mock_receivers = []
|
mock_receivers = []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user