Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SharkIQ token expiration #89357

10 changes: 9 additions & 1 deletion homeassistant/components/sharkiq/update_coordinator.py
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

import asyncio
from datetime import datetime, timedelta

from async_timeout import timeout
from sharkiq import (
Expand Down Expand Up @@ -60,6 +61,13 @@ async def _async_update_vacuum(sharkiq: SharkIqVacuum) -> None:
async def _async_update_data(self) -> bool:
"""Update data device by device."""
try:
if self.ayla_api.token_expiring_soon:
await self.ayla_api.async_refresh_auth()
elif datetime.now() > self.ayla_api.auth_expiration - timedelta(
seconds=600
):
await self.ayla_api.async_refresh_auth()

all_vacuums = await self.ayla_api.async_list_devices()
self._online_dsns = {
v["dsn"]
Expand All @@ -78,7 +86,7 @@ async def _async_update_data(self) -> bool:
LOGGER.debug("Bad auth state. Attempting re-auth", exc_info=err)
raise ConfigEntryAuthFailed from err
funkybunch marked this conversation as resolved.
Show resolved Hide resolved
except Exception as err:
LOGGER.exception("Unexpected error updating SharkIQ")
LOGGER.exception("Unexpected error updating SharkIQ. Attempting re-auth")
raise UpdateFailed(err) from err

return True
18 changes: 18 additions & 0 deletions tests/components/sharkiq/test_vacuum.py
Expand Up @@ -3,6 +3,7 @@

from collections.abc import Iterable
from copy import deepcopy
from datetime import datetime, timedelta
import enum
from typing import Any
from unittest.mock import patch
Expand Down Expand Up @@ -72,9 +73,14 @@
class MockAyla(AylaApi):
"""Mocked AylaApi that doesn't do anything."""

desired_expiry = False

async def async_sign_in(self):
"""Instead of signing in, just return."""

async def async_refresh_auth(self):
"""Instead of refreshing auth, just return."""

async def async_sign_out(self):
"""Instead of signing out, just return."""

Expand All @@ -92,6 +98,18 @@ async def async_get_devices(self, update: bool = True) -> list[SharkIqVacuum]:
async def async_request(self, http_method: str, url: str, **kwargs):
"""Don't make an HTTP request."""

@property
def token_expiring_soon(self) -> bool:
"""Toggling Property for Token Expiration Flag."""
# Alternate expiry flag for each test
self.desired_expiry = not self.desired_expiry
return self.desired_expiry

@property
def auth_expiration(self) -> datetime:
"""Sample expiration timestamp that is always 1200 seconds behind now()."""
return datetime.now() - timedelta(seconds=1200)


class MockShark(SharkIqVacuum):
"""Mocked SharkIqVacuum that won't hit the API."""
Expand Down