Skip to content

Commit

Permalink
Add support for passing in the client session (#42)
Browse files Browse the repository at this point in the history
Works as expected
  • Loading branch information
bdraco authored Feb 12, 2021
1 parent 770da14 commit 715404f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 54 deletions.
129 changes: 75 additions & 54 deletions sense_energy/asyncsenseable.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,69 @@
import asyncio
import aiohttp
import json
import websockets
import ssl

import aiohttp
import websockets

from .sense_api import *
from .sense_exceptions import *


class ASyncSenseable(SenseableBase):

def __init__(
self,
username=None,
password=None,
api_timeout=API_TIMEOUT,
wss_timeout=WSS_TIMEOUT,
client_session=None,
):
"""Init the ASyncSenseable object."""
self._client_session = client_session or aiohttp.ClientSession()
self.ssl_context = None

super().__init__(
username=username,
password=password,
api_timeout=api_timeout,
wss_timeout=wss_timeout,
)

async def authenticate(self, username, password):
auth_data = {
"email": username,
"password": password
}
auth_data = {"email": username, "password": password}

self.ssl_context = ssl.create_default_context()

# Get auth token
try:
async with aiohttp.ClientSession() as session:
async with session.post(API_URL+'authenticate',
timeout=self.api_timeout,
data=auth_data) as resp:

# check for 200 return
if resp.status != 200:
raise SenseAuthenticationException(
"Please check username and password. API Return Code: %s" %
resp.status)

# Build out some common variables
self.set_auth_data(await resp.json())
except Exception as e:
raise SenseAPITimeoutException('Connection failure: %s' % e)
async with self._client_session.post(
API_URL + "authenticate", timeout=self.api_timeout, data=auth_data
) as resp:

# check for 200 return
if resp.status != 200:
raise SenseAuthenticationException(
"Please check username and password. API Return Code: %s"
% resp.status
)

# Build out some common variables
self.set_auth_data(await resp.json())
except Exception as ex:
raise SenseAPITimeoutException("Connection failure: %s" % ex) from ex

# Update the realtime data for asyncio
async def update_realtime(self):
# rate limit API calls
if self._realtime and self.rate_limit and \
self.last_realtime_call + self.rate_limit > time():
if (
self._realtime
and self.rate_limit
and self.last_realtime_call + self.rate_limit > time()
):
return self._realtime
self.last_realtime_call = time()
await self.async_realtime_stream(single=True)

async def async_realtime_stream(self, callback=None, single=False):
""" Reads realtime data from websocket"""
url = WS_URL % (self.sense_monitor_id, self.sense_access_token)
Expand All @@ -52,42 +72,46 @@ async def async_realtime_stream(self, callback=None, single=False):
while True:
try:
message = await asyncio.wait_for(
ws.recv(), timeout=self.wss_timeout)
except asyncio.TimeoutError:
raise SenseAPITimeoutException("API websocket timed out")

ws.recv(), timeout=self.wss_timeout
)
except asyncio.TimeoutError as ex:
raise SenseAPITimeoutException("API websocket timed out") from ex

result = json.loads(message)
if result.get('type') == 'realtime_update':
data = result['payload']
if result.get("type") == "realtime_update":
data = result["payload"]
self.set_realtime(data)
if callback: callback(data)
if single: return
elif result.get('type') == 'error':
data = result['payload']
raise SenseWebsocketException(data['error_reason'])

if callback:
callback(data)
if single:
return
elif result.get("type") == "error":
data = result["payload"]
raise SenseWebsocketException(data["error_reason"])

async def get_realtime_future(self, callback):
""" Returns an async Future to parse realtime data with callback"""
await self.async_realtime_stream(callback)

async def api_call(self, url, payload={}):
timeout = aiohttp.ClientTimeout(total=self.api_timeout)
async with aiohttp.ClientSession() as session:
async with session.get(API_URL + url,
headers=self.headers,
timeout=timeout,
data=payload) as resp:
try:
async with self._client_session.get(
API_URL + url, headers=self.headers, timeout=timeout, data=payload
) as resp:
return await resp.json()
# timed out
raise SenseAPITimeoutException("API call timed out")
except asyncio.TimeoutError as ex:
# timed out
raise SenseAPITimeoutException("API call timed out") from ex

async def get_trend_data(self, scale):
if scale.upper() not in valid_scales:
raise Exception("%s not a valid scale" % scale)
t = datetime.now().replace(hour=12)
json = self.api_call(
'app/history/trends?monitor_id=%s&scale=%s&start=%s' %
(self.sense_monitor_id, scale, t.isoformat()))
"app/history/trends?monitor_id=%s&scale=%s&start=%s"
% (self.sense_monitor_id, scale, t.isoformat())
)
self._trend_data[scale] = await json

async def update_trend_data(self):
Expand All @@ -96,13 +120,10 @@ async def update_trend_data(self):

async def get_discovered_device_names(self):
# lots more info in here to be parsed out
json = self.api_call('app/monitors/%s/devices' %
self.sense_monitor_id)
self._devices = await [entry['name'] for entry in json]
json = self.api_call("app/monitors/%s/devices" % self.sense_monitor_id)
self._devices = await [entry["name"] for entry in json]
return self._devices

async def get_discovered_device_data(self):
json = self.api_call('monitors/%s/devices' %
self.sense_monitor_id)
json = self.api_call("monitors/%s/devices" % self.sense_monitor_id)
return await json

1 change: 1 addition & 0 deletions sense_energy/sense_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def __init__(self, username=None, password=None,
self.api_timeout = api_timeout
self.wss_timeout = wss_timeout
self.rate_limit = RATE_LIMIT
self.last_realtime_call = 0

self._realtime = {}
self._devices = []
Expand Down

0 comments on commit 715404f

Please sign in to comment.