Skip to content

Commit 55d3976

Browse files
committed
Add initial client
1 parent b8ca61d commit 55d3976

1 file changed

Lines changed: 173 additions & 0 deletions

File tree

elmax/__init__.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
"""Client for the Elmax Cloud service."""
2+
from yarl import URL
3+
import asyncio
4+
import logging
5+
import httpx
6+
import json
7+
8+
from .constants import (
9+
BASE_URL,
10+
ENDPOINT_DEVICES,
11+
ENDPOINT_LOGIN,
12+
ENDPOINT_STATUS_ENTITY_ID,
13+
ENDPOINT_ENTITY_ID_COMMAND,
14+
ENDPOINT_DISCOVERY,
15+
USER_AGENT,
16+
ZONE,
17+
OUTPUT,
18+
AREA,
19+
)
20+
21+
headers = {
22+
"user-agent": USER_AGENT,
23+
"Accept": "application/json, text/plain, */*",
24+
}
25+
26+
_LOGGER = logging.getLogger(__name__)
27+
28+
29+
class Elmax(object):
30+
"""A class for handling the data retrieval."""
31+
32+
def __init__(
33+
self,
34+
username: str = None,
35+
password: str = None,
36+
device_id: str = None,
37+
):
38+
"""Initialize the connection."""
39+
self.username = username
40+
self.password = password
41+
self.devices = None
42+
self.authorized = False
43+
self.authorization = None
44+
self.areas = self.outputs = self.zones = {}
45+
46+
self.registry = DeviceRegistry()
47+
48+
async def connect(self):
49+
"""Establish connection to the API."""
50+
url = URL(BASE_URL) / ENDPOINT_LOGIN
51+
data = {
52+
"username": self.username,
53+
"password": self.password,
54+
}
55+
56+
async with httpx.AsyncClient() as client:
57+
response = await client.post(str(url), headers=headers, data=data)
58+
59+
_LOGGER.debug("Status code:", response.status_code)
60+
61+
try:
62+
response_data = response.json()
63+
self.authorization = response_data["token"]
64+
self.authorized = True
65+
# The API doesn't respond with 401 but there will be no JSON
66+
except json.decoder.JSONDecodeError:
67+
self.authorized = False
68+
_LOGGER.error("Credentials are not valid")
69+
70+
async def disconnect(self):
71+
"""Terminate the connection to the API."""
72+
if self.authorized:
73+
self.authorized = False
74+
75+
async def get_devices(self):
76+
"""Retrieve the devices."""
77+
if self.authorized is False:
78+
self.connect()
79+
80+
url = URL(BASE_URL) / ENDPOINT_DEVICES
81+
headers["Authorization"] = self.authorization
82+
83+
async with httpx.AsyncClient() as client:
84+
response = await client.get(str(url), headers=headers)
85+
86+
_LOGGER.debug("Status code:", response.status_code)
87+
88+
for response_entry in response.json():
89+
device = AvailableDevice.create_new_device(response_entry)
90+
self.registry.register(device)
91+
92+
async def list_devices(self):
93+
"""List all available devices."""
94+
await self.get_devices()
95+
96+
device_list = []
97+
for device in self.registry.devices():
98+
device_list.append(
99+
{"online": device.online, "hash": device.hash, "name": device.name}
100+
)
101+
102+
return device_list
103+
104+
async def get_units(self, device_id, pin):
105+
"""List all units of a devices."""
106+
if self.authorized is False:
107+
self.connect()
108+
109+
url = URL(BASE_URL) / ENDPOINT_DISCOVERY / device_id / str(pin)
110+
111+
headers["Authorization"] = self.authorization
112+
113+
async with httpx.AsyncClient() as client:
114+
response = await client.get(str(url), headers=headers)
115+
116+
response_data = response.json()
117+
118+
if response_data[ZONE]:
119+
self.zones = response_data[ZONE]
120+
if response_data[OUTPUT]:
121+
self.outputs = response_data[OUTPUT]
122+
if response_data[AREA]:
123+
self.areas = response_data[AREA]
124+
125+
async def get_status(self, entity_id):
126+
"""Get the status of an unit."""
127+
if self.authorized is False:
128+
self.connect()
129+
130+
url = URL(BASE_URL) / ENDPOINT_STATUS_ENTITY_ID / entity_id
131+
132+
headers["Authorization"] = self.authorization
133+
134+
async with httpx.AsyncClient() as client:
135+
response = await client.get(str(url), headers=headers)
136+
137+
return response.json()["zone"][0]
138+
139+
140+
class AvailableDevice:
141+
"""Representation of an available device."""
142+
143+
def __init__(self, hash, online, name):
144+
"""Initialize the new device."""
145+
self.hash = hash
146+
self.online = online
147+
self.name = name
148+
149+
@staticmethod
150+
def create_new_device(response_entry):
151+
"""Create a new device."""
152+
device = AvailableDevice(
153+
hash=response_entry["hash"],
154+
online=bool(response_entry["centrale_online"]),
155+
name=response_entry["username"][0]["label"],
156+
)
157+
return device
158+
159+
160+
class DeviceRegistry(object):
161+
"""Representation of the devices registry."""
162+
163+
def __init__(self):
164+
"""Initialize the device registry."""
165+
self.devices_by_hash = {}
166+
167+
def register(self, device):
168+
"""Register a new device."""
169+
self.devices_by_hash[device.hash] = device
170+
171+
def devices(self) -> list:
172+
"""Get all available devices."""
173+
return list(self.devices_by_hash.values())

0 commit comments

Comments
 (0)