Skip to content

Commit e425196

Browse files
committed
-) Moved getting account and device portions in their own methods
-) Device update when waiting for task to be completed (open/close) is now done every 5 seconds and not part of minimum update interval.
1 parent 5c25339 commit e425196

File tree

2 files changed

+118
-102
lines changed

2 files changed

+118
-102
lines changed

pymyq/api.py

Lines changed: 116 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -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

598614
async def login(username: str, password: str, websession: ClientSession = None) -> API:

pymyq/device.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ async def wait_for_state(self, current_state: List, new_state: List, last_state_
128128
wait_timeout = wait_timeout - 5
129129
await asyncio.sleep(5)
130130
try:
131-
await self.update()
131+
await self._api.update_device_info(for_account=self.account)
132132
except MyQError:
133133
# Ignoring
134134
pass
@@ -140,7 +140,7 @@ async def wait_for_state(self, current_state: List, new_state: List, last_state_
140140
wait_timeout = wait_timeout - 5
141141
await asyncio.sleep(5)
142142
try:
143-
await self.update()
143+
await self._api.update_device_info(for_account=self.account)
144144
except MyQError:
145145
# Ignoring
146146
pass

0 commit comments

Comments
 (0)