Skip to content

Commit 5385137

Browse files
authored
Relogin when disconnected (#43)
1 parent bc27baf commit 5385137

File tree

9 files changed

+62
-84
lines changed

9 files changed

+62
-84
lines changed

.github/workflows/main.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- uses: actions/checkout@v1
16-
- uses: actions/setup-python@v1
16+
- uses: actions/setup-python@v2
17+
with:
18+
python-version: '3.7'
1719
- uses: pre-commit/action@v2.0.0

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/python-tahoma-api.iml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ repos:
99
rev: 19.10b0
1010
hooks:
1111
- id: black
12-
language_version: python3.8
12+
language_version: python3.7
1313
- repo: https://github.com/pre-commit/pre-commit-hooks
1414
rev: v2.4.0
1515
hooks:
1616
- id: flake8
17-
language_version: python3.8
17+
language_version: python3.7
1818
- repo: https://github.com/pre-commit/mirrors-mypy
1919
rev: v0.740
2020
hooks:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async def main() -> None:
4646
listener_id = await client.register_event_listener()
4747

4848
while True:
49-
events = await client.fetch_event_listener(listener_id)
49+
events = await client.fetch_events()
5050
print(events)
5151

5252
time.sleep(2)

poetry.lock

Lines changed: 15 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyhoma/client.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from types import TracebackType
77
from typing import Any, Dict, List, Optional, Type, Union
88

9+
import backoff
910
import humps
1011
from aiohttp import ClientResponse, ClientSession
1112

@@ -21,6 +22,10 @@
2122
API_URL = "https://tahomalink.com/enduser-mobile-web/enduserAPI/" # /doc for API doc
2223

2324

25+
async def relogin(invocation: Dict[str, Any]) -> None:
26+
await invocation["args"][0].login()
27+
28+
2429
class TahomaClient:
2530
""" Interface class for the Tahoma API """
2631

@@ -64,11 +69,11 @@ async def __aexit__(
6469
async def close(self) -> None:
6570
"""Close the session."""
6671
if self.event_listener_id:
67-
await self.unregister_event_listener(self.event_listener_id)
72+
await self.unregister_event_listener()
6873

6974
await self.session.close()
7075

71-
async def login(self) -> bool:
76+
async def login(self, register_event_listener: Optional[bool] = True) -> bool:
7277
"""
7378
Authenticate and create an API session allowing access to the other operations.
7479
Caller must provide one of [userId+userPassword, userId+ssoToken, accessToken, jwt]
@@ -77,10 +82,9 @@ async def login(self) -> bool:
7782
response = await self.__post("login", data=payload)
7883

7984
if response.get("success"):
80-
self.__roles = response.get("roles")
81-
85+
if register_event_listener:
86+
await self.register_event_listener()
8287
return True
83-
8488
return False
8589

8690
async def get_devices(self, refresh: bool = False) -> List[Device]:
@@ -96,6 +100,9 @@ async def get_devices(self, refresh: bool = False) -> List[Device]:
96100

97101
return devices
98102

103+
@backoff.on_exception(
104+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
105+
)
99106
async def get_state(self, deviceurl: str) -> List[State]:
100107
"""
101108
Retrieve states of requested device
@@ -123,40 +130,49 @@ async def register_event_listener(self) -> str:
123130

124131
return listener_id
125132

126-
async def fetch_event_listener(self, listener_id: str) -> List[Event]:
133+
async def fetch_events(self) -> List[Event]:
127134
"""
128135
Fetch new events from a registered event listener. Fetched events are removed
129136
from the listener buffer. Return an empty response if no event is available.
130137
Per-session rate-limit : 1 calls per 1 SECONDS period for this particular
131138
operation (polling)
132139
"""
133-
response = await self.__post(f"events/{listener_id}/fetch")
140+
response = await self.__post(f"events/{self.event_listener_id}/fetch")
134141
events = [Event(**e) for e in humps.decamelize(response)]
135142

136143
return events
137144

138-
async def unregister_event_listener(self, listener_id: str) -> None:
145+
async def unregister_event_listener(self) -> None:
139146
"""
140147
Unregister an event listener.
141148
API response status is always 200, even on unknown listener ids.
142149
"""
143-
await self.__post(f"events/{listener_id}/unregister")
150+
await self.__post(f"events/{self.event_listener_id}/unregister")
144151
self.event_listener_id = None
145152

153+
@backoff.on_exception(
154+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
155+
)
146156
async def get_current_execution(self, exec_id: str) -> Execution:
147157
""" Get an action group execution currently running """
148158
response = await self.__get(f"exec/current/{exec_id}")
149159
execution = Execution(**humps.decamelize(response))
150160

151161
return execution
152162

163+
@backoff.on_exception(
164+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
165+
)
153166
async def get_current_executions(self) -> List[Execution]:
154167
""" Get all action groups executions currently running """
155168
response = await self.__get("exec/current")
156169
executions = [Execution(**e) for e in humps.decamelize(response)]
157170

158171
return executions
159172

173+
@backoff.on_exception(
174+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
175+
)
160176
async def execute_command(
161177
self,
162178
device_url: str,
@@ -168,10 +184,16 @@ async def execute_command(
168184
command = Command(command)
169185
return await self.execute_commands(device_url, [command], label)
170186

187+
@backoff.on_exception(
188+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
189+
)
171190
async def cancel_command(self, exec_id: str) -> None:
172191
""" Cancel a running setup-level execution """
173192
await self.__delete(f"/exec/current/setup/{exec_id}")
174193

194+
@backoff.on_exception(
195+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
196+
)
175197
async def execute_commands(
176198
self,
177199
device_url: str,
@@ -186,11 +208,17 @@ async def execute_commands(
186208
response = await self.__post("exec/apply", payload)
187209
return response["execId"]
188210

211+
@backoff.on_exception(
212+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
213+
)
189214
async def get_scenarios(self) -> List[Scenario]:
190215
""" List the scenarios """
191216
response = await self.__get("actionGroups")
192217
return [Scenario(**scenario) for scenario in response]
193218

219+
@backoff.on_exception(
220+
backoff.expo, NotAuthenticatedException, max_tries=2, on_backoff=relogin
221+
)
194222
async def execute_scenario(self, oid: str) -> str:
195223
""" Execute a scenario """
196224
response = await self.__post(f"exec/{oid}")

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ packages = [
1515
python = ">=3.7"
1616
aiohttp = "^3.6.1"
1717
pyhumps = "^1.3.1"
18+
backoff = "^1.10.0"
1819

1920
[tool.poetry.dev-dependencies]
2021
tox = ">=3.0"

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ select = C,E,F,W,B,B950
44
ignore = E501
55

66
[isort]
7-
known_third_party = aiohttp,humps
7+
known_third_party = aiohttp,backoff,humps
88
multi_line_output=3
99
include_trailing_comma=true
1010
force_grid_wrap=0

0 commit comments

Comments
 (0)