mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Refactor ZHA device initialized logic (#25796)
* refactor device initialized * better names and update tests * clean up last seen logic * logging consistency
This commit is contained in:
parent
dc5c1783dc
commit
fafd228418
@ -57,7 +57,7 @@ class IASZoneChannel(ZigbeeChannel):
|
|||||||
"""Configure IAS device."""
|
"""Configure IAS device."""
|
||||||
# Xiaomi devices don't need this and it disrupts pairing
|
# Xiaomi devices don't need this and it disrupts pairing
|
||||||
if self._zha_device.manufacturer == "LUMI":
|
if self._zha_device.manufacturer == "LUMI":
|
||||||
self.debug("%s: finished IASZoneChannel configuration")
|
self.debug("finished IASZoneChannel configuration")
|
||||||
return
|
return
|
||||||
from zigpy.exceptions import DeliveryError
|
from zigpy.exceptions import DeliveryError
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ class IASZoneChannel(ZigbeeChannel):
|
|||||||
self._cluster.ep_attribute,
|
self._cluster.ep_attribute,
|
||||||
str(ex),
|
str(ex),
|
||||||
)
|
)
|
||||||
self.debug("%s: finished IASZoneChannel configuration")
|
self.debug("finished IASZoneChannel configuration")
|
||||||
|
|
||||||
await self.get_attribute_value("zone_type", from_cache=False)
|
await self.get_attribute_value("zone_type", from_cache=False)
|
||||||
|
|
||||||
|
@ -138,9 +138,7 @@ class ZHAGateway:
|
|||||||
if device.nwk == 0x0000:
|
if device.nwk == 0x0000:
|
||||||
continue
|
continue
|
||||||
init_tasks.append(
|
init_tasks.append(
|
||||||
init_with_semaphore(
|
init_with_semaphore(self.async_device_restored(device), semaphore)
|
||||||
self.async_device_initialized(device, False), semaphore
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
await asyncio.gather(*init_tasks)
|
await asyncio.gather(*init_tasks)
|
||||||
|
|
||||||
@ -181,7 +179,7 @@ class ZHAGateway:
|
|||||||
|
|
||||||
def device_initialized(self, device):
|
def device_initialized(self, device):
|
||||||
"""Handle device joined and basic information discovered."""
|
"""Handle device joined and basic information discovered."""
|
||||||
self._hass.async_create_task(self.async_device_initialized(device, True))
|
self._hass.async_create_task(self.async_device_initialized(device))
|
||||||
|
|
||||||
def device_left(self, device):
|
def device_left(self, device):
|
||||||
"""Handle device leaving the network."""
|
"""Handle device leaving the network."""
|
||||||
@ -292,7 +290,7 @@ class ZHAGateway:
|
|||||||
self.debug_enabled = False
|
self.debug_enabled = False
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_get_or_create_device(self, zigpy_device, is_new_join):
|
def _async_get_or_create_device(self, zigpy_device):
|
||||||
"""Get or create a ZHA device."""
|
"""Get or create a ZHA device."""
|
||||||
zha_device = self._devices.get(zigpy_device.ieee)
|
zha_device = self._devices.get(zigpy_device.ieee)
|
||||||
if zha_device is None:
|
if zha_device is None:
|
||||||
@ -306,9 +304,6 @@ class ZHAGateway:
|
|||||||
manufacturer=zha_device.manufacturer,
|
manufacturer=zha_device.manufacturer,
|
||||||
model=zha_device.model,
|
model=zha_device.model,
|
||||||
)
|
)
|
||||||
if not is_new_join:
|
|
||||||
entry = self.zha_storage.async_get_or_create(zha_device)
|
|
||||||
zha_device.async_update_last_seen(entry.last_seen)
|
|
||||||
return zha_device
|
return zha_device
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -333,55 +328,38 @@ class ZHAGateway:
|
|||||||
self.zha_storage.async_update(device)
|
self.zha_storage.async_update(device)
|
||||||
await self.zha_storage.async_save()
|
await self.zha_storage.async_save()
|
||||||
|
|
||||||
async def async_device_initialized(self, device, is_new_join):
|
async def async_device_initialized(self, device):
|
||||||
"""Handle device joined and basic information discovered (async)."""
|
"""Handle device joined and basic information discovered (async)."""
|
||||||
if device.nwk == 0x0000:
|
if device.nwk == 0x0000:
|
||||||
return
|
return
|
||||||
|
|
||||||
zha_device = self._async_get_or_create_device(device, is_new_join)
|
zha_device = self._async_get_or_create_device(device)
|
||||||
|
|
||||||
is_rejoin = False
|
|
||||||
if zha_device.status is not DeviceStatus.INITIALIZED:
|
|
||||||
discovery_infos = []
|
|
||||||
for endpoint_id, endpoint in device.endpoints.items():
|
|
||||||
async_process_endpoint(
|
|
||||||
self._hass,
|
|
||||||
self._config,
|
|
||||||
endpoint_id,
|
|
||||||
endpoint,
|
|
||||||
discovery_infos,
|
|
||||||
device,
|
|
||||||
zha_device,
|
|
||||||
is_new_join,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
is_rejoin = is_new_join is True
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"skipping discovery for previously discovered device: %s",
|
"device - %s entering async_device_initialized - is_new_join: %s",
|
||||||
"{} - is rejoin: {}".format(zha_device.ieee, is_rejoin),
|
"0x{:04x}:{}".format(device.nwk, device.ieee),
|
||||||
|
zha_device.status is not DeviceStatus.INITIALIZED,
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_new_join:
|
if zha_device.status is DeviceStatus.INITIALIZED:
|
||||||
# configure the device
|
# ZHA already has an initialized device so either the device was assigned a
|
||||||
await zha_device.async_configure()
|
# new nwk or device was physically reset and added again without being removed
|
||||||
zha_device.update_available(True)
|
|
||||||
elif zha_device.is_mains_powered:
|
|
||||||
# the device isn't a battery powered device so we should be able
|
|
||||||
# to update it now
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"attempting to request fresh state for %s %s",
|
"device - %s has been reset and readded or its nwk address changed",
|
||||||
zha_device.name,
|
"0x{:04x}:{}".format(device.nwk, device.ieee),
|
||||||
"with power source: {}".format(zha_device.power_source),
|
|
||||||
)
|
)
|
||||||
await zha_device.async_initialize(from_cache=False)
|
await self._async_device_rejoined(zha_device)
|
||||||
else:
|
else:
|
||||||
await zha_device.async_initialize(from_cache=True)
|
_LOGGER.debug(
|
||||||
|
"device - %s has joined the ZHA zigbee network",
|
||||||
|
"0x{:04x}:{}".format(device.nwk, device.ieee),
|
||||||
|
)
|
||||||
|
await self._async_device_joined(device, zha_device)
|
||||||
|
|
||||||
if not is_rejoin:
|
# This is real traffic from a device so lets update last seen on the entry
|
||||||
for discovery_info in discovery_infos:
|
entry = self.zha_storage.async_get_or_create(zha_device)
|
||||||
async_dispatch_discovery_info(self._hass, is_new_join, discovery_info)
|
zha_device.async_update_last_seen(entry.last_seen)
|
||||||
|
|
||||||
if is_new_join:
|
|
||||||
device_info = async_get_device_info(
|
device_info = async_get_device_info(
|
||||||
self._hass, zha_device, self.ha_device_registry
|
self._hass, zha_device, self.ha_device_registry
|
||||||
)
|
)
|
||||||
@ -394,6 +372,70 @@ class ZHAGateway:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _async_device_joined(self, device, zha_device):
|
||||||
|
discovery_infos = []
|
||||||
|
for endpoint_id, endpoint in device.endpoints.items():
|
||||||
|
async_process_endpoint(
|
||||||
|
self._hass,
|
||||||
|
self._config,
|
||||||
|
endpoint_id,
|
||||||
|
endpoint,
|
||||||
|
discovery_infos,
|
||||||
|
device,
|
||||||
|
zha_device,
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
|
await zha_device.async_configure()
|
||||||
|
# will cause async_init to fire so don't explicitly call it
|
||||||
|
zha_device.update_available(True)
|
||||||
|
|
||||||
|
for discovery_info in discovery_infos:
|
||||||
|
async_dispatch_discovery_info(self._hass, True, discovery_info)
|
||||||
|
|
||||||
|
# only public for testing
|
||||||
|
async def async_device_restored(self, device):
|
||||||
|
"""Add an existing device to the ZHA zigbee network when ZHA first starts."""
|
||||||
|
zha_device = self._async_get_or_create_device(device)
|
||||||
|
discovery_infos = []
|
||||||
|
for endpoint_id, endpoint in device.endpoints.items():
|
||||||
|
async_process_endpoint(
|
||||||
|
self._hass,
|
||||||
|
self._config,
|
||||||
|
endpoint_id,
|
||||||
|
endpoint,
|
||||||
|
discovery_infos,
|
||||||
|
device,
|
||||||
|
zha_device,
|
||||||
|
False,
|
||||||
|
)
|
||||||
|
|
||||||
|
if zha_device.is_mains_powered:
|
||||||
|
# the device isn't a battery powered device so we should be able
|
||||||
|
# to update it now
|
||||||
|
_LOGGER.debug(
|
||||||
|
"attempting to request fresh state for device - %s %s %s",
|
||||||
|
"0x{:04x}:{}".format(zha_device.nwk, zha_device.ieee),
|
||||||
|
zha_device.name,
|
||||||
|
"with power source: {}".format(zha_device.power_source),
|
||||||
|
)
|
||||||
|
await zha_device.async_initialize(from_cache=False)
|
||||||
|
else:
|
||||||
|
await zha_device.async_initialize(from_cache=True)
|
||||||
|
|
||||||
|
for discovery_info in discovery_infos:
|
||||||
|
async_dispatch_discovery_info(self._hass, False, discovery_info)
|
||||||
|
|
||||||
|
async def _async_device_rejoined(self, zha_device):
|
||||||
|
_LOGGER.debug(
|
||||||
|
"skipping discovery for previously discovered device - %s",
|
||||||
|
"0x{:04x}:{}".format(zha_device.nwk, zha_device.ieee),
|
||||||
|
)
|
||||||
|
# we don't have to do this on a nwk swap but we don't have a way to tell currently
|
||||||
|
await zha_device.async_configure()
|
||||||
|
# will cause async_init to fire so don't explicitly call it
|
||||||
|
zha_device.update_available(True)
|
||||||
|
|
||||||
async def shutdown(self):
|
async def shutdown(self):
|
||||||
"""Stop ZHA Controller Application."""
|
"""Stop ZHA Controller Application."""
|
||||||
_LOGGER.debug("Shutting down ZHA ControllerApplication")
|
_LOGGER.debug("Shutting down ZHA ControllerApplication")
|
||||||
|
@ -140,7 +140,10 @@ async def async_init_zigpy_device(
|
|||||||
device = make_device(
|
device = make_device(
|
||||||
in_cluster_ids, out_cluster_ids, device_type, ieee, manufacturer, model
|
in_cluster_ids, out_cluster_ids, device_type, ieee, manufacturer, model
|
||||||
)
|
)
|
||||||
await gateway.async_device_initialized(device, is_new_join)
|
if is_new_join:
|
||||||
|
await gateway.async_device_initialized(device)
|
||||||
|
else:
|
||||||
|
await gateway.async_device_restored(device)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
return device
|
return device
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user