Small speedups to unifi (#122684)
- Use a set for event_is_on to avoid linear search - Avoid many duplicate property lookups
This commit is contained in:
parent
1a5706a693
commit
482cf261c0
7 changed files with 40 additions and 35 deletions
|
@ -149,7 +149,7 @@ class UnifiButtonEntity(UnifiEntity[HandlerT, ApiItemT], ButtonEntity):
|
|||
|
||||
async def async_press(self) -> None:
|
||||
"""Press the button."""
|
||||
await self.entity_description.control_fn(self.hub.api, self._obj_id)
|
||||
await self.entity_description.control_fn(self.api, self._obj_id)
|
||||
|
||||
@callback
|
||||
def async_update_state(self, event: ItemEvent, obj_id: str) -> None:
|
||||
|
|
|
@ -153,7 +153,7 @@ ENTITY_DESCRIPTIONS: tuple[UnifiTrackerEntityDescription, ...] = (
|
|||
allowed_fn=async_client_allowed_fn,
|
||||
api_handler_fn=lambda api: api.clients,
|
||||
device_info_fn=lambda api, obj_id: None,
|
||||
event_is_on=(WIRED_CONNECTION + WIRELESS_CONNECTION),
|
||||
event_is_on=set(WIRED_CONNECTION + WIRELESS_CONNECTION),
|
||||
event_to_subscribe=(
|
||||
WIRED_CONNECTION
|
||||
+ WIRED_DISCONNECTION
|
||||
|
@ -226,7 +226,7 @@ class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity):
|
|||
|
||||
entity_description: UnifiTrackerEntityDescription
|
||||
|
||||
_event_is_on: tuple[EventKey, ...]
|
||||
_event_is_on: set[EventKey]
|
||||
_ignore_events: bool
|
||||
_is_connected: bool
|
||||
|
||||
|
@ -237,7 +237,7 @@ class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity):
|
|||
Initiate is_connected.
|
||||
"""
|
||||
description = self.entity_description
|
||||
self._event_is_on = description.event_is_on or ()
|
||||
self._event_is_on = description.event_is_on or set()
|
||||
self._ignore_events = False
|
||||
self._is_connected = description.is_connected_fn(self.hub, self._obj_id)
|
||||
if self.is_connected:
|
||||
|
@ -255,12 +255,12 @@ class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity):
|
|||
@property
|
||||
def hostname(self) -> str | None:
|
||||
"""Return hostname of the device."""
|
||||
return self.entity_description.hostname_fn(self.hub.api, self._obj_id)
|
||||
return self.entity_description.hostname_fn(self.api, self._obj_id)
|
||||
|
||||
@property
|
||||
def ip_address(self) -> str | None:
|
||||
"""Return the primary ip address of the device."""
|
||||
return self.entity_description.ip_address_fn(self.hub.api, self._obj_id)
|
||||
return self.entity_description.ip_address_fn(self.api, self._obj_id)
|
||||
|
||||
@cached_property
|
||||
def mac_address(self) -> str:
|
||||
|
@ -293,42 +293,45 @@ class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity):
|
|||
Schedule new heartbeat check if connected.
|
||||
"""
|
||||
description = self.entity_description
|
||||
hub = self.hub
|
||||
|
||||
if event == ItemEvent.CHANGED:
|
||||
if event is ItemEvent.CHANGED:
|
||||
# Prioritize normal data updates over events
|
||||
self._ignore_events = True
|
||||
|
||||
elif event == ItemEvent.ADDED and not self.available:
|
||||
elif event is ItemEvent.ADDED and not self.available:
|
||||
# From unifi.entity.async_signal_reachable_callback
|
||||
# Controller connection state has changed and entity is unavailable
|
||||
# Cancel heartbeat
|
||||
self.hub.remove_heartbeat(self.unique_id)
|
||||
hub.remove_heartbeat(self.unique_id)
|
||||
return
|
||||
|
||||
if is_connected := description.is_connected_fn(self.hub, self._obj_id):
|
||||
obj_id = self._obj_id
|
||||
if is_connected := description.is_connected_fn(hub, obj_id):
|
||||
self._is_connected = is_connected
|
||||
self.hub.update_heartbeat(
|
||||
self.unique_id,
|
||||
dt_util.utcnow()
|
||||
+ description.heartbeat_timedelta_fn(self.hub, self._obj_id),
|
||||
dt_util.utcnow() + description.heartbeat_timedelta_fn(hub, obj_id),
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_event_callback(self, event: Event) -> None:
|
||||
"""Event subscription callback."""
|
||||
if event.mac != self._obj_id or self._ignore_events:
|
||||
obj_id = self._obj_id
|
||||
if event.mac != obj_id or self._ignore_events:
|
||||
return
|
||||
|
||||
hub = self.hub
|
||||
if event.key in self._event_is_on:
|
||||
self.hub.remove_heartbeat(self.unique_id)
|
||||
hub.remove_heartbeat(self.unique_id)
|
||||
self._is_connected = True
|
||||
self.async_write_ha_state()
|
||||
return
|
||||
|
||||
self.hub.update_heartbeat(
|
||||
hub.update_heartbeat(
|
||||
self.unique_id,
|
||||
dt_util.utcnow()
|
||||
+ self.entity_description.heartbeat_timedelta_fn(self.hub, self._obj_id),
|
||||
+ self.entity_description.heartbeat_timedelta_fn(hub, obj_id),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
|
@ -353,7 +356,7 @@ class UnifiScannerEntity(UnifiEntity[HandlerT, ApiItemT], ScannerEntity):
|
|||
if self.entity_description.key != "Client device scanner":
|
||||
return None
|
||||
|
||||
client = self.entity_description.object_fn(self.hub.api, self._obj_id)
|
||||
client = self.entity_description.object_fn(self.api, self._obj_id)
|
||||
raw = client.raw
|
||||
|
||||
attributes_to_check = CLIENT_STATIC_ATTRIBUTES
|
||||
|
|
|
@ -120,7 +120,7 @@ class UnifiEntityDescription(EntityDescription, Generic[HandlerT, ApiItemT]):
|
|||
# Optional constants
|
||||
has_entity_name = True # Part of EntityDescription
|
||||
"""Has entity name defaults to true."""
|
||||
event_is_on: tuple[EventKey, ...] | None = None
|
||||
event_is_on: set[EventKey] | None = None
|
||||
"""Which UniFi events should be used to consider state 'on'."""
|
||||
event_to_subscribe: tuple[EventKey, ...] | None = None
|
||||
"""Which UniFi events to listen on."""
|
||||
|
@ -143,6 +143,7 @@ class UnifiEntity(Entity, Generic[HandlerT, ApiItemT]):
|
|||
"""Set up UniFi switch entity."""
|
||||
self._obj_id = obj_id
|
||||
self.hub = hub
|
||||
self.api = hub.api
|
||||
self.entity_description = description
|
||||
|
||||
hub.entity_loader.known_objects.add((description.key, obj_id))
|
||||
|
@ -154,14 +155,14 @@ class UnifiEntity(Entity, Generic[HandlerT, ApiItemT]):
|
|||
self._attr_should_poll = description.should_poll
|
||||
self._attr_unique_id = description.unique_id_fn(hub, obj_id)
|
||||
|
||||
obj = description.object_fn(self.hub.api, obj_id)
|
||||
obj = description.object_fn(self.api, obj_id)
|
||||
self._attr_name = description.name_fn(obj)
|
||||
self.async_initiate_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
description = self.entity_description
|
||||
handler = description.api_handler_fn(self.hub.api)
|
||||
handler = description.api_handler_fn(self.api)
|
||||
|
||||
@callback
|
||||
def unregister_object() -> None:
|
||||
|
@ -201,7 +202,7 @@ class UnifiEntity(Entity, Generic[HandlerT, ApiItemT]):
|
|||
# Subscribe to events if defined
|
||||
if description.event_to_subscribe is not None:
|
||||
self.async_on_remove(
|
||||
self.hub.api.events.subscribe(
|
||||
self.api.events.subscribe(
|
||||
self.async_event_callback,
|
||||
description.event_to_subscribe,
|
||||
)
|
||||
|
@ -210,8 +211,8 @@ class UnifiEntity(Entity, Generic[HandlerT, ApiItemT]):
|
|||
@callback
|
||||
def async_signalling_callback(self, event: ItemEvent, obj_id: str) -> None:
|
||||
"""Update the entity state."""
|
||||
if event == ItemEvent.DELETED and obj_id == self._obj_id:
|
||||
self.hass.async_create_task(self.remove_item({self._obj_id}))
|
||||
if event is ItemEvent.DELETED and obj_id == self._obj_id:
|
||||
self.hass.async_create_task(self.remove_item({obj_id}))
|
||||
return
|
||||
|
||||
description = self.entity_description
|
||||
|
|
|
@ -97,7 +97,7 @@ class UnifiImageEntity(UnifiEntity[HandlerT, ApiItemT], ImageEntity):
|
|||
"""Return bytes of image."""
|
||||
if self.current_image is None:
|
||||
description = self.entity_description
|
||||
obj = description.object_fn(self.hub.api, self._obj_id)
|
||||
obj = description.object_fn(self.api, self._obj_id)
|
||||
self.current_image = description.image_fn(self.hub, obj)
|
||||
return self.current_image
|
||||
|
||||
|
@ -105,7 +105,7 @@ class UnifiImageEntity(UnifiEntity[HandlerT, ApiItemT], ImageEntity):
|
|||
def async_update_state(self, event: ItemEvent, obj_id: str) -> None:
|
||||
"""Update entity state."""
|
||||
description = self.entity_description
|
||||
obj = description.object_fn(self.hub.api, self._obj_id)
|
||||
obj = description.object_fn(self.api, self._obj_id)
|
||||
if (value := description.value_fn(obj)) != self.previous_value:
|
||||
self.previous_value = value
|
||||
self.current_image = None
|
||||
|
|
|
@ -490,7 +490,7 @@ class UnifiSensorEntity(UnifiEntity[HandlerT, ApiItemT], SensorEntity):
|
|||
Update native_value.
|
||||
"""
|
||||
description = self.entity_description
|
||||
obj = description.object_fn(self.hub.api, self._obj_id)
|
||||
obj = description.object_fn(self.api, self._obj_id)
|
||||
# Update the value only if value is considered to have changed relative to its previous state
|
||||
if description.value_changed_fn(
|
||||
self.native_value, (value := description.value_fn(self.hub, obj))
|
||||
|
|
|
@ -11,7 +11,7 @@ from __future__ import annotations
|
|||
import asyncio
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import aiounifi
|
||||
from aiounifi.interfaces.api_handlers import ItemEvent
|
||||
|
@ -189,7 +189,7 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSwitchEntityDescription, ...] = (
|
|||
api_handler_fn=lambda api: api.clients,
|
||||
control_fn=async_block_client_control_fn,
|
||||
device_info_fn=async_client_device_info_fn,
|
||||
event_is_on=CLIENT_UNBLOCKED,
|
||||
event_is_on=set(CLIENT_UNBLOCKED),
|
||||
event_to_subscribe=CLIENT_BLOCKED + CLIENT_UNBLOCKED,
|
||||
is_on_fn=lambda hub, client: not client.blocked,
|
||||
object_fn=lambda api, obj_id: api.clients[obj_id],
|
||||
|
@ -342,7 +342,7 @@ class UnifiSwitchEntity(UnifiEntity[HandlerT, ApiItemT], SwitchEntity):
|
|||
return
|
||||
|
||||
description = self.entity_description
|
||||
obj = description.object_fn(self.hub.api, self._obj_id)
|
||||
obj = description.object_fn(self.api, self._obj_id)
|
||||
if (is_on := description.is_on_fn(self.hub, obj)) != self.is_on:
|
||||
self._attr_is_on = is_on
|
||||
|
||||
|
@ -353,8 +353,9 @@ class UnifiSwitchEntity(UnifiEntity[HandlerT, ApiItemT], SwitchEntity):
|
|||
return
|
||||
|
||||
description = self.entity_description
|
||||
assert isinstance(description.event_to_subscribe, tuple)
|
||||
assert isinstance(description.event_is_on, tuple)
|
||||
if TYPE_CHECKING:
|
||||
assert description.event_to_subscribe is not None
|
||||
assert description.event_is_on is not None
|
||||
|
||||
if event.key in description.event_to_subscribe:
|
||||
self._attr_is_on = event.key in description.event_is_on
|
||||
|
@ -367,7 +368,7 @@ class UnifiSwitchEntity(UnifiEntity[HandlerT, ApiItemT], SwitchEntity):
|
|||
|
||||
if self.entity_description.custom_subscribe is not None:
|
||||
self.async_on_remove(
|
||||
self.entity_description.custom_subscribe(self.hub.api)(
|
||||
self.entity_description.custom_subscribe(self.api)(
|
||||
self.async_signalling_callback, ItemEvent.CHANGED
|
||||
),
|
||||
)
|
||||
|
|
|
@ -96,7 +96,7 @@ class UnifiDeviceUpdateEntity(UnifiEntity[_HandlerT, _DataT], UpdateEntity):
|
|||
self, version: str | None, backup: bool, **kwargs: Any
|
||||
) -> None:
|
||||
"""Install an update."""
|
||||
await self.entity_description.control_fn(self.hub.api, self._obj_id)
|
||||
await self.entity_description.control_fn(self.api, self._obj_id)
|
||||
|
||||
@callback
|
||||
def async_update_state(self, event: ItemEvent, obj_id: str) -> None:
|
||||
|
@ -106,7 +106,7 @@ class UnifiDeviceUpdateEntity(UnifiEntity[_HandlerT, _DataT], UpdateEntity):
|
|||
"""
|
||||
description = self.entity_description
|
||||
|
||||
obj = description.object_fn(self.hub.api, self._obj_id)
|
||||
self._attr_in_progress = description.state_fn(self.hub.api, obj)
|
||||
obj = description.object_fn(self.api, self._obj_id)
|
||||
self._attr_in_progress = description.state_fn(self.api, obj)
|
||||
self._attr_installed_version = obj.version
|
||||
self._attr_latest_version = obj.upgrade_to_firmware or obj.version
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue