| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- """ZYXEL API Client"""
- import asyncio
- import base64
- import aiohttp
- from .const import (API_TIMEOUT,
- API_SCHEMA,
- API_BASE_PATH,
- API_LOGIN_PATH,
- LOGIN_PAYLOAD,
- KEY_RESULT,
- VAL_SUCCES,
- KEY_OBJECT)
- class RouterApiClientError(Exception):
- """Exception to indicate a general API error."""
- class RouterApiClientCommunicationError(RouterApiClientError):
- """Exception to indicate a communication error."""
- class RouterApiClientLoginError(RouterApiClientError):
- """Exception to indicate an api key error."""
- class RouterApiClientResponseError(RouterApiClientError):
- """Exception to indicate a response error."""
- class RouterApiClient:
- """Router API wrapper for ZYXEL routers"""
- def __init__(
- self,
- endpoint: str,
- user: str,
- password: str,
- session: aiohttp.ClientSession,
- ) -> None:
- """ZYXEL API Client."""
- self.endpoint = endpoint
- self.user = user
- self.password = password
- self._session = session
- async def async_login(self) -> bool:
- """Login and obtain the session cookie"""
- payload = LOGIN_PAYLOAD.copy()
- payload['Input_Account'] = self.user
- payload['Input_Passwd'] = base64.b64encode(
- self.password.encode('utf-8')).decode('utf-8')
- response = await self._session.post(
- f'{API_SCHEMA}://{self.endpoint}{API_LOGIN_PATH}',
- json=payload)
-
- if response.ok:
- try:
- data = response.json()
- if 'result' in data:
- if data['result'] == 'ZCFG_SUCCESS':
- return True
- else:
- raise RouterApiClientLoginError('Login failed')
- else:
- raise RouterApiClientResponseError('Key "result" not set in response')
-
- except Exception as json_exception:
- raise RouterApiClientResponseError(f'Unable to decode login response') \
- from json_exception
-
- raise RouterApiClientCommunicationError(
- f'Error connecting to router. Status: {response.status}')
-
- async def async_query_api(self,
- oid: str) -> dict:
- """Query an authenticated API endpoint"""
- try:
- async with asyncio.timeout(API_TIMEOUT):
- response = await self._session.get(
- f'{API_SCHEMA}://{self.endpoint}{API_BASE_PATH}',
- params={'oid': oid})
- if response.ok:
- try:
- data: dict = await response.json()
- if data.get(KEY_RESULT, None) == VAL_SUCCES:
- return data.get(KEY_OBJECT, [{}])[0]
- else:
- raise RouterApiClientResponseError(f'Response returned error')
- except Exception as json_exception:
- raise RouterApiClientResponseError(f'Unable to decode JSON') \
- from json_exception
- else:
- raise RouterApiClientCommunicationError(
- f'Error retrieving API. Status: {response.status}')
- except Exception as exception:
- raise RouterApiClientCommunicationError('Unable to connect to router API') \
- from exception
|