@@ -97,6 +97,8 @@ def __init__(
9797 self .ws_token : str = ""
9898 self .endpoint : str = ""
9999 self ._urn : str | None = None
100+ self ._websocket_device_cache : list [dict [str , Any ]] = []
101+ self ._device_cache_ready : asyncio .Event = asyncio .Event ()
100102
101103 @classmethod
102104 async def async_create (
@@ -796,13 +798,19 @@ def _transform_graphql_device_to_rest(
796798 async def get_devices (self , location_id : int ) -> list [dict [str , Any ]]:
797799 """Get list of all devices.
798800
799- Now uses GraphQL instead of the deprecated REST endpoint.
800- Falls back to REST if GraphQL fails or URN is not available.
801+ Prioritizes websocket-cached device data (from DeviceListInitialValuesReceived)
802+ over REST/GraphQL since the websocket provides everything we need.
803+ Falls back to GraphQL, then REST if websocket data unavailable.
801804 """
802805 devices : list [dict [str , Any ]] = []
803806
804- # Try GraphQL first if we have a URN
805- if self .urn :
807+ # Try to use cached websocket device data first
808+ # The DeviceHub websocket sends DeviceListInitialValuesReceived with full device info
809+ if self ._websocket_device_cache :
810+ LOG .debug ("Using cached device list from websocket (%d devices)" , len (self ._websocket_device_cache ))
811+ devices = self ._websocket_device_cache .copy ()
812+ # Try GraphQL if we have a URN and no websocket cache
813+ elif self .urn :
806814 try :
807815 LOG .debug ("Fetching devices via GraphQL for URN: %s" , self .urn )
808816 devices = await self .get_devices_graphql (self .urn )
@@ -854,6 +862,42 @@ async def get_devices(self, location_id: int) -> list[dict[str, Any]]:
854862 devices .append (callback ())
855863
856864 return devices
865+
866+ def cache_websocket_devices (self , device_list : list [dict [str , Any ]]) -> None :
867+ """Cache device list received from DeviceHub websocket.
868+
869+ The DeviceListInitialValuesReceived message contains the full device list
870+ with all the info we need (id, name, identifier, etc.) in REST format.
871+ This eliminates the need to call the deprecated REST endpoint.
872+
873+ Args:
874+ device_list: List of devices from DeviceListInitialValuesReceived
875+ """
876+ self ._websocket_device_cache = device_list
877+ self ._device_cache_ready .set ()
878+ LOG .debug ("Cached %d devices from websocket" , len (device_list ))
879+
880+ async def wait_for_device_cache (self , timeout : float = 10.0 ) -> bool :
881+ """Wait for the websocket device cache to be populated.
882+
883+ This should be called before devices.async_init() to ensure
884+ device names and IDs are available from the websocket.
885+
886+ Args:
887+ timeout: Maximum time to wait in seconds (default: 10.0)
888+
889+ Returns:
890+ True if cache was populated, False if timeout occurred
891+ """
892+ try :
893+ await asyncio .wait_for (self ._device_cache_ready .wait (), timeout = timeout )
894+ LOG .debug ("Device cache ready after waiting" )
895+ return True
896+ except asyncio .TimeoutError :
897+ LOG .warning (
898+ "Timeout waiting for websocket device cache, will use fallback method"
899+ )
900+ return False
857901
858902 async def _set_device_attribute (
859903 self ,
0 commit comments