@@ -473,7 +473,96 @@ async def _authenticate(self) -> None:
473473 datetime .now (),
474474 )
475475
476- async def update_device_info (self ) -> None :
476+ async def _get_accounts (self ) -> Optional [dict ]:
477+
478+ _LOGGER .debug ("Retrieving account information" )
479+
480+ # Retrieve the accounts
481+ _ , accounts_resp = await self .request (
482+ method = "get" , returns = "json" , url = ACCOUNTS_ENDPOINT
483+ )
484+
485+ if accounts_resp is not None and accounts_resp .get ("accounts" ) is not None :
486+ accounts = {}
487+ for account in accounts_resp ["accounts" ]:
488+ account_id = account .get ("id" )
489+ if account_id is not None :
490+ _LOGGER .debug (
491+ f"Got account { account_id } with name { account .get ('name' )} "
492+ )
493+ accounts .update ({account_id : account .get ("name" )})
494+ else :
495+ _LOGGER .debug (f"No accounts found" )
496+ accounts = None
497+
498+ return accounts
499+
500+ async def _get_devices_for_account (self , account ) -> None :
501+
502+ _LOGGER .debug (f"Retrieving devices for account { self .accounts [account ]} " )
503+
504+ _ , devices_resp = await self .request (
505+ method = "get" ,
506+ returns = "json" ,
507+ url = DEVICES_ENDPOINT .format (account_id = account ),
508+ )
509+
510+ state_update_timestmp = datetime .utcnow ()
511+ if devices_resp is not None and devices_resp .get ("items" ) is not None :
512+ for device in devices_resp .get ("items" ):
513+ serial_number = device .get ("serial_number" )
514+ if serial_number is None :
515+ _LOGGER .debug (f"No serial number for device with name { device .get ('name' )} ." )
516+ continue
517+
518+ if serial_number in self .devices :
519+ _LOGGER .debug (f"Updating information for device with serial number { serial_number } " )
520+ myqdevice = self .devices [serial_number ]
521+
522+ # When performing commands we might update the state temporary, need to ensure
523+ # that the state is not set back to something else if MyQ does not yet have updated
524+ # state
525+ last_update = myqdevice .device_json ["state" ].get ("last_update" )
526+ myqdevice .device_json = device
527+
528+ if myqdevice .device_json ["state" ].get ("last_update" ) is not None and \
529+ myqdevice .device_json ["state" ].get ("last_update" ) != last_update :
530+ # MyQ has updated device state, reset ours ensuring we have the one from MyQ.
531+ myqdevice .state = None
532+ _LOGGER .debug (f"State for device { myqdevice .name } was updated to { myqdevice .state } " )
533+
534+ myqdevice .state_update = state_update_timestmp
535+ else :
536+ if device .get ("device_family" ) == DEVICE_FAMILY_GARAGEDOOR :
537+ _LOGGER .debug (f"Adding new garage door with serial number { serial_number } " )
538+ self .devices [serial_number ] = MyQGaragedoor (
539+ api = self ,
540+ account = account ,
541+ device_json = device ,
542+ state_update = state_update_timestmp ,
543+ )
544+ elif device .get ("device_family" ) == DEVICE_FAMLY_LAMP :
545+ _LOGGER .debug (f"Adding new lamp with serial number { serial_number } " )
546+ self .devices [serial_number ] = MyQLamp (
547+ api = self ,
548+ account = account ,
549+ device_json = device ,
550+ state_update = state_update_timestmp ,
551+ )
552+ elif device .get ("device_family" ) == DEVICE_FAMILY_GATEWAY :
553+ _LOGGER .debug (f"Adding new gateway with serial number { serial_number } " )
554+ self .devices [serial_number ] = MyQDevice (
555+ api = self ,
556+ account = account ,
557+ device_json = device ,
558+ state_update = state_update_timestmp ,
559+ )
560+ else :
561+ _LOGGER .warning (f"Unknown device family { device .get ('device_family' )} " )
562+ else :
563+ _LOGGER .debug (f"No devices found for account { self .accounts [account ]} " )
564+
565+ async def update_device_info (self , for_account : str = None ) -> None :
477566 """Get up-to-date device info."""
478567 # The MyQ API can time out if state updates are too frequent; therefore,
479568 # if back-to-back requests occur within a threshold, respond to only the first
@@ -486,113 +575,40 @@ async def update_device_info(self) -> None:
486575 self .last_state_update + DEFAULT_STATE_UPDATE_INTERVAL
487576 )
488577
489- if call_dt < next_available_call_dt :
578+ # Ensure we're within our minimum update interval AND update request is not for a specific device
579+ if call_dt < next_available_call_dt and for_account is None :
490580 _LOGGER .debug (
491581 "Ignoring device update request as it is within throttle window"
492582 )
493583 return
494584
495- _LOGGER .debug (
496- "Updating device information, starting with retrieving accounts"
497- )
498- _ , accounts_resp = await self .request (
499- method = "get" , returns = "json" , url = ACCOUNTS_ENDPOINT
500- )
501- self .accounts = {}
502- if accounts_resp is not None and accounts_resp .get ("accounts" ) is not None :
503- for account in accounts_resp ["accounts" ]:
504- account_id = account .get ("id" )
505- if account_id is not None :
506- _LOGGER .debug (
507- f"Got account { account_id } with name { account .get ('name' )} "
508- )
509- self .accounts .update ({account_id : account .get ("name" )})
510- else :
511- _LOGGER .debug (f"No accounts found" )
512- self .devices = []
585+ _LOGGER .debug ("Updating device information" )
586+ # If update request is for a specific account then do not retrieve account information.
587+ if for_account is None :
588+ self .accounts = await self ._get_accounts ()
513589
514- for account in self .accounts :
515- _LOGGER .debug (
516- f"Retrieving devices for account { self .accounts [account ]} "
517- )
518- _ , devices_resp = await self .request (
519- method = "get" ,
520- returns = "json" ,
521- url = DEVICES_ENDPOINT .format (account_id = account ),
522- )
523-
524- state_update_timestmp = datetime .utcnow ()
525- if devices_resp is not None and devices_resp .get ("items" ) is not None :
526- for device in devices_resp .get ("items" ):
527- serial_number = device .get ("serial_number" )
528- if serial_number is None :
529- _LOGGER .debug (
530- f"No serial number for device with name { device .get ('name' )} ."
531- )
532- continue
533-
534- if serial_number in self .devices :
535- _LOGGER .debug (
536- f"Updating information for device with serial number { serial_number } "
537- )
538- myqdevice = self .devices [serial_number ]
539-
540- # When performing commands we might update the state temporary, need to ensure
541- # that the state is not set back to something else if MyQ does not yet have updated
542- # state
543- last_update = myqdevice .device_json ["state" ].get ("last_update" )
544- myqdevice .device_json = device
545-
546- if myqdevice .device_json ["state" ].get ("last_update" ) is not None and \
547- myqdevice .device_json ["state" ].get ("last_update" ) != last_update :
548- # MyQ has updated device state, reset ours ensuring we have the one from MyQ.
549- myqdevice .state = None
550- _LOGGER .debug (f"State for device { myqdevice .name } was updated to { myqdevice .state } " )
551-
552-
553- myqdevice .state_update = state_update_timestmp
554- else :
555- if device .get ("device_family" ) == DEVICE_FAMILY_GARAGEDOOR :
556- _LOGGER .debug (
557- f"Adding new garage door with serial number { serial_number } "
558- )
559- self .devices [serial_number ] = MyQGaragedoor (
560- api = self ,
561- account = account ,
562- device_json = device ,
563- state_update = state_update_timestmp ,
564- )
565- elif device .get ("device_family" ) == DEVICE_FAMLY_LAMP :
566- _LOGGER .debug (
567- f"Adding new lamp with serial number { serial_number } "
568- )
569- self .devices [serial_number ] = MyQLamp (
570- api = self ,
571- account = account ,
572- device_json = device ,
573- state_update = state_update_timestmp ,
574- )
575- elif device .get ("device_family" ) == DEVICE_FAMILY_GATEWAY :
576- _LOGGER .debug (
577- f"Adding new gateway with serial number { serial_number } "
578- )
579- self .devices [serial_number ] = MyQDevice (
580- api = self ,
581- account = account ,
582- device_json = device ,
583- state_update = state_update_timestmp ,
584- )
585- else :
586- _LOGGER .warning (
587- f"Unknown device family { device .get ('device_family' )} "
588- )
589- else :
590- _LOGGER .debug (
591- f"No devices found for account { self .accounts [account ]} "
592- )
590+ if self .accounts is None :
591+ _LOGGER .debug (f"No accounts found" )
593592 self .devices = []
593+ accounts = {}
594+ else :
595+ accounts = self .accounts
596+ else :
597+ # Request is for specific account, thus restrict retrieval to the 1 account.
598+ if self .accounts .get (for_account ) is None :
599+ # Checking to ensure we know the account, but this should never happen.
600+ _LOGGER .debug (f"Unable to perform update request for account { account } as it is not known." )
601+ accounts = {}
602+ else :
603+ accounts = ({for_account : self .accounts .get (for_account )})
604+
605+ for account in accounts :
606+ _LOGGER .debug (f"Retrieving devices for account { self .accounts [account ]} " )
607+ await self ._get_devices_for_account (account = account )
594608
595- self .last_state_update = datetime .utcnow ()
609+ # Update our last update timestamp UNLESS this is for a specific account
610+ if for_account is None :
611+ self .last_state_update = datetime .utcnow ()
596612
597613
598614async def login (username : str , password : str , websession : ClientSession = None ) -> API :
0 commit comments