From b632423126d396dd886eea381a46d5a45120b8da Mon Sep 17 00:00:00 2001 From: Thibaut Etienne Date: Tue, 14 Feb 2023 22:35:32 +0100 Subject: [PATCH] Rework event listener logic --- pyoverkiz/client.py | 19 +++++++------------ pyoverkiz/servers/overkiz_server.py | 29 +++++++++++++++++++++++++++-- pyoverkiz/servers/somfy.py | 5 ++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/pyoverkiz/client.py b/pyoverkiz/client.py index 59c40f2f..2057089d 100644 --- a/pyoverkiz/client.py +++ b/pyoverkiz/client.py @@ -55,7 +55,6 @@ class OverkizClient: setup: Setup | None devices: list[Device] gateways: list[Gateway] - event_listener_id: str | None session: ClientSession _refresh_token: str | None = None @@ -86,7 +85,6 @@ def __init__( self.setup: Setup | None = None self.devices: list[Device] = [] self.gateways: list[Gateway] = [] - self.event_listener_id: str | None = None async def __aenter__(self) -> OverkizClient: return self @@ -101,8 +99,8 @@ async def __aexit__( async def close(self) -> None: """Close the session.""" - if self.event_listener_id: - await self.unregister_event_listener() + if self.server.event_listener_id: + await self.server.unregister_event_listener() await self.server.session.close() @@ -286,11 +284,7 @@ async def register_event_listener(self) -> str: timeout : listening sessions are expected to call the /events/{listenerId}/fetch API on a regular basis. """ - response = await self.server.post("events/register") - listener_id = cast(str, response.get("id")) - self.event_listener_id = listener_id - - return listener_id + return await self.server.register_event_listener() @backoff.on_exception(backoff.expo, TooManyConcurrentRequestsException, max_tries=5) @backoff.on_exception( @@ -309,7 +303,9 @@ async def fetch_events(self) -> list[Event]: Per-session rate-limit : 1 calls per 1 SECONDS period for this particular operation (polling) """ - response = await self.server.post(f"events/{self.event_listener_id}/fetch") + response = await self.server.post( + f"events/{self.server.event_listener_id}/fetch" + ) events = [Event(**e) for e in humps.decamelize(response)] return events @@ -319,8 +315,7 @@ async def unregister_event_listener(self) -> None: Unregister an event listener. API response status is always 200, even on unknown listener ids. """ - await self.server.post(f"events/{self.event_listener_id}/unregister") - self.event_listener_id = None + return await self.server.unregister_event_listener() @backoff.on_exception( backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin diff --git a/pyoverkiz/servers/overkiz_server.py b/pyoverkiz/servers/overkiz_server.py index 7d3e199c..17ce93cd 100644 --- a/pyoverkiz/servers/overkiz_server.py +++ b/pyoverkiz/servers/overkiz_server.py @@ -2,10 +2,11 @@ from abc import ABC, abstractmethod from json import JSONDecodeError -from typing import Any +from typing import Any, cast from aiohttp import ClientResponse, ClientSession from attr import define +from attrs import field from pyoverkiz.exceptions import ( AccessDeniedToGatewayException, @@ -37,8 +38,8 @@ class OverkizServer(ABC): endpoint: str manufacturer: str session: ClientSession - configuration_url: str | None + event_listener_id: str | None = field(default=None, init=False) @abstractmethod async def login(self, username: str, password: str) -> bool: @@ -167,3 +168,27 @@ async def check_response(response: ClientResponse) -> None: raise AccessDeniedToGatewayException(message) raise Exception(message if message else result) + + async def register_event_listener(self) -> str: + """ + Register a new setup event listener on the current session and return a new + listener id. + Only one listener may be registered on a given session. + Registering an new listener will invalidate the previous one if any. + Note that registering an event listener drastically reduces the session + timeout : listening sessions are expected to call the /events/{listenerId}/fetch + API on a regular basis. + """ + response = await self.post("events/register") + listener_id = cast(str, response.get("id")) + self.event_listener_id = listener_id + + return listener_id + + async def unregister_event_listener(self) -> None: + """ + Unregister an event listener. + API response status is always 200, even on unknown listener ids. + """ + await self.post(f"events/{self.event_listener_id}/unregister") + self.event_listener_id = None diff --git a/pyoverkiz/servers/somfy.py b/pyoverkiz/servers/somfy.py index 1aac37e8..1d81de47 100644 --- a/pyoverkiz/servers/somfy.py +++ b/pyoverkiz/servers/somfy.py @@ -128,6 +128,5 @@ async def _refresh_token_if_expired(self) -> None: ): await self.refresh_token() - # TODO - # if self.event_listener_id: - # await self.register_event_listener() + if self.event_listener_id: + await self.register_event_listener()