go back to signals and no hard entity references (#24894)

This commit is contained in:
David F. Mulcahey 2019-07-01 16:32:57 -04:00 committed by GitHub
parent b6e0f538c5
commit 7f90a1cab2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 13 deletions

View file

@ -139,7 +139,7 @@ def async_get_device_info(hass, device, ha_device_registry=None):
ret_device = {} ret_device = {}
ret_device.update(device.device_info) ret_device.update(device.device_info)
ret_device['entities'] = [{ ret_device['entities'] = [{
'entity_id': entity_ref.entity.entity_id, 'entity_id': entity_ref.reference_id,
NAME: entity_ref.device_info[NAME] NAME: entity_ref.device_info[NAME]
} for entity_ref in zha_gateway.device_registry[device.ieee]] } for entity_ref in zha_gateway.device_registry[device.ieee]]

View file

@ -103,6 +103,7 @@ SIGNAL_MOVE_LEVEL = "move_level"
SIGNAL_SET_LEVEL = "set_level" SIGNAL_SET_LEVEL = "set_level"
SIGNAL_STATE_ATTR = "update_state_attribute" SIGNAL_STATE_ATTR = "update_state_attribute"
SIGNAL_AVAILABLE = 'available' SIGNAL_AVAILABLE = 'available'
SIGNAL_REMOVE = 'remove'
QUIRK_APPLIED = 'quirk_applied' QUIRK_APPLIED = 'quirk_applied'
QUIRK_CLASS = 'quirk_class' QUIRK_CLASS = 'quirk_class'

View file

@ -27,8 +27,8 @@ from .const import (
DEBUG_LEVELS, DEFAULT_BAUDRATE, DEFAULT_DATABASE_NAME, DEVICE_FULL_INIT, DEBUG_LEVELS, DEFAULT_BAUDRATE, DEFAULT_DATABASE_NAME, DEVICE_FULL_INIT,
DEVICE_INFO, DEVICE_JOINED, DEVICE_REMOVED, DOMAIN, IEEE, LOG_ENTRY, DEVICE_INFO, DEVICE_JOINED, DEVICE_REMOVED, DOMAIN, IEEE, LOG_ENTRY,
LOG_OUTPUT, MODEL, NWK, ORIGINAL, RADIO, RADIO_DESCRIPTION, RAW_INIT, LOG_OUTPUT, MODEL, NWK, ORIGINAL, RADIO, RADIO_DESCRIPTION, RAW_INIT,
SIGNATURE, TYPE, UNKNOWN_MANUFACTURER, UNKNOWN_MODEL, ZHA, ZHA_GW_MSG, SIGNAL_REMOVE, SIGNATURE, TYPE, UNKNOWN_MANUFACTURER, UNKNOWN_MODEL, ZHA,
ZIGPY, ZIGPY_DECONZ, ZIGPY_XBEE) ZHA_GW_MSG, ZIGPY, ZIGPY_DECONZ, ZIGPY_XBEE)
from .device import DeviceStatus, ZHADevice from .device import DeviceStatus, ZHADevice
from .discovery import ( from .discovery import (
async_create_device_entity, async_dispatch_discovery_info, async_create_device_entity, async_dispatch_discovery_info,
@ -41,8 +41,7 @@ _LOGGER = logging.getLogger(__name__)
EntityReference = collections.namedtuple( EntityReference = collections.namedtuple(
'EntityReference', 'EntityReference',
'entity device_info' 'reference_id zha_device cluster_channels device_info remove_future')
)
class ZHAGateway: class ZHAGateway:
@ -149,8 +148,8 @@ class ZHAGateway:
if entity_refs is not None: if entity_refs is not None:
remove_tasks = [] remove_tasks = []
for entity_ref in entity_refs: for entity_ref in entity_refs:
remove_tasks.append(entity_ref.entity.async_remove()) remove_tasks.append(entity_ref.remove_future)
await asyncio.gather(*remove_tasks) await asyncio.wait(remove_tasks)
ha_device_registry = await get_dev_reg(self._hass) ha_device_registry = await get_dev_reg(self._hass)
reg_device = ha_device_registry.async_get_device( reg_device = ha_device_registry.async_get_device(
{(DOMAIN, str(device.ieee))}, set()) {(DOMAIN, str(device.ieee))}, set())
@ -164,6 +163,10 @@ class ZHAGateway:
if zha_device is not None: if zha_device is not None:
device_info = async_get_device_info(self._hass, zha_device) device_info = async_get_device_info(self._hass, zha_device)
zha_device.async_unsub_dispatcher() zha_device.async_unsub_dispatcher()
async_dispatcher_send(
self._hass,
"{}_{}".format(SIGNAL_REMOVE, str(zha_device.ieee))
)
asyncio.ensure_future( asyncio.ensure_future(
self._async_remove_device(zha_device, entity_refs) self._async_remove_device(zha_device, entity_refs)
) )
@ -185,7 +188,7 @@ class ZHAGateway:
"""Return entity reference for given entity_id if found.""" """Return entity reference for given entity_id if found."""
for entity_reference in itertools.chain.from_iterable( for entity_reference in itertools.chain.from_iterable(
self.device_registry.values()): self.device_registry.values()):
if entity_id == entity_reference.entity.entity_id: if entity_id == entity_reference.reference_id:
return entity_reference return entity_reference
@property @property
@ -198,10 +201,18 @@ class ZHAGateway:
"""Return entities by ieee.""" """Return entities by ieee."""
return self._device_registry return self._device_registry
def register_entity_reference(self, ieee, entity, device_info): def register_entity_reference(
self, ieee, reference_id, zha_device, cluster_channels,
device_info, remove_future):
"""Record the creation of a hass entity associated with ieee.""" """Record the creation of a hass entity associated with ieee."""
self._device_registry[ieee].append( self._device_registry[ieee].append(
EntityReference(entity=entity, device_info=device_info) EntityReference(
reference_id=reference_id,
zha_device=zha_device,
cluster_channels=cluster_channels,
device_info=device_info,
remove_future=remove_future
)
) )
@callback @callback

View file

@ -1,5 +1,6 @@
"""Entity for Zigbee Home Automation.""" """Entity for Zigbee Home Automation."""
import asyncio
import logging import logging
import time import time
@ -11,7 +12,8 @@ from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.util import slugify from homeassistant.util import slugify
from .core.const import ( from .core.const import (
ATTR_MANUFACTURER, DATA_ZHA, DATA_ZHA_BRIDGE_ID, DOMAIN, MODEL, NAME) ATTR_MANUFACTURER, DATA_ZHA, DATA_ZHA_BRIDGE_ID, DOMAIN, MODEL, NAME,
SIGNAL_REMOVE)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -48,6 +50,7 @@ class ZhaEntity(RestoreEntity, entity.Entity):
self._available = False self._available = False
self._component = kwargs['component'] self._component = kwargs['component']
self._unsubs = [] self._unsubs = []
self.remove_future = asyncio.Future()
for channel in channels: for channel in channels:
self.cluster_channels[channel.name] = channel self.cluster_channels[channel.name] = channel
@ -125,9 +128,14 @@ class ZhaEntity(RestoreEntity, entity.Entity):
None, "{}_{}".format(self.zha_device.available_signal, 'entity'), None, "{}_{}".format(self.zha_device.available_signal, 'entity'),
self.async_set_available, self.async_set_available,
signal_override=True) signal_override=True)
self._zha_device.gateway.register_entity_reference( await self.async_accept_signal(
self._zha_device.ieee, self, self.device_info None, "{}_{}".format(SIGNAL_REMOVE, str(self.zha_device.ieee)),
self.async_remove,
signal_override=True
) )
self._zha_device.gateway.register_entity_reference(
self._zha_device.ieee, self.entity_id, self._zha_device,
self.cluster_channels, self.device_info, self.remove_future)
async def async_check_recently_seen(self): async def async_check_recently_seen(self):
"""Check if the device was seen within the last 2 hours.""" """Check if the device was seen within the last 2 hours."""
@ -145,6 +153,7 @@ class ZhaEntity(RestoreEntity, entity.Entity):
"""Disconnect entity object when removed.""" """Disconnect entity object when removed."""
for unsub in self._unsubs: for unsub in self._unsubs:
unsub() unsub()
self.remove_future.set_result(True)
@callback @callback
def async_restore_last_state(self, last_state): def async_restore_last_state(self, last_state):