Skip to content

Commit a73eb58

Browse files
committed
Added unittests, created API for data updating.
1 parent d1e555c commit a73eb58

22 files changed

Lines changed: 587 additions & 8 deletions

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include requirements.txt

crownstone_cloud/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
from crownstone_cloud._RequestHandlerInstance import RequestHandler
1+
from crownstone_cloud._RequestHandlerInstance import RequestHandler
2+
from crownstone_cloud.lib.cloud import CrownstoneCloud

crownstone_cloud/lib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Library that communicates with the Crownstone lib"""
22

3-
__version__ = '0.1'
3+
__version__ = '1.0.2'

crownstone_cloud/lib/cloud.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def initialize_sync(self) -> None:
4545
def set_access_token(access_token: str) -> None:
4646
RequestHandler.access_token = access_token
4747

48+
@staticmethod
49+
def get_access_token() -> str:
50+
return RequestHandler.access_token
51+
4852
async def login(self) -> None:
4953
"""Login to Crownstone API"""
5054
result = await RequestHandler.post('users', 'login', json=self.login_data)
@@ -65,7 +69,9 @@ async def sync(self) -> None:
6569
for sphere in self.spheres:
6670
await asyncio.gather(
6771
sphere.crownstones.update(),
72+
sphere.crownstones.update_state(),
6873
sphere.locations.update(),
74+
sphere.locations.update_presence(),
6975
sphere.users.update()
7076
)
7177
_LOGGER.warning("Cloud data successfully initialized")

crownstone_cloud/lib/cloudModels/crownstones.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from crownstone_cloud._RequestHandlerInstance import RequestHandler
2-
from typing import Optional, ValuesView
2+
from typing import Optional
33
import logging
44
import asyncio
55

@@ -29,6 +29,8 @@ async def update(self) -> None:
2929
for crownstone in crownstone_data:
3030
self.crownstones[crownstone['id']] = Crownstone(self.loop, crownstone)
3131

32+
async def update_state(self) -> None:
33+
"""Replaces the switch state of all crownstones with that of the cloud."""
3234
for crownstone in self.crownstones.values():
3335
crownstone_state = await RequestHandler.get('Stones', 'currentSwitchState', model_id=crownstone.cloud_id)
3436
crownstone.state = crownstone_state['switchState']
@@ -37,6 +39,10 @@ def update_sync(self) -> None:
3739
"""Sync function for updating the crownstone data"""
3840
self.loop.run_until_complete(self.update())
3941

42+
def update_state_sync(self) -> None:
43+
"""Sync function for updating the crownstone state"""
44+
self.loop.run_until_complete(self.update_state())
45+
4046
def find(self, crownstone_name: str) -> object or None:
4147
"""Search for a crownstone by name and return crownstone object if found"""
4248
for crownstone in self.crownstones.values():

crownstone_cloud/lib/cloudModels/locations.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ async def update(self) -> None:
2626
for location in location_data:
2727
self.locations[location['id']] = Location(location)
2828

29+
async def update_presence(self) -> None:
30+
"""Replaces the current presence with that of the cloud."""
2931
presence_data = await RequestHandler.get('Spheres', 'presentPeople', model_id=self.sphere_id)
3032
for presence in presence_data:
3133
for present_location in presence['locations']:
@@ -37,6 +39,10 @@ def update_sync(self) -> None:
3739
"""Sync function for updating the location data"""
3840
self.loop.run_until_complete(self.update())
3941

42+
def update_presence_sync(self) -> None:
43+
"""Sync function for updating the presence"""
44+
self.loop.run_until_complete(self.update_presence())
45+
4046
def find(self, location_name: str) -> object or None:
4147
"""Search for a sphere by name and return sphere object if found"""
4248
for location in self.locations.values():

crownstone_cloud/lib/requestHandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ async def raise_on_error(self, data) -> bool:
105105
if 'code' in error:
106106
error_type = error['code']
107107
try:
108-
if error_type == 'INVALID_TOKEN':
108+
if error_type == 'INVALID_TOKEN' or error_type == 'AUTHORIZATION_REQUIRED':
109109
_LOGGER.warning("Token expired. Refreshing now...")
110110
await self.refresh_token()
111111
return True # re-run the request

crownstone_cloud/util/__init__.py

Whitespace-only changes.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from crownstone_cloud import CrownstoneCloud
2+
3+
4+
class CloudDataUpdater:
5+
"""
6+
Optional API.
7+
Contains callbacks that can be used with the Crownstone SSE lib, or own events.
8+
"""
9+
def __init__(self, cloud_instance: CrownstoneCloud) -> None:
10+
"""
11+
:param cloud_instance: your instance of the cloud lib.
12+
13+
Make sure your instance is initialized with data first!
14+
"""
15+
self.cloud_instance = cloud_instance
16+
17+
def update_switch_state(self, switch_state_event) -> None:
18+
"""
19+
Updates the switch state of a crownstone.
20+
21+
:param switch_state_event: Instance of SwitchStateUpdateEvent of the Crownstone SSE lib.
22+
23+
SwitchStateUpdateEvent is a class containing: sphere_id, cloud_id, unique_id, switch_state.
24+
"""
25+
sphere = self.cloud_instance.spheres.find_by_id(switch_state_event.sphere_id)
26+
crownstone = sphere.crownstones.find_by_id(switch_state_event.cloud_id)
27+
crownstone.state = switch_state_event.switch_state
28+
29+
def update_presence(self, presence_event) -> None:
30+
"""
31+
Updates the presence in a location.
32+
33+
:param presence_event: Instance of PresenceEvent of the Crownstone SSE lib.
34+
35+
PresenceEvent is a class containing: event_type, sphere_id, location_id, user_id.
36+
"""
37+
sphere = self.cloud_instance.spheres.find_by_id(presence_event.sphere_id)
38+
location = sphere.locations.find_by_id(presence_event.location_id)
39+
user = sphere.users.find_by_id(presence_event.user_id)
40+
41+
if presence_event.type == 'enterLocation':
42+
location.present_people.append(user.cloud_id)
43+
44+
if presence_event.type == 'exitLocation':
45+
location.present_people.remove(user.cloud_id)
46+
47+
def update_data(self, data_change_event) -> None:
48+
"""
49+
Replace the current data with new data from the cloud after a change.
50+
51+
:param data_change_event: Instance of DataChangeEvent of the Crownstone SSE lib.
52+
53+
DataChangeEvent is a class containing: operation, sphere_id, changed_item_id, changed_item_name
54+
"""
55+
if data_change_event.type == 'spheres':
56+
self.cloud_instance.spheres.update_sync()
57+
58+
sphere = self.cloud_instance.spheres.find_by_id(data_change_event.sphere_id)
59+
60+
if data_change_event.type == 'stones':
61+
sphere.crownstones.update_sync()
62+
63+
if data_change_event.type == 'users':
64+
sphere.users.update_sync()
65+
66+
if data_change_event.type == 'locations':
67+
sphere.locations.update_sync()

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
aiohttp==3.6.2
1+
aiohttp==3.6.2
2+
asynctest~=0.13.0

0 commit comments

Comments
 (0)