Skip to content

Commit

Permalink
Merge pull request #2 from Cyr-ius/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
cyr-ius committed Jan 23, 2022
2 parents be1c401 + de014e9 commit 809658d
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: [3.7, 3.8]
python-version: [3.8, 3.9]

steps:
- uses: actions/checkout@v1
Expand Down
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.pythonPath": "/media/datas/hass-integrations/heatzypy/.venv/bin/python",
"cSpell.words": [
"Gizwits",
"Heatzy"
]
}
25 changes: 25 additions & 0 deletions heatzypy.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"folders": [{
"path": "."
}],
"settings": {
"python.linting.flake8Args": ["--ignore=E501,W504,E712,W503"],
"python.linting.pycodestyleArgs": [
"--ignore=E501,W503"
],
"python.pythonPath": "/media/datas/hass-integrations/heatzypy/.venv/bin/python"
},
"launch": {
"version": "0.2.0",
"configurations": [

{
"name": "Python : Fichier actuel",
"type": "python",
"request": "launch",
"program": "example_home.py",
"console": "integratedTerminal"
}
]
}
}
2 changes: 1 addition & 1 deletion heatzypy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
from .heatzy import HeatzyClient

name = "heatzy"
__version__ = "0.1.4.2"
__version__ = "2.0.0"
__all__ = ["HeatzyClient"]
56 changes: 25 additions & 31 deletions heatzypy/heatzy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .const import HEATZY_API_URL, HEATZY_APPLICATION_ID
from .exception import HeatzyException, HttpRequestFailed

logger = logging.getLogger(__name__)
_LOGGER = logging.getLogger(__name__)


class HeatzyClient:
Expand All @@ -21,83 +21,77 @@ def __init__(self, username, password):
self._password = password
self._authentication = None

def _authenticate(self):
async def async_authenticate(self):
"""Get Heatzy stored authentication if it exists or authenticate against Heatzy API."""
headers = {"X-Gizwits-Application-Id": HEATZY_APPLICATION_ID}
payload = {"username": self._username, "password": self._password}

response = self._make_request("/login", method="POST", payload=payload, headers=headers)
response = await self._async_make_request("/login", method="POST", payload=payload, headers=headers)
if response.status_code != 200:
raise HeatzyException("Authentication failed", response.status_code)

logger.debug("Authentication successful with {}".format(self._username))
return response.json()

def _get_token(self):
async def async_get_token(self):
"""Get authentication token."""
if self._authentication is not None and self._authentication.get("expire_at") > time.time():
return self._authentication["token"]
self._authentication = self._authenticate()
if self._authentication:
return self._authentication["token"]
if self._authentication is None or self._authentication.get("expire_at") < time.time():
self._authentication = await self.async_authenticate()
return self._authentication["token"]

def _make_request(self, service, method="GET", headers=None, payload=None):
async def _async_make_request(self, service, method="GET", headers=None, payload=None):
"""Request session."""
if headers is None:
token = self._get_token()
token = await self.async_get_token()
headers = {
"X-Gizwits-Application-Id": HEATZY_APPLICATION_ID,
"X-Gizwits-User-Token": token,
}
url = HEATZY_API_URL + service
logger.debug("{} {} {}".format(method, url, headers))

try:
url = HEATZY_API_URL + service
_LOGGER.debug("{} {} {}".format(method, url, headers))
return self._session.request(method=method, url=url, json=payload, headers=headers)
except RequestException as error:
raise HttpRequestFailed("Request failed") from error

def get_devices(self):
async def async_get_devices(self):
"""Fetch all configured devices."""
response = self._make_request("/bindings")
response = await self._async_make_request("/bindings")
if response.status_code != 200:
raise HeatzyException("Devices not retrieved", response.status_code)

# API response has Content-Type=text/html, content_type=None silences parse error by forcing content type
body = response.json()
devices = body.get("devices")

return [self._merge_with_device_data(device) for device in devices]
return [await self._async_merge_with_device_data(device) for device in devices]

def get_device(self, device_id):
async def async_get_device(self, device_id):
"""Fetch device with given id."""
response = self._make_request(f"/devices/{device_id}")
response = await self._async_make_request(f"/devices/{device_id}")
if response.status_code != 200:
raise HeatzyException(f"Device data for {device_id} not retrieved", response.status_code)

# API response has Content-Type=text/html, content_type=None silences parse error by forcing content type
logger.debug(response.text)
device = response.json()
return self._merge_with_device_data(device)
return await self._async_merge_with_device_data(device)

def _merge_with_device_data(self, device):
async def _async_merge_with_device_data(self, device):
"""Fetch detailled data for given device and merge it with the device information."""
device_data = self._get_device_data(device.get("did"))
device_data = await self.async_get_device_data(device.get("did"))
return {**device, **device_data}

def _get_device_data(self, device_id):
async def async_get_device_data(self, device_id):
"""Fetch detailled data for device with given id."""
response = self._make_request(f"/devdata/{device_id}/latest")
response = await self._async_make_request(f"/devdata/{device_id}/latest")
if response.status_code != 200:
raise HeatzyException(f"Device data for {device_id} not retrieved", response.status_code)

logger.debug(response.text)
device_data = response.json()
return device_data

def control_device(self, device_id, payload):
async def async_control_device(self, device_id, payload):
"""Control state of device with given id."""
self._make_request(f"/control/{device_id}", method="POST", payload=payload)
await self._async_make_request(f"/control/{device_id}", method="POST", payload=payload)

def is_connected(self):
"""Check connection."""
return self._authenticate() is not None
return self._authentication is not None
5 changes: 5 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Heatzypy
-r requirements.txt

flake8
black

0 comments on commit 809658d

Please sign in to comment.