├── .coveragerc ├── .gitignore ├── .travis.yml ├── LICENSE.rst ├── MANIFEST.in ├── README.rst ├── beddit ├── __init__.py ├── client.py ├── compatibility.py ├── group.py ├── session.py ├── sleep.py └── user.py ├── requirements.txt ├── runtests.py ├── setup.py ├── tests ├── __init__.py ├── compatibility.py ├── fixtures │ ├── group.json │ ├── session.json │ ├── session_sample.json │ ├── sleep.json │ └── user.json ├── test_client.py ├── test_group.py ├── test_session.py ├── test_sleep.py └── test_user.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | include = 3 | beddit/*.py 4 | tests/*.py 5 | omit = 6 | beddit/__init__.py 7 | tests/__init__.py 8 | */compatibility.py 9 | exclude_lines = 10 | pragma: no cover 11 | if __name__ == .__main__.: 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/d1caffed352607b5415e9e0e827f4770eb39e316/Python.gitignore 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # IPython Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # dotenv 81 | .env 82 | 83 | # virtualenv 84 | venv/ 85 | ENV/ 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | 90 | # Rope project settings 91 | .ropeproject 92 | 93 | 94 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | python: 4 | - 2.7 5 | - 3.3 6 | - 3.4 7 | - 3.5 8 | install: 9 | - pip install tox-travis 10 | - pip install "tox>=1.8" 11 | - pip install coverage coveralls 12 | script: 13 | - tox -r 14 | after_success: 15 | - coverage report 16 | - coveralls 17 | -------------------------------------------------------------------------------- /LICENSE.rst: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Kohki Miki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE.rst 3 | include requirements.txt 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | beddit-python 3 | ============================ 4 | .. image:: https://travis-ci.org/giginet/beddit-python.svg?branch=master 5 | :target: https://travis-ci.org/giginet/beddit-python 6 | .. image:: https://coveralls.io/repos/github/giginet/beddit-python/badge.svg?branch=master 7 | :target: https://coveralls.io/github/giginet/beddit-python?branch=master 8 | 9 | API Client for Beddit_ in Python. 10 | 11 | .. _Beddit: http://www.beddit.com 12 | 13 | Read `API Documentation`_ for detail. 14 | 15 | .. _API Documentation: https://github.com/beddit/beddit-api 16 | 17 | Installation 18 | --------------------- 19 | 20 | .. code:: sh 21 | 22 | pip install beddit-python 23 | 24 | 25 | Usage 26 | -------------- 27 | 28 | List sleep scores per day 29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | 31 | .. code:: python 32 | 33 | from datetime import datetime 34 | from beddit.client import BedditClient 35 | 36 | client = BedditClient('user@example.com', password) 37 | 38 | start_date = datetime(2016, 7, 1) 39 | end_date = datetime(2016, 7, 31) 40 | 41 | sleeps = client.get_sleeps(start=start_date, end=end_date) 42 | for sleep in sleeps: 43 | print(sleep.date.strftime('%Y-%m-%d'), sleep.property.total_sleep_score) 44 | 45 | 46 | .. code:: txt 47 | 48 | 2016-07-01 75 49 | 2016-07-02 92 50 | .... 51 | 52 | Get user information 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | 55 | .. code:: python 56 | 57 | import os 58 | from beddit.client import BedditClient 59 | 60 | client = BedditClient(os.environ.get('BEDDIT_USERNAME'), os.environ.get('BEDDIT_PASSWORD')) 61 | 62 | user = client.get_user() 63 | print(user.name) 64 | print(user.height) 65 | print(user.weight) 66 | 67 | 68 | 69 | Supported Python 70 | ------------------------ 71 | 72 | Python 2.7, 3.3, 3.4, 3.5 73 | 74 | LICENSE 75 | ---------------- 76 | 77 | MIT License 78 | 79 | -------------------------------------------------------------------------------- /beddit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giginet/beddit-python/c6fde02abb8c79f4a3824929fa98f1531c7c756a/beddit/__init__.py -------------------------------------------------------------------------------- /beddit/client.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import json 4 | from .user import User 5 | from .group import Group 6 | from .sleep import Sleep 7 | from .session import Session 8 | from .compatibility import urljoin 9 | 10 | 11 | def auth_required(func): 12 | def _is_logged_in(self, *args, **kwargs): 13 | if not self.access_token or not self.user_id: 14 | raise BedditClient.AuthError('authentication is required') 15 | return func(self, *args, **kwargs) 16 | return _is_logged_in 17 | 18 | 19 | def datetime_to_timestamp(datetime): 20 | return time.mktime(datetime.timetuple()) 21 | 22 | 23 | class BedditClient(object): 24 | class ArgumentError(BaseException): 25 | pass 26 | 27 | class AuthError(BaseException): 28 | pass 29 | 30 | class APIError(BaseException): 31 | pass 32 | 33 | BASE_URL = 'https://cloudapi.beddit.com' 34 | access_token = None 35 | user_id = None 36 | 37 | @classmethod 38 | def build_full_path(cls, path): 39 | return urljoin(cls.BASE_URL, path) 40 | 41 | def __init__(self, username=None, password=None, access_token=None, user_id=None): 42 | if access_token and user_id: 43 | self.user_id = user_id 44 | self.access_token = access_token 45 | elif username and password: 46 | payload = { 47 | 'grant_type': 'password', 48 | 'username': username, 49 | 'password': password 50 | } 51 | endpoint = BedditClient.build_full_path('/api/v1/auth/authorize') 52 | r = requests.post(endpoint, data=payload) 53 | if r.status_code == 200: 54 | response_object = r.json() 55 | self.access_token = response_object['access_token'] 56 | self.user_id = response_object['user'] 57 | else: 58 | response = r.json() 59 | if response['description']: 60 | raise BedditClient.AuthError(response['description']) 61 | else: 62 | raise BedditClient.AuthError('Authentication is failed') 63 | else: 64 | raise BedditClient.ArgumentError('you must either use both access_token and user_id or both username and password') 65 | 66 | @property 67 | def _headers(self): 68 | return {'Authorization': "UserToken {}".format(self.access_token)} 69 | 70 | def _get_with_auth(self, path, params={}): 71 | endpoint = BedditClient.build_full_path(path) 72 | r = requests.get(endpoint, 73 | params=params, 74 | headers=self._headers) 75 | return r 76 | 77 | def _post_with_auth(self, path, params={}): 78 | endpoint = BedditClient.build_full_path(path) 79 | r = requests.post(endpoint, 80 | data=params, 81 | headers=self._headers) 82 | return r 83 | 84 | def _put_with_auth(self, path, params={}): 85 | endpoint = BedditClient.build_full_path(path) 86 | r = requests.put(endpoint, 87 | data=params, 88 | headers=self._headers) 89 | return r 90 | 91 | @auth_required 92 | def get_sleeps(self, user_id=None, start=None, end=None, updated_after=None, limit=None, reverse=False): 93 | params = {} 94 | if start: 95 | params['start_date'] = start.strftime('%Y-%m-%d') 96 | if end: 97 | params['end_date'] = end.strftime('%Y-%m-%d') 98 | if updated_after: 99 | params['updated_after'] = updated_after.timestamp() 100 | if limit: 101 | params['limit'] = limit 102 | if reverse: 103 | params['reverse'] = 'yes' 104 | 105 | if not user_id: 106 | user_id = self.user_id 107 | path = "/api/v1/user/{}/sleep".format(user_id) 108 | r = self._get_with_auth(path, params=params) 109 | if r.status_code == 200: 110 | return [Sleep(sleep) for sleep in r.json()] 111 | else: 112 | raise BedditClient.APIError(r.json()['description']) 113 | 114 | @auth_required 115 | def get_sessions(self, start=None, end=None, updated_after=None): 116 | params = {} 117 | 118 | if updated_after and not start and not end: 119 | params['updated_after'] = datetime_to_timestamp(updated_after) 120 | elif not updated_after and start and end: 121 | params['start_timestamp'] = datetime_to_timestamp(start) 122 | params['end_timestamp'] = datetime_to_timestamp(end) 123 | else: 124 | raise BedditClient.ArgumentError('you must either use the updated_after or both start and end.') 125 | 126 | path = "/api/v1/user/{}/session".format(self.user_id) 127 | r = self._get_with_auth(path, params=params) 128 | if r.status_code == 200: 129 | return [Session(session) for session in r.json()] 130 | else: 131 | raise BedditClient.APIError(r.json()['description']) 132 | 133 | @classmethod 134 | def reset_password(cls, email): 135 | path = "/api/v1/user/password_reset" 136 | endpoint = BedditClient.build_full_path(path) 137 | r = requests.post(endpoint, data={'email': email}) 138 | if r.status_code == 200: 139 | return True 140 | else: 141 | raise BedditClient.APIError(r.status_code) 142 | 143 | @auth_required 144 | def get_user(self, user_id=None): 145 | if not user_id: 146 | user_id = self.user_id 147 | 148 | path = "/api/v1/user/{}".format(user_id) 149 | r = self._get_with_auth(path) 150 | if r.status_code == 200: 151 | return User(r.json()) 152 | else: 153 | raise BedditClient.APIError(r.json()['description']) 154 | 155 | @auth_required 156 | def update_user(self, user_id=None, **params): 157 | if not user_id: 158 | user_id = self.user_id 159 | 160 | path = "/api/v1/user/{}".format(user_id) 161 | r = self._put_with_auth(path, params=json.dumps(params)) 162 | if r.status_code == 200: 163 | return User(r.json()) 164 | else: 165 | raise BedditClient.APIError(r.json()['description']) 166 | 167 | @auth_required 168 | def get_groups(self, user_id=None): 169 | if not user_id: 170 | user_id = self.user_id 171 | 172 | path = "/api/v1/user/{}/group".format(user_id) 173 | r = self._get_with_auth(path) 174 | if r.status_code == 200: 175 | return [Group(group) for group in r.json()] 176 | else: 177 | raise BedditClient.APIError(r.json()['description']) 178 | 179 | @auth_required 180 | def invite_to_group(self, email, group_id=None): 181 | if group_id: 182 | path = "/api/v1/group/{}/invite".format(group_id) 183 | else: 184 | path = "/api/v1/group/new/invite" 185 | 186 | r = self._post_with_auth(path, params={'email': email}) 187 | if r.status_code == 200: 188 | return [Group(group) for group in r.json()] 189 | else: 190 | raise BedditClient.APIError(r.json()['description']) 191 | 192 | @auth_required 193 | def remove_group_invite(self, group_id, user_id): 194 | path = '/api/v1/group/{}/member/{}/remove'.format(group_id, user_id) 195 | r = self._post_with_auth(path) 196 | if r.status_code == 200: 197 | return [Group(group) for group in r.json()] 198 | else: 199 | raise BedditClient.APIError(r.json()['description']) 200 | -------------------------------------------------------------------------------- /beddit/compatibility.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib.parse import urljoin 3 | except ImportError: 4 | from urlparse import urljoin 5 | -------------------------------------------------------------------------------- /beddit/group.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from .user import User 3 | 4 | 5 | class PendingInvite(object): 6 | def __init__(self, response_object): 7 | self.created = datetime.utcfromtimestamp(response_object['created']) 8 | self.created_by = response_object['created_by'] 9 | self.email = response_object['email'] 10 | 11 | 12 | class Group(object): 13 | def __init__(self, response_object): 14 | self.id = int(response_object['id']) 15 | self.created = datetime.utcfromtimestamp(response_object['created']) 16 | self.members = [User(user) for user in response_object['members']] 17 | self.pending_invites = [PendingInvite(invitation) for invitation in response_object['pending_invites']] 18 | -------------------------------------------------------------------------------- /beddit/session.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | from enum import Enum 3 | from pytz import timezone 4 | 5 | 6 | class SensorStatus(Enum): 7 | Operational = 1 8 | Interference = 2 9 | Unclear = 3 10 | 11 | 12 | class SampledTrack(object): 13 | def __init__(self, obj): 14 | self.samples_per_frame = obj['samples_per_frame'] 15 | self.data_url = obj.get('data_url', None) 16 | self.data_type = obj['data_type'] 17 | 18 | 19 | class Session(object): 20 | def __init__(self, response_object): 21 | self.timezone = timezone(response_object['timezone']) 22 | self.id = response_object['id'] 23 | self.start = datetime.fromtimestamp(response_object['start_timestamp'], tz=self.timezone) 24 | self.end = datetime.fromtimestamp(response_object['end_timestamp'], tz=self.timezone) 25 | 26 | self.hardware = response_object.get("hardware", None) 27 | 28 | self.software = response_object["software"] 29 | self.frame_length = response_object.get("frame_length", None) 30 | self.error_code = response_object.get("error_code", None) 31 | self.sampled_tracks = {key: SampledTrack(value) for key, value in response_object.get('sampled_tracks', {}).items()} 32 | 33 | time_value_tracks = response_object['time_value_tracks'] 34 | 35 | def parse(name, initializer=float): 36 | if name in time_value_tracks: 37 | 38 | def datetime_from_start(timestamp): 39 | td = timedelta(seconds=timestamp) 40 | return self.start + td 41 | 42 | value = {datetime_from_start(float(timestamp)): initializer(v) 43 | for timestamp, v in time_value_tracks[name]['items']} 44 | setattr(self, name, value) 45 | else: 46 | setattr(self, name, []) 47 | parse('respiration_cycle_amplitudes') 48 | parse('heartbeat') 49 | parse('heart_rate') 50 | parse('signal_high_percentile') 51 | parse('repiration_cycles') 52 | parse('events') 53 | parse('actigram') 54 | parse('sensor_status', initializer=SensorStatus) 55 | parse('snoring_events') 56 | parse('activity_segment_length') 57 | parse('high_activity_intervals') 58 | parse('activity_segment_variation') 59 | 60 | self.updated = datetime.fromtimestamp(response_object['updated'], tz=self.timezone) 61 | -------------------------------------------------------------------------------- /beddit/sleep.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from enum import Enum 3 | from pytz import timezone 4 | 5 | 6 | class SleepStage(Enum): 7 | Away = 65 8 | Sleep = 83 9 | RestlessSleep = 82 10 | Awake = 87 11 | NoSignal = 78 12 | GapInMeasurement = 71 13 | 14 | 15 | class Presence(Enum): 16 | Away = 65 17 | Present = 80 18 | End = 78 19 | 20 | 21 | class Sleep(object): 22 | class Property(object): 23 | def __init__(self, properties): 24 | for p in properties: 25 | score = int(properties[p]) 26 | setattr(self, p, score) 27 | 28 | def __init__(self, response_object): 29 | self.timezone = timezone(response_object['timezone']) 30 | self.date = datetime.strptime(response_object['date'], '%Y-%m-%d').replace(tzinfo=self.timezone) 31 | self.start = datetime.fromtimestamp(response_object['start_timestamp'], tz=self.timezone) 32 | self.end = datetime.fromtimestamp(response_object['end_timestamp'], tz=self.timezone) 33 | self.session_range_start = datetime.fromtimestamp(response_object['session_range_start'], tz=self.timezone) 34 | self.session_range_end = datetime.fromtimestamp(response_object['session_range_end'], tz=self.timezone) 35 | self.updated = datetime.fromtimestamp(response_object['updated'], tz=self.timezone) 36 | 37 | # properties 38 | self.property = self.Property(response_object['properties']) 39 | 40 | time_value_tracks = response_object['time_value_tracks'] 41 | self.actigram = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): float(value) 42 | for timestamp, value in time_value_tracks['actigram_epochwise']['items']} 43 | self.sleep_event = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): SleepStage(value) 44 | for timestamp, value in time_value_tracks['sleep_stages']['items']} 45 | self.presence = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): Presence(value) 46 | for timestamp, value in time_value_tracks['presence']['items']} 47 | self.snoring_episodes = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): value 48 | for timestamp, value in time_value_tracks['presence']['items']} 49 | 50 | self.nap_periods = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): float(value) 51 | for timestamp, value in time_value_tracks['nap_periods']['items']} 52 | self.heart_rate_curve = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): float(value) 53 | for timestamp, value in time_value_tracks['heart_rate_curve']['items']} 54 | self.sleep_cycles = {datetime.fromtimestamp(float(timestamp), tz=self.timezone): float(value) 55 | for timestamp, value in time_value_tracks['sleep_cycles']['items']} 56 | -------------------------------------------------------------------------------- /beddit/user.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | from enum import Enum 3 | 4 | 5 | class Sex(Enum): 6 | Unknown = None 7 | Male = 'male' 8 | Female = 'female' 9 | 10 | 11 | class User(object): 12 | def __init__(self, response_object): 13 | self.id = response_object['id'] 14 | self.email = response_object['email'] 15 | self.name = response_object['name'] 16 | self.date_of_birth = datetime.strptime(response_object['date_of_birth'], '%Y-%m-%d') 17 | self.sex = Sex(response_object['sex']) 18 | self.weight = float(response_object['weight']) 19 | self.height = float(response_object['height']) 20 | self.sleep_time_goal = timedelta(seconds=response_object['sleep_time_goal']) 21 | self.tip_audiences = response_object['tip_audiences'] 22 | self.created = datetime.utcfromtimestamp(response_object['created']) 23 | self.updated = datetime.utcfromtimestamp(response_object['updated']) 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytz 2 | requests 3 | -------------------------------------------------------------------------------- /runtests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | if __name__ == '__main__': 4 | suite = unittest.TestLoader().discover('tests') 5 | unittest.TextTestRunner(verbosity=1).run(suite) 6 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import sys 3 | from setuptools import setup, find_packages 4 | 5 | NAME = 'beddit-python' 6 | VERSION = '0.1.1' 7 | 8 | 9 | def read(filename): 10 | import os 11 | BASE_DIR = os.path.dirname(__file__) 12 | filename = os.path.join(BASE_DIR, filename) 13 | with open(filename, 'r') as fi: 14 | return fi.read() 15 | 16 | 17 | def readlist(filename): 18 | rows = read(filename).split("\n") 19 | rows = [x.strip() for x in rows if x.strip()] 20 | return list(rows) 21 | 22 | 23 | def requirements(): 24 | requires = readlist('requirements.txt') 25 | if sys.version_info < (3, 4): 26 | requires.append('enum34') 27 | return requires 28 | 29 | 30 | def requirements_test(): 31 | if sys.version_info < (3, 0): 32 | return ['mock'] 33 | return [] 34 | 35 | setup( 36 | name=NAME, 37 | version=VERSION, 38 | description='API client for Beddit sleep tracker', 39 | long_description=read('README.rst'), 40 | classifiers=[ 41 | 'Development Status :: 4 - Beta', 42 | 'Environment :: Web Environment', 43 | 'Intended Audience :: Developers', 44 | 'License :: OSI Approved :: MIT License', 45 | 'Programming Language :: Python', 46 | 'Programming Language :: Python :: 2', 47 | 'Programming Language :: Python :: 2.7', 48 | 'Programming Language :: Python :: 3', 49 | 'Programming Language :: Python :: 3.3', 50 | 'Programming Language :: Python :: 3.4', 51 | 'Programming Language :: Python :: 3.5', 52 | 'Topic :: Internet :: WWW/HTTP', 53 | 'Topic :: Software Development :: Libraries', 54 | 'Topic :: Software Development :: Libraries :: Python Modules', 55 | ], 56 | keywords='beddit api client sleep IoT', 57 | author='giginet', 58 | author_email='giginet.net@gmail.com', 59 | url='https://github.com/giginet/%s' % NAME, 60 | download_url='https://github.com/giginet/%s/tarball/master' % NAME, 61 | license='MIT', 62 | packages=find_packages(), 63 | include_package_data=True, 64 | package_data={ 65 | '': ['README.rst', 66 | 'LICENSE.rst', 67 | 'requirements.txt', 68 | 'requirements-test.txt'], 69 | }, 70 | zip_safe=True, 71 | install_requires=requirements(), 72 | test_suite='tests', 73 | tests_require=requirements_test(), 74 | ) 75 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | from tests import test_client 2 | from tests import test_group 3 | from tests import test_session 4 | from tests import test_sleep 5 | from tests import test_user 6 | -------------------------------------------------------------------------------- /tests/compatibility.py: -------------------------------------------------------------------------------- 1 | try: 2 | from unittest.mock import patch, Mock 3 | except ImportError: 4 | from mock import patch, Mock 5 | -------------------------------------------------------------------------------- /tests/fixtures/group.json: -------------------------------------------------------------------------------- 1 | { 2 | "id":1234, 3 | "created":1371472503.646541, 4 | "members":[ 5 | { 6 | "updated":1471356194.0, 7 | "weight":60.0, 8 | "height":175.0, 9 | "sleep_time_goal":27000.0, 10 | "tip_audiences":[ 11 | "general" 12 | ], 13 | "sex":null, 14 | "id":10000, 15 | "name":"John Doe", 16 | "created":1468327763.0, 17 | "date_of_birth":"1990-01-01", 18 | "email":"beddit@example.com" 19 | } 20 | ], 21 | "pending_invites":[ 22 | { 23 | "created":1371472503.646541, 24 | "created_by":132, 25 | "email":"example@beddit.com" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/fixtures/session_sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 1431835725, 3 | "start_timestamp" : 1431835725.618702, 4 | "end_timestamp" : 1431865087.218702, 5 | "timezone" : "America/New_York", 6 | "hardware" : "1.0/39bc22e bl:1.1 hw:1", 7 | "software" : "1.11.0 (101)", 8 | "frame_length" : 0.2, 9 | "error_code" : 0, 10 | "sampled_tracks" : { 11 | "normal" : { 12 | "samples_per_frame" : 28, 13 | "data_url" : "https://bedditcloud-sleepdata...", 14 | "data_type" : "uint16" 15 | }, 16 | "noise" : { 17 | "samples_per_frame" : 2, 18 | "data_url" : "https://bedditcloud-sleepdata...", 19 | "data_type" : "float32" 20 | } 21 | }, 22 | "time_value_tracks" : { 23 | "actigram" : { 24 | "value_data_type" : "float32", 25 | "items" : [ 26 | [0, 29973.82] 27 | ] 28 | }, 29 | "snoring_events" : { 30 | "value_data_type" : "float32", 31 | "items" : [] 32 | }, 33 | "respiration_cycles" : { 34 | "value_data_type" : "float32", 35 | "items" : [ 36 | [40.3, 4.1] 37 | ] 38 | }, 39 | "heart_rate" : { 40 | "value_data_type" : "float32", 41 | "items" : [ 42 | [60, 64.59961] 43 | ] 44 | }, 45 | "sensor_status" : { 46 | "value_data_type" : "uint8", 47 | "items" : [ 48 | [58.4, 1], 49 | [29316.8, 1] 50 | ] 51 | } 52 | }, 53 | "updated" : 1371482503.646541 54 | } 55 | -------------------------------------------------------------------------------- /tests/fixtures/sleep.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "updated":1471303494.441255, 4 | "tags":[ 5 | "not_enough_sleep", 6 | "long_sleep_latency" 7 | ], 8 | "session_range_end":1471303494.304574, 9 | "start_timestamp":1471271701.304574, 10 | "session_range_start":1471271701.304574, 11 | "time_value_tracks":{ 12 | "snoring_episodes":{ 13 | "items":[ 14 | 15 | ], 16 | "value_data_type":"float32" 17 | }, 18 | "presence":{ 19 | "items":[ 20 | [ 21 | 1471271701.304574, 22 | 80 23 | ], 24 | [ 25 | 1471274101.304574, 26 | 65 27 | ], 28 | [ 29 | 1471274206.304574, 30 | 80 31 | ], 32 | [ 33 | 1471275418.304574, 34 | 65 35 | ], 36 | [ 37 | 1471275499.304574, 38 | 80 39 | ], 40 | [ 41 | 1471276018.304574, 42 | 65 43 | ], 44 | [ 45 | 1471276273.304574, 46 | 80 47 | ], 48 | [ 49 | 1471276993.304574, 50 | 65 51 | ], 52 | [ 53 | 1471277164.304574, 54 | 80 55 | ], 56 | [ 57 | 1471279243.304574, 58 | 65 59 | ], 60 | [ 61 | 1471279321.304574, 62 | 80 63 | ], 64 | [ 65 | 1471280683.304574, 66 | 65 67 | ], 68 | [ 69 | 1471280734.304574, 70 | 80 71 | ], 72 | [ 73 | 1471281061.304574, 74 | 65 75 | ], 76 | [ 77 | 1471281109.304574, 78 | 80 79 | ], 80 | [ 81 | 1471281256.304574, 82 | 65 83 | ], 84 | [ 85 | 1471281721.304574, 86 | 80 87 | ], 88 | [ 89 | 1471301389.304574, 90 | 65 91 | ], 92 | [ 93 | 1471301863.304574, 94 | 80 95 | ], 96 | [ 97 | 1471303494.304574, 98 | 78 99 | ] 100 | ], 101 | "value_data_type":"uint8" 102 | }, 103 | "heart_rate_curve":{ 104 | "items":[ 105 | [ 106 | 1471271851.304574, 107 | 62.63658 108 | ], 109 | [ 110 | 1471272121.304574, 111 | 61.87636 112 | ], 113 | [ 114 | 1471272391.304574, 115 | 60.97872 116 | ], 117 | [ 118 | 1471272661.304574, 119 | 60.04105 120 | ], 121 | [ 122 | 1471272931.304574, 123 | 59.17064 124 | ], 125 | [ 126 | 1471273201.304574, 127 | 58.43846 128 | ], 129 | [ 130 | 1471273471.304574, 131 | 57.86841 132 | ], 133 | [ 134 | 1471273741.304574, 135 | 57.45359 136 | ], 137 | [ 138 | 1471274011.304574, 139 | 57.17458 140 | ], 141 | [ 142 | 1471275796.304574, 143 | -1 144 | ], 145 | [ 146 | 1471277581.304574, 147 | 61.5239 148 | ], 149 | [ 150 | 1471277875.304574, 151 | 61.93123 152 | ], 153 | [ 154 | 1471278169.304574, 155 | 62.3657 156 | ], 157 | [ 158 | 1471278463.304574, 159 | 62.80887 160 | ], 161 | [ 162 | 1471278757.304574, 163 | 63.23592 164 | ], 165 | [ 166 | 1471279051.304574, 167 | 63.62184 168 | ], 169 | [ 170 | 1471280551.304574, 171 | -1 172 | ], 173 | [ 174 | 1471282051.304574, 175 | 57.03327 176 | ], 177 | [ 178 | 1471282348.073805, 179 | 56.82242 180 | ], 181 | [ 182 | 1471282644.843035, 183 | 56.27057 184 | ], 185 | [ 186 | 1471282941.612266, 187 | 54.63978 188 | ], 189 | [ 190 | 1471283238.381497, 191 | 52.16257 192 | ], 193 | [ 194 | 1471283535.150728, 195 | 50.57847 196 | ], 197 | [ 198 | 1471283831.919959, 199 | 50.19911 200 | ], 201 | [ 202 | 1471284128.689189, 203 | 50.38454 204 | ], 205 | [ 206 | 1471284425.45842, 207 | 50.62543 208 | ], 209 | [ 210 | 1471284722.227651, 211 | 50.64314 212 | ], 213 | [ 214 | 1471285018.996882, 215 | 50.51146 216 | ], 217 | [ 218 | 1471285315.766113, 219 | 50.23912 220 | ], 221 | [ 222 | 1471285612.535343, 223 | 49.86904 224 | ], 225 | [ 226 | 1471285909.304574, 227 | 49.55513 228 | ], 229 | [ 230 | 1471286206.073805, 231 | 49.2816 232 | ], 233 | [ 234 | 1471286502.843035, 235 | 48.87523 236 | ], 237 | [ 238 | 1471286799.612266, 239 | 48.32054 240 | ], 241 | [ 242 | 1471287096.381497, 243 | 47.56644 244 | ], 245 | [ 246 | 1471287393.150728, 247 | 46.58322 248 | ], 249 | [ 250 | 1471287689.919959, 251 | 45.5936 252 | ], 253 | [ 254 | 1471287986.689189, 255 | 44.59049 256 | ], 257 | [ 258 | 1471288283.45842, 259 | 43.62611 260 | ], 261 | [ 262 | 1471288580.227651, 263 | 42.8988 264 | ], 265 | [ 266 | 1471288876.996882, 267 | 42.39175 268 | ], 269 | [ 270 | 1471289173.766113, 271 | 42.13291 272 | ], 273 | [ 274 | 1471289470.535343, 275 | 41.90181 276 | ], 277 | [ 278 | 1471289767.304574, 279 | 41.6539 280 | ], 281 | [ 282 | 1471290064.073805, 283 | 41.54634 284 | ], 285 | [ 286 | 1471290360.843035, 287 | 41.66116 288 | ], 289 | [ 290 | 1471290657.612266, 291 | 41.90859 292 | ], 293 | [ 294 | 1471290954.381497, 295 | 42.46593 296 | ], 297 | [ 298 | 1471291251.150728, 299 | 44.05619 300 | ], 301 | [ 302 | 1471291547.919959, 303 | 46.3861 304 | ], 305 | [ 306 | 1471291844.689189, 307 | 48.74503 308 | ], 309 | [ 310 | 1471292141.45842, 311 | 50.36564 312 | ], 313 | [ 314 | 1471292438.227651, 315 | 50.95593 316 | ], 317 | [ 318 | 1471292734.996882, 319 | 50.61172 320 | ], 321 | [ 322 | 1471293031.766113, 323 | 49.93097 324 | ], 325 | [ 326 | 1471293328.535343, 327 | 49.09637 328 | ], 329 | [ 330 | 1471293625.304574, 331 | 48.167 332 | ], 333 | [ 334 | 1471293922.073805, 335 | 47.29314 336 | ], 337 | [ 338 | 1471294218.843035, 339 | 46.67207 340 | ], 341 | [ 342 | 1471294515.612266, 343 | 46.25134 344 | ], 345 | [ 346 | 1471294812.381497, 347 | 45.9056 348 | ], 349 | [ 350 | 1471295109.150728, 351 | 45.48126 352 | ], 353 | [ 354 | 1471295405.919959, 355 | 44.81023 356 | ], 357 | [ 358 | 1471295702.689189, 359 | 43.97517 360 | ], 361 | [ 362 | 1471295999.45842, 363 | 42.98652 364 | ], 365 | [ 366 | 1471296296.227651, 367 | 42.15085 368 | ], 369 | [ 370 | 1471296592.996882, 371 | 41.55727 372 | ], 373 | [ 374 | 1471296889.766113, 375 | 40.98151 376 | ], 377 | [ 378 | 1471297186.535343, 379 | 40.37354 380 | ], 381 | [ 382 | 1471297483.304574, 383 | 39.81243 384 | ], 385 | [ 386 | 1471297780.073805, 387 | 39.44584 388 | ], 389 | [ 390 | 1471298076.843035, 391 | 39.43487 392 | ], 393 | [ 394 | 1471298373.612266, 395 | 39.8405 396 | ], 397 | [ 398 | 1471298670.381497, 399 | 40.86671 400 | ], 401 | [ 402 | 1471298967.150728, 403 | 42.4552 404 | ], 405 | [ 406 | 1471299263.919959, 407 | 43.47453 408 | ], 409 | [ 410 | 1471299560.689189, 411 | 43.45704 412 | ], 413 | [ 414 | 1471299857.45842, 415 | 42.92355 416 | ], 417 | [ 418 | 1471300154.227651, 419 | 42.32153 420 | ], 421 | [ 422 | 1471300450.996882, 423 | 41.93509 424 | ], 425 | [ 426 | 1471300747.766113, 427 | 41.68883 428 | ], 429 | [ 430 | 1471301044.535343, 431 | 41.5456 432 | ], 433 | [ 434 | 1471301341.304574, 435 | 41.49703 436 | ], 437 | [ 438 | 1471301716.304574, 439 | -1 440 | ], 441 | [ 442 | 1471302091.304574, 443 | 38.75278 444 | ], 445 | [ 446 | 1471302338.804574, 447 | 38.7361 448 | ], 449 | [ 450 | 1471302586.304574, 451 | 38.70276 452 | ], 453 | [ 454 | 1471302833.804574, 455 | 38.64872 456 | ], 457 | [ 458 | 1471303081.304574, 459 | 38.57022 460 | ] 461 | ], 462 | "value_data_type":"float32" 463 | }, 464 | "sleep_cycles":{ 465 | "items":[ 466 | [ 467 | 1471283761.304574, 468 | 1 469 | ], 470 | [ 471 | 1471283881.304574, 472 | 1 473 | ], 474 | [ 475 | 1471284001.304574, 476 | 0.9978961 477 | ], 478 | [ 479 | 1471284121.304574, 480 | 0.9909727 481 | ], 482 | [ 483 | 1471284241.304574, 484 | 0.9780444 485 | ], 486 | [ 487 | 1471284361.304574, 488 | 0.9588018 489 | ], 490 | [ 491 | 1471284481.304574, 492 | 0.9334407 493 | ], 494 | [ 495 | 1471284601.304574, 496 | 0.9026994 497 | ], 498 | [ 499 | 1471284721.304574, 500 | 0.8679368 501 | ], 502 | [ 503 | 1471284841.304574, 504 | 0.830976 505 | ], 506 | [ 507 | 1471284961.304574, 508 | 0.7946212 509 | ], 510 | [ 511 | 1471285081.304574, 512 | 0.7622218 513 | ], 514 | [ 515 | 1471285201.304574, 516 | 0.7361534 517 | ], 518 | [ 519 | 1471285321.304574, 520 | 0.7176204 521 | ], 522 | [ 523 | 1471285441.304574, 524 | 0.7068353 525 | ], 526 | [ 527 | 1471285561.304574, 528 | 0.7030646 529 | ], 530 | [ 531 | 1471285681.304574, 532 | 0.7061182 533 | ], 534 | [ 535 | 1471285801.304574, 536 | 0.7164559 537 | ], 538 | [ 539 | 1471285921.304574, 540 | 0.7328856 541 | ], 542 | [ 543 | 1471286041.304574, 544 | 0.7528535 545 | ], 546 | [ 547 | 1471286161.304574, 548 | 0.7737426 549 | ], 550 | [ 551 | 1471286281.304574, 552 | 0.7931395 553 | ], 554 | [ 555 | 1471286401.304574, 556 | 0.809449 557 | ], 558 | [ 559 | 1471286521.304574, 560 | 0.8220297 561 | ], 562 | [ 563 | 1471286641.304574, 564 | 0.8317648 565 | ], 566 | [ 567 | 1471286761.304574, 568 | 0.8395958 569 | ], 570 | [ 571 | 1471286881.304574, 572 | 0.8451601 573 | ], 574 | [ 575 | 1471287001.304574, 576 | 0.8481414 577 | ], 578 | [ 579 | 1471287121.304574, 580 | 0.8492848 581 | ], 582 | [ 583 | 1471287241.304574, 584 | 0.8493727 585 | ], 586 | [ 587 | 1471287361.304574, 588 | 0.8484033 589 | ], 590 | [ 591 | 1471287481.304574, 592 | 0.8474622 593 | ], 594 | [ 595 | 1471287601.304574, 596 | 0.8476346 597 | ], 598 | [ 599 | 1471287721.304574, 600 | 0.8489168 601 | ], 602 | [ 603 | 1471287841.304574, 604 | 0.8512828 605 | ], 606 | [ 607 | 1471287961.304574, 608 | 0.8539866 609 | ], 610 | [ 611 | 1471288081.304574, 612 | 0.8561103 613 | ], 614 | [ 615 | 1471288201.304574, 616 | 0.8578486 617 | ], 618 | [ 619 | 1471288321.304574, 620 | 0.8595688 621 | ], 622 | [ 623 | 1471288441.304574, 624 | 0.8605384 625 | ], 626 | [ 627 | 1471288561.304574, 628 | 0.8596367 629 | ], 630 | [ 631 | 1471288681.304574, 632 | 0.8564793 633 | ], 634 | [ 635 | 1471288801.304574, 636 | 0.8507277 637 | ], 638 | [ 639 | 1471288921.304574, 640 | 0.8432354 641 | ], 642 | [ 643 | 1471289041.304574, 644 | 0.8352946 645 | ], 646 | [ 647 | 1471289161.304574, 648 | 0.8283409 649 | ], 650 | [ 651 | 1471289281.304574, 652 | 0.8230919 653 | ], 654 | [ 655 | 1471289401.304574, 656 | 0.8189567 657 | ], 658 | [ 659 | 1471289521.304574, 660 | 0.8150328 661 | ], 662 | [ 663 | 1471289641.304574, 664 | 0.8104132 665 | ], 666 | [ 667 | 1471289761.304574, 668 | 0.8059977 669 | ], 670 | [ 671 | 1471289881.304574, 672 | 0.8023869 673 | ], 674 | [ 675 | 1471290001.304574, 676 | 0.7997624 677 | ], 678 | [ 679 | 1471290121.304574, 680 | 0.7985803 681 | ], 682 | [ 683 | 1471290241.304574, 684 | 0.7985337 685 | ], 686 | [ 687 | 1471290361.304574, 688 | 0.7985947 689 | ], 690 | [ 691 | 1471290481.304574, 692 | 0.7980641 693 | ], 694 | [ 695 | 1471290601.304574, 696 | 0.7976507 697 | ], 698 | [ 699 | 1471290721.304574, 700 | 0.7987583 701 | ], 702 | [ 703 | 1471290841.304574, 704 | 0.802632 705 | ], 706 | [ 707 | 1471290961.304574, 708 | 0.8083671 709 | ], 710 | [ 711 | 1471291081.304574, 712 | 0.8140832 713 | ], 714 | [ 715 | 1471291201.304574, 716 | 0.8192957 717 | ], 718 | [ 719 | 1471291321.304574, 720 | 0.8249645 721 | ], 722 | [ 723 | 1471291441.304574, 724 | 0.8320401 725 | ], 726 | [ 727 | 1471291561.304574, 728 | 0.8409481 729 | ], 730 | [ 731 | 1471291681.304574, 732 | 0.8528827 733 | ], 734 | [ 735 | 1471291801.304574, 736 | 0.8684066 737 | ], 738 | [ 739 | 1471291921.304574, 740 | 0.8866341 741 | ], 742 | [ 743 | 1471292041.304574, 744 | 0.9066244 745 | ], 746 | [ 747 | 1471292161.304574, 748 | 0.9272728 749 | ], 750 | [ 751 | 1471292281.304574, 752 | 0.9467633 753 | ], 754 | [ 755 | 1471292401.304574, 756 | 0.9640015 757 | ], 758 | [ 759 | 1471292521.304574, 760 | 0.9786363 761 | ], 762 | [ 763 | 1471292641.304574, 764 | 0.9903699 765 | ], 766 | [ 767 | 1471292761.304574, 768 | 0.9978975 769 | ], 770 | [ 771 | 1471292881.304574, 772 | 1 773 | ], 774 | [ 775 | 1471293001.304574, 776 | 0.9966346 777 | ], 778 | [ 779 | 1471293121.304574, 780 | 0.9878698 781 | ], 782 | [ 783 | 1471293241.304574, 784 | 0.973884 785 | ], 786 | [ 787 | 1471293361.304574, 788 | 0.9540611 789 | ], 790 | [ 791 | 1471293481.304574, 792 | 0.9280707 793 | ], 794 | [ 795 | 1471293601.304574, 796 | 0.8966087 797 | ], 798 | [ 799 | 1471293721.304574, 800 | 0.8603157 801 | ], 802 | [ 803 | 1471293841.304574, 804 | 0.8203332 805 | ], 806 | [ 807 | 1471293961.304574, 808 | 0.778281 809 | ], 810 | [ 811 | 1471294081.304574, 812 | 0.7358209 813 | ], 814 | [ 815 | 1471294201.304574, 816 | 0.6930806 817 | ], 818 | [ 819 | 1471294321.304574, 820 | 0.6489849 821 | ], 822 | [ 823 | 1471294441.304574, 824 | 0.6023519 825 | ], 826 | [ 827 | 1471294561.304574, 828 | 0.5528569 829 | ], 830 | [ 831 | 1471294681.304574, 832 | 0.5015073 833 | ], 834 | [ 835 | 1471294801.304574, 836 | 0.4500464 837 | ], 838 | [ 839 | 1471294921.304574, 840 | 0.4002196 841 | ], 842 | [ 843 | 1471295041.304574, 844 | 0.3522354 845 | ], 846 | [ 847 | 1471295161.304574, 848 | 0.3058621 849 | ], 850 | [ 851 | 1471295281.304574, 852 | 0.2612379 853 | ], 854 | [ 855 | 1471295401.304574, 856 | 0.2188684 857 | ], 858 | [ 859 | 1471295521.304574, 860 | 0.1790464 861 | ], 862 | [ 863 | 1471295641.304574, 864 | 0.1420128 865 | ], 866 | [ 867 | 1471295761.304574, 868 | 0.1090913 869 | ], 870 | [ 871 | 1471295881.304574, 872 | 0.08082397 873 | ], 874 | [ 875 | 1471296001.304574, 876 | 0.05708846 877 | ], 878 | [ 879 | 1471296121.304574, 880 | 0.03779825 881 | ], 882 | [ 883 | 1471296241.304574, 884 | 0.02277629 885 | ], 886 | [ 887 | 1471296361.304574, 888 | 0.0116306 889 | ], 890 | [ 891 | 1471296481.304574, 892 | 0.00446002 893 | ], 894 | [ 895 | 1471296601.304574, 896 | 0.0009143898 897 | ], 898 | [ 899 | 1471296721.304574, 900 | 0 901 | ], 902 | [ 903 | 1471296841.304574, 904 | 0.001165727 905 | ], 906 | [ 907 | 1471296961.304574, 908 | 0.003710155 909 | ], 910 | [ 911 | 1471297081.304574, 912 | 0.008043277 913 | ], 914 | [ 915 | 1471297201.304574, 916 | 0.01447975 917 | ], 918 | [ 919 | 1471297321.304574, 920 | 0.02272167 921 | ], 922 | [ 923 | 1471297441.304574, 924 | 0.033171 925 | ], 926 | [ 927 | 1471297561.304574, 928 | 0.04618475 929 | ], 930 | [ 931 | 1471297681.304574, 932 | 0.06069227 933 | ], 934 | [ 935 | 1471297801.304574, 936 | 0.07639824 937 | ], 938 | [ 939 | 1471297921.304574, 940 | 0.09378865 941 | ], 942 | [ 943 | 1471298041.304574, 944 | 0.1125095 945 | ], 946 | [ 947 | 1471298161.304574, 948 | 0.1325825 949 | ], 950 | [ 951 | 1471298281.304574, 952 | 0.154002 953 | ], 954 | [ 955 | 1471298401.304574, 956 | 0.1763318 957 | ], 958 | [ 959 | 1471298521.304574, 960 | 0.1991175 961 | ], 962 | [ 963 | 1471298641.304574, 964 | 0.2218951 965 | ], 966 | [ 967 | 1471298761.304574, 968 | 0.2438181 969 | ], 970 | [ 971 | 1471298881.304574, 972 | 0.2642677 973 | ], 974 | [ 975 | 1471299001.304574, 976 | 0.2832575 977 | ], 978 | [ 979 | 1471299121.304574, 980 | 0.3004512 981 | ], 982 | [ 983 | 1471299241.304574, 984 | 0.315152 985 | ], 986 | [ 987 | 1471299361.304574, 988 | 0.3266989 989 | ], 990 | [ 991 | 1471299481.304574, 992 | 0.3348697 993 | ], 994 | [ 995 | 1471299601.304574, 996 | 0.3398862 997 | ], 998 | [ 999 | 1471299721.304574, 1000 | 0.342 1001 | ], 1002 | [ 1003 | 1471299841.304574, 1004 | 0.3414884 1005 | ], 1006 | [ 1007 | 1471299961.304574, 1008 | 0.3386522 1009 | ], 1010 | [ 1011 | 1471300081.304574, 1012 | 0.3330174 1013 | ], 1014 | [ 1015 | 1471300201.304574, 1016 | 0.3369571 1017 | ], 1018 | [ 1019 | 1471300321.304574, 1020 | 0.3726638 1021 | ], 1022 | [ 1023 | 1471300441.304574, 1024 | 0.4510965 1025 | ], 1026 | [ 1027 | 1471300561.304574, 1028 | 0.5678037 1029 | ], 1030 | [ 1031 | 1471300681.304574, 1032 | 0.7040361 1033 | ], 1034 | [ 1035 | 1471300801.304574, 1036 | 0.8299714 1037 | ], 1038 | [ 1039 | 1471300921.304574, 1040 | 0.9241955 1041 | ], 1042 | [ 1043 | 1471301041.304574, 1044 | 0.9802487 1045 | ], 1046 | [ 1047 | 1471301161.304574, 1048 | 1 1049 | ] 1050 | ], 1051 | "value_data_type":"float32" 1052 | }, 1053 | "actigram_epochwise":{ 1054 | "items":[ 1055 | [ 1056 | 1471271701.304574, 1057 | 14 1058 | ], 1059 | [ 1060 | 1471271761.304574, 1061 | 2 1062 | ], 1063 | [ 1064 | 1471271821.304574, 1065 | 0 1066 | ], 1067 | [ 1068 | 1471271881.304574, 1069 | 1 1070 | ], 1071 | [ 1072 | 1471271941.304574, 1073 | 1 1074 | ], 1075 | [ 1076 | 1471272001.304574, 1077 | 1 1078 | ], 1079 | [ 1080 | 1471272061.304574, 1081 | 0 1082 | ], 1083 | [ 1084 | 1471272121.304574, 1085 | 2 1086 | ], 1087 | [ 1088 | 1471272181.304574, 1089 | 0 1090 | ], 1091 | [ 1092 | 1471272241.304574, 1093 | 0 1094 | ], 1095 | [ 1096 | 1471272301.304574, 1097 | 0 1098 | ], 1099 | [ 1100 | 1471272361.304574, 1101 | 2 1102 | ], 1103 | [ 1104 | 1471272421.304574, 1105 | 2 1106 | ], 1107 | [ 1108 | 1471272481.304574, 1109 | 1 1110 | ], 1111 | [ 1112 | 1471272541.304574, 1113 | 1 1114 | ], 1115 | [ 1116 | 1471272601.304574, 1117 | 1 1118 | ], 1119 | [ 1120 | 1471272661.304574, 1121 | 1 1122 | ], 1123 | [ 1124 | 1471272721.304574, 1125 | 0 1126 | ], 1127 | [ 1128 | 1471272781.304574, 1129 | 1 1130 | ], 1131 | [ 1132 | 1471272841.304574, 1133 | 1 1134 | ], 1135 | [ 1136 | 1471272901.304574, 1137 | 0 1138 | ], 1139 | [ 1140 | 1471272961.304574, 1141 | 0 1142 | ], 1143 | [ 1144 | 1471273021.304574, 1145 | 0 1146 | ], 1147 | [ 1148 | 1471273081.304574, 1149 | 0 1150 | ], 1151 | [ 1152 | 1471273141.304574, 1153 | 1 1154 | ], 1155 | [ 1156 | 1471273201.304574, 1157 | 1 1158 | ], 1159 | [ 1160 | 1471273261.304574, 1161 | 0 1162 | ], 1163 | [ 1164 | 1471273321.304574, 1165 | 1 1166 | ], 1167 | [ 1168 | 1471273381.304574, 1169 | 0 1170 | ], 1171 | [ 1172 | 1471273441.304574, 1173 | 0 1174 | ], 1175 | [ 1176 | 1471273501.304574, 1177 | 1 1178 | ], 1179 | [ 1180 | 1471273561.304574, 1181 | 0 1182 | ], 1183 | [ 1184 | 1471273621.304574, 1185 | 2 1186 | ], 1187 | [ 1188 | 1471273681.304574, 1189 | 0 1190 | ], 1191 | [ 1192 | 1471273741.304574, 1193 | 0 1194 | ], 1195 | [ 1196 | 1471273801.304574, 1197 | 0 1198 | ], 1199 | [ 1200 | 1471273861.304574, 1201 | 3 1202 | ], 1203 | [ 1204 | 1471273921.304574, 1205 | 0 1206 | ], 1207 | [ 1208 | 1471273981.304574, 1209 | 0 1210 | ], 1211 | [ 1212 | 1471274041.304574, 1213 | 12 1214 | ], 1215 | [ 1216 | 1471274206.304574, 1217 | 10 1218 | ], 1219 | [ 1220 | 1471274266.304574, 1221 | 7 1222 | ], 1223 | [ 1224 | 1471274326.304574, 1225 | 2 1226 | ], 1227 | [ 1228 | 1471274386.304574, 1229 | 0 1230 | ], 1231 | [ 1232 | 1471274446.304574, 1233 | 1 1234 | ], 1235 | [ 1236 | 1471274506.304574, 1237 | 3 1238 | ], 1239 | [ 1240 | 1471274566.304574, 1241 | 0 1242 | ], 1243 | [ 1244 | 1471274626.304574, 1245 | 7 1246 | ], 1247 | [ 1248 | 1471274686.304574, 1249 | 0 1250 | ], 1251 | [ 1252 | 1471274746.304574, 1253 | 0 1254 | ], 1255 | [ 1256 | 1471274806.304574, 1257 | 4 1258 | ], 1259 | [ 1260 | 1471274866.304574, 1261 | 5 1262 | ], 1263 | [ 1264 | 1471274926.304574, 1265 | 7 1266 | ], 1267 | [ 1268 | 1471274986.304574, 1269 | 3 1270 | ], 1271 | [ 1272 | 1471275046.304574, 1273 | 1 1274 | ], 1275 | [ 1276 | 1471275106.304574, 1277 | 9 1278 | ], 1279 | [ 1280 | 1471275166.304574, 1281 | 4 1282 | ], 1283 | [ 1284 | 1471275226.304574, 1285 | 9 1286 | ], 1287 | [ 1288 | 1471275286.304574, 1289 | 14 1290 | ], 1291 | [ 1292 | 1471275346.304574, 1293 | 3 1294 | ], 1295 | [ 1296 | 1471275499.304574, 1297 | 7 1298 | ], 1299 | [ 1300 | 1471275559.304574, 1301 | 5 1302 | ], 1303 | [ 1304 | 1471275619.304574, 1305 | 11 1306 | ], 1307 | [ 1308 | 1471275679.304574, 1309 | 10 1310 | ], 1311 | [ 1312 | 1471275739.304574, 1313 | 10 1314 | ], 1315 | [ 1316 | 1471275799.304574, 1317 | 2 1318 | ], 1319 | [ 1320 | 1471275859.304574, 1321 | 4 1322 | ], 1323 | [ 1324 | 1471275919.304574, 1325 | 6 1326 | ], 1327 | [ 1328 | 1471276273.304574, 1329 | 18 1330 | ], 1331 | [ 1332 | 1471276333.304574, 1333 | 5 1334 | ], 1335 | [ 1336 | 1471276393.304574, 1337 | 9 1338 | ], 1339 | [ 1340 | 1471276453.304574, 1341 | 2 1342 | ], 1343 | [ 1344 | 1471276513.304574, 1345 | 1 1346 | ], 1347 | [ 1348 | 1471276573.304574, 1349 | 4 1350 | ], 1351 | [ 1352 | 1471276633.304574, 1353 | 1 1354 | ], 1355 | [ 1356 | 1471276693.304574, 1357 | 0 1358 | ], 1359 | [ 1360 | 1471276753.304574, 1361 | 2 1362 | ], 1363 | [ 1364 | 1471276813.304574, 1365 | 1 1366 | ], 1367 | [ 1368 | 1471276873.304574, 1369 | 1 1370 | ], 1371 | [ 1372 | 1471276933.304574, 1373 | 5 1374 | ], 1375 | [ 1376 | 1471277164.304574, 1377 | 14 1378 | ], 1379 | [ 1380 | 1471277224.304574, 1381 | 8 1382 | ], 1383 | [ 1384 | 1471277284.304574, 1385 | 2 1386 | ], 1387 | [ 1388 | 1471277344.304574, 1389 | 1 1390 | ], 1391 | [ 1392 | 1471277404.304574, 1393 | 11 1394 | ], 1395 | [ 1396 | 1471277464.304574, 1397 | 7 1398 | ], 1399 | [ 1400 | 1471277524.304574, 1401 | 1 1402 | ], 1403 | [ 1404 | 1471277584.304574, 1405 | 0 1406 | ], 1407 | [ 1408 | 1471277644.304574, 1409 | 1 1410 | ], 1411 | [ 1412 | 1471277704.304574, 1413 | 7 1414 | ], 1415 | [ 1416 | 1471277764.304574, 1417 | 3 1418 | ], 1419 | [ 1420 | 1471277824.304574, 1421 | 0 1422 | ], 1423 | [ 1424 | 1471277884.304574, 1425 | 0 1426 | ], 1427 | [ 1428 | 1471277944.304574, 1429 | 0 1430 | ], 1431 | [ 1432 | 1471278004.304574, 1433 | 0 1434 | ], 1435 | [ 1436 | 1471278064.304574, 1437 | 8 1438 | ], 1439 | [ 1440 | 1471278124.304574, 1441 | 2 1442 | ], 1443 | [ 1444 | 1471278184.304574, 1445 | 2 1446 | ], 1447 | [ 1448 | 1471278244.304574, 1449 | 3 1450 | ], 1451 | [ 1452 | 1471278304.304574, 1453 | 2 1454 | ], 1455 | [ 1456 | 1471278364.304574, 1457 | 4 1458 | ], 1459 | [ 1460 | 1471278424.304574, 1461 | 4 1462 | ], 1463 | [ 1464 | 1471278484.304574, 1465 | 11 1466 | ], 1467 | [ 1468 | 1471278544.304574, 1469 | 13 1470 | ], 1471 | [ 1472 | 1471278604.304574, 1473 | 0 1474 | ], 1475 | [ 1476 | 1471278664.304574, 1477 | 2 1478 | ], 1479 | [ 1480 | 1471278724.304574, 1481 | 2 1482 | ], 1483 | [ 1484 | 1471278784.304574, 1485 | 0 1486 | ], 1487 | [ 1488 | 1471278844.304574, 1489 | 10 1490 | ], 1491 | [ 1492 | 1471278904.304574, 1493 | 1 1494 | ], 1495 | [ 1496 | 1471278964.304574, 1497 | 2 1498 | ], 1499 | [ 1500 | 1471279024.304574, 1501 | 1 1502 | ], 1503 | [ 1504 | 1471279084.304574, 1505 | 4 1506 | ], 1507 | [ 1508 | 1471279144.304574, 1509 | 0 1510 | ], 1511 | [ 1512 | 1471279321.304574, 1513 | 9 1514 | ], 1515 | [ 1516 | 1471279381.304574, 1517 | 3 1518 | ], 1519 | [ 1520 | 1471279441.304574, 1521 | 0 1522 | ], 1523 | [ 1524 | 1471279501.304574, 1525 | 1 1526 | ], 1527 | [ 1528 | 1471279561.304574, 1529 | 1 1530 | ], 1531 | [ 1532 | 1471279621.304574, 1533 | 0 1534 | ], 1535 | [ 1536 | 1471279681.304574, 1537 | 1 1538 | ], 1539 | [ 1540 | 1471279741.304574, 1541 | 1 1542 | ], 1543 | [ 1544 | 1471279801.304574, 1545 | 1 1546 | ], 1547 | [ 1548 | 1471279861.304574, 1549 | 0 1550 | ], 1551 | [ 1552 | 1471279921.304574, 1553 | 5 1554 | ], 1555 | [ 1556 | 1471279981.304574, 1557 | 0 1558 | ], 1559 | [ 1560 | 1471280041.304574, 1561 | 1 1562 | ], 1563 | [ 1564 | 1471280101.304574, 1565 | 2 1566 | ], 1567 | [ 1568 | 1471280161.304574, 1569 | 1 1570 | ], 1571 | [ 1572 | 1471280221.304574, 1573 | 4 1574 | ], 1575 | [ 1576 | 1471280281.304574, 1577 | 0 1578 | ], 1579 | [ 1580 | 1471280341.304574, 1581 | 0 1582 | ], 1583 | [ 1584 | 1471280401.304574, 1585 | 2 1586 | ], 1587 | [ 1588 | 1471280461.304574, 1589 | 2 1590 | ], 1591 | [ 1592 | 1471280521.304574, 1593 | 0 1594 | ], 1595 | [ 1596 | 1471280581.304574, 1597 | 4 1598 | ], 1599 | [ 1600 | 1471280734.304574, 1601 | 13 1602 | ], 1603 | [ 1604 | 1471280794.304574, 1605 | 15 1606 | ], 1607 | [ 1608 | 1471280854.304574, 1609 | 7 1610 | ], 1611 | [ 1612 | 1471280914.304574, 1613 | 6 1614 | ], 1615 | [ 1616 | 1471280974.304574, 1617 | 0 1618 | ], 1619 | [ 1620 | 1471281109.304574, 1621 | 9 1622 | ], 1623 | [ 1624 | 1471281169.304574, 1625 | 4 1626 | ], 1627 | [ 1628 | 1471281721.304574, 1629 | 6 1630 | ], 1631 | [ 1632 | 1471281781.304574, 1633 | 0 1634 | ], 1635 | [ 1636 | 1471281841.304574, 1637 | 0 1638 | ], 1639 | [ 1640 | 1471281901.304574, 1641 | 3 1642 | ], 1643 | [ 1644 | 1471281961.304574, 1645 | 3 1646 | ], 1647 | [ 1648 | 1471282021.304574, 1649 | 3 1650 | ], 1651 | [ 1652 | 1471282081.304574, 1653 | 2 1654 | ], 1655 | [ 1656 | 1471282141.304574, 1657 | 2 1658 | ], 1659 | [ 1660 | 1471282201.304574, 1661 | 0 1662 | ], 1663 | [ 1664 | 1471282261.304574, 1665 | 0 1666 | ], 1667 | [ 1668 | 1471282321.304574, 1669 | 0 1670 | ], 1671 | [ 1672 | 1471282381.304574, 1673 | 0 1674 | ], 1675 | [ 1676 | 1471282441.304574, 1677 | 0 1678 | ], 1679 | [ 1680 | 1471282501.304574, 1681 | 0 1682 | ], 1683 | [ 1684 | 1471282561.304574, 1685 | 0 1686 | ], 1687 | [ 1688 | 1471282621.304574, 1689 | 3 1690 | ], 1691 | [ 1692 | 1471282681.304574, 1693 | 0 1694 | ], 1695 | [ 1696 | 1471282741.304574, 1697 | 2 1698 | ], 1699 | [ 1700 | 1471282801.304574, 1701 | 0 1702 | ], 1703 | [ 1704 | 1471282861.304574, 1705 | 1 1706 | ], 1707 | [ 1708 | 1471282921.304574, 1709 | 2 1710 | ], 1711 | [ 1712 | 1471282981.304574, 1713 | 1 1714 | ], 1715 | [ 1716 | 1471283041.304574, 1717 | 0 1718 | ], 1719 | [ 1720 | 1471283101.304574, 1721 | 0 1722 | ], 1723 | [ 1724 | 1471283161.304574, 1725 | 1 1726 | ], 1727 | [ 1728 | 1471283221.304574, 1729 | 1 1730 | ], 1731 | [ 1732 | 1471283281.304574, 1733 | 1 1734 | ], 1735 | [ 1736 | 1471283341.304574, 1737 | 1 1738 | ], 1739 | [ 1740 | 1471283401.304574, 1741 | 1 1742 | ], 1743 | [ 1744 | 1471283461.304574, 1745 | 3 1746 | ], 1747 | [ 1748 | 1471283521.304574, 1749 | 0 1750 | ], 1751 | [ 1752 | 1471283581.304574, 1753 | 1 1754 | ], 1755 | [ 1756 | 1471283641.304574, 1757 | 0 1758 | ], 1759 | [ 1760 | 1471283701.304574, 1761 | 0 1762 | ], 1763 | [ 1764 | 1471283761.304574, 1765 | 0 1766 | ], 1767 | [ 1768 | 1471283821.304574, 1769 | 0 1770 | ], 1771 | [ 1772 | 1471283881.304574, 1773 | 0 1774 | ], 1775 | [ 1776 | 1471283941.304574, 1777 | 0 1778 | ], 1779 | [ 1780 | 1471284001.304574, 1781 | 0 1782 | ], 1783 | [ 1784 | 1471284061.304574, 1785 | 0 1786 | ], 1787 | [ 1788 | 1471284121.304574, 1789 | 0 1790 | ], 1791 | [ 1792 | 1471284181.304574, 1793 | 5 1794 | ], 1795 | [ 1796 | 1471284241.304574, 1797 | 0 1798 | ], 1799 | [ 1800 | 1471284301.304574, 1801 | 3 1802 | ], 1803 | [ 1804 | 1471284361.304574, 1805 | 0 1806 | ], 1807 | [ 1808 | 1471284421.304574, 1809 | 0 1810 | ], 1811 | [ 1812 | 1471284481.304574, 1813 | 0 1814 | ], 1815 | [ 1816 | 1471284541.304574, 1817 | 0 1818 | ], 1819 | [ 1820 | 1471284601.304574, 1821 | 0 1822 | ], 1823 | [ 1824 | 1471284661.304574, 1825 | 0 1826 | ], 1827 | [ 1828 | 1471284721.304574, 1829 | 0 1830 | ], 1831 | [ 1832 | 1471284781.304574, 1833 | 0 1834 | ], 1835 | [ 1836 | 1471284841.304574, 1837 | 0 1838 | ], 1839 | [ 1840 | 1471284901.304574, 1841 | 0 1842 | ], 1843 | [ 1844 | 1471284961.304574, 1845 | 0 1846 | ], 1847 | [ 1848 | 1471285021.304574, 1849 | 0 1850 | ], 1851 | [ 1852 | 1471285081.304574, 1853 | 0 1854 | ], 1855 | [ 1856 | 1471285141.304574, 1857 | 0 1858 | ], 1859 | [ 1860 | 1471285201.304574, 1861 | 0 1862 | ], 1863 | [ 1864 | 1471285261.304574, 1865 | 3 1866 | ], 1867 | [ 1868 | 1471285321.304574, 1869 | 0 1870 | ], 1871 | [ 1872 | 1471285381.304574, 1873 | 7 1874 | ], 1875 | [ 1876 | 1471285441.304574, 1877 | 0 1878 | ], 1879 | [ 1880 | 1471285501.304574, 1881 | 0 1882 | ], 1883 | [ 1884 | 1471285561.304574, 1885 | 0 1886 | ], 1887 | [ 1888 | 1471285621.304574, 1889 | 0 1890 | ], 1891 | [ 1892 | 1471285681.304574, 1893 | 0 1894 | ], 1895 | [ 1896 | 1471285741.304574, 1897 | 3 1898 | ], 1899 | [ 1900 | 1471285801.304574, 1901 | 1 1902 | ], 1903 | [ 1904 | 1471285861.304574, 1905 | 0 1906 | ], 1907 | [ 1908 | 1471285921.304574, 1909 | 0 1910 | ], 1911 | [ 1912 | 1471285981.304574, 1913 | 0 1914 | ], 1915 | [ 1916 | 1471286041.304574, 1917 | 1 1918 | ], 1919 | [ 1920 | 1471286101.304574, 1921 | 0 1922 | ], 1923 | [ 1924 | 1471286161.304574, 1925 | 0 1926 | ], 1927 | [ 1928 | 1471286221.304574, 1929 | 0 1930 | ], 1931 | [ 1932 | 1471286281.304574, 1933 | 0 1934 | ], 1935 | [ 1936 | 1471286341.304574, 1937 | 4 1938 | ], 1939 | [ 1940 | 1471286401.304574, 1941 | 0 1942 | ], 1943 | [ 1944 | 1471286461.304574, 1945 | 0 1946 | ], 1947 | [ 1948 | 1471286521.304574, 1949 | 0 1950 | ], 1951 | [ 1952 | 1471286581.304574, 1953 | 3 1954 | ], 1955 | [ 1956 | 1471286641.304574, 1957 | 0 1958 | ], 1959 | [ 1960 | 1471286701.304574, 1961 | 0 1962 | ], 1963 | [ 1964 | 1471286761.304574, 1965 | 5 1966 | ], 1967 | [ 1968 | 1471286821.304574, 1969 | 1 1970 | ], 1971 | [ 1972 | 1471286881.304574, 1973 | 0 1974 | ], 1975 | [ 1976 | 1471286941.304574, 1977 | 0 1978 | ], 1979 | [ 1980 | 1471287001.304574, 1981 | 0 1982 | ], 1983 | [ 1984 | 1471287061.304574, 1985 | 0 1986 | ], 1987 | [ 1988 | 1471287121.304574, 1989 | 0 1990 | ], 1991 | [ 1992 | 1471287181.304574, 1993 | 3 1994 | ], 1995 | [ 1996 | 1471287241.304574, 1997 | 0 1998 | ], 1999 | [ 2000 | 1471287301.304574, 2001 | 0 2002 | ], 2003 | [ 2004 | 1471287361.304574, 2005 | 0 2006 | ], 2007 | [ 2008 | 1471287421.304574, 2009 | 0 2010 | ], 2011 | [ 2012 | 1471287481.304574, 2013 | 0 2014 | ], 2015 | [ 2016 | 1471287541.304574, 2017 | 5 2018 | ], 2019 | [ 2020 | 1471287601.304574, 2021 | 3 2022 | ], 2023 | [ 2024 | 1471287661.304574, 2025 | 0 2026 | ], 2027 | [ 2028 | 1471287721.304574, 2029 | 0 2030 | ], 2031 | [ 2032 | 1471287781.304574, 2033 | 0 2034 | ], 2035 | [ 2036 | 1471287841.304574, 2037 | 0 2038 | ], 2039 | [ 2040 | 1471287901.304574, 2041 | 0 2042 | ], 2043 | [ 2044 | 1471287961.304574, 2045 | 0 2046 | ], 2047 | [ 2048 | 1471288021.304574, 2049 | 0 2050 | ], 2051 | [ 2052 | 1471288081.304574, 2053 | 0 2054 | ], 2055 | [ 2056 | 1471288141.304574, 2057 | 0 2058 | ], 2059 | [ 2060 | 1471288201.304574, 2061 | 4 2062 | ], 2063 | [ 2064 | 1471288261.304574, 2065 | 8 2066 | ], 2067 | [ 2068 | 1471288321.304574, 2069 | 7 2070 | ], 2071 | [ 2072 | 1471288381.304574, 2073 | 0 2074 | ], 2075 | [ 2076 | 1471288441.304574, 2077 | 0 2078 | ], 2079 | [ 2080 | 1471288501.304574, 2081 | 0 2082 | ], 2083 | [ 2084 | 1471288561.304574, 2085 | 0 2086 | ], 2087 | [ 2088 | 1471288621.304574, 2089 | 0 2090 | ], 2091 | [ 2092 | 1471288681.304574, 2093 | 0 2094 | ], 2095 | [ 2096 | 1471288741.304574, 2097 | 0 2098 | ], 2099 | [ 2100 | 1471288801.304574, 2101 | 0 2102 | ], 2103 | [ 2104 | 1471288861.304574, 2105 | 0 2106 | ], 2107 | [ 2108 | 1471288921.304574, 2109 | 0 2110 | ], 2111 | [ 2112 | 1471288981.304574, 2113 | 0 2114 | ], 2115 | [ 2116 | 1471289041.304574, 2117 | 0 2118 | ], 2119 | [ 2120 | 1471289101.304574, 2121 | 0 2122 | ], 2123 | [ 2124 | 1471289161.304574, 2125 | 0 2126 | ], 2127 | [ 2128 | 1471289221.304574, 2129 | 8 2130 | ], 2131 | [ 2132 | 1471289281.304574, 2133 | 0 2134 | ], 2135 | [ 2136 | 1471289341.304574, 2137 | 0 2138 | ], 2139 | [ 2140 | 1471289401.304574, 2141 | 3 2142 | ], 2143 | [ 2144 | 1471289461.304574, 2145 | 0 2146 | ], 2147 | [ 2148 | 1471289521.304574, 2149 | 0 2150 | ], 2151 | [ 2152 | 1471289581.304574, 2153 | 3 2154 | ], 2155 | [ 2156 | 1471289641.304574, 2157 | 4 2158 | ], 2159 | [ 2160 | 1471289701.304574, 2161 | 0 2162 | ], 2163 | [ 2164 | 1471289761.304574, 2165 | 0 2166 | ], 2167 | [ 2168 | 1471289821.304574, 2169 | 0 2170 | ], 2171 | [ 2172 | 1471289881.304574, 2173 | 0 2174 | ], 2175 | [ 2176 | 1471289941.304574, 2177 | 0 2178 | ], 2179 | [ 2180 | 1471290001.304574, 2181 | 7 2182 | ], 2183 | [ 2184 | 1471290061.304574, 2185 | 0 2186 | ], 2187 | [ 2188 | 1471290121.304574, 2189 | 0 2190 | ], 2191 | [ 2192 | 1471290181.304574, 2193 | 0 2194 | ], 2195 | [ 2196 | 1471290241.304574, 2197 | 0 2198 | ], 2199 | [ 2200 | 1471290301.304574, 2201 | 0 2202 | ], 2203 | [ 2204 | 1471290361.304574, 2205 | 0 2206 | ], 2207 | [ 2208 | 1471290421.304574, 2209 | 0 2210 | ], 2211 | [ 2212 | 1471290481.304574, 2213 | 0 2214 | ], 2215 | [ 2216 | 1471290541.304574, 2217 | 0 2218 | ], 2219 | [ 2220 | 1471290601.304574, 2221 | 0 2222 | ], 2223 | [ 2224 | 1471290661.304574, 2225 | 5 2226 | ], 2227 | [ 2228 | 1471290721.304574, 2229 | 1 2230 | ], 2231 | [ 2232 | 1471290781.304574, 2233 | 0 2234 | ], 2235 | [ 2236 | 1471290841.304574, 2237 | 0 2238 | ], 2239 | [ 2240 | 1471290901.304574, 2241 | 0 2242 | ], 2243 | [ 2244 | 1471290961.304574, 2245 | 0 2246 | ], 2247 | [ 2248 | 1471291021.304574, 2249 | 0 2250 | ], 2251 | [ 2252 | 1471291081.304574, 2253 | 0 2254 | ], 2255 | [ 2256 | 1471291141.304574, 2257 | 0 2258 | ], 2259 | [ 2260 | 1471291201.304574, 2261 | 0 2262 | ], 2263 | [ 2264 | 1471291261.304574, 2265 | 0 2266 | ], 2267 | [ 2268 | 1471291321.304574, 2269 | 0 2270 | ], 2271 | [ 2272 | 1471291381.304574, 2273 | 0 2274 | ], 2275 | [ 2276 | 1471291441.304574, 2277 | 0 2278 | ], 2279 | [ 2280 | 1471291501.304574, 2281 | 8 2282 | ], 2283 | [ 2284 | 1471291561.304574, 2285 | 4 2286 | ], 2287 | [ 2288 | 1471291621.304574, 2289 | 0 2290 | ], 2291 | [ 2292 | 1471291681.304574, 2293 | 9 2294 | ], 2295 | [ 2296 | 1471291741.304574, 2297 | 1 2298 | ], 2299 | [ 2300 | 1471291801.304574, 2301 | 0 2302 | ], 2303 | [ 2304 | 1471291861.304574, 2305 | 0 2306 | ], 2307 | [ 2308 | 1471291921.304574, 2309 | 0 2310 | ], 2311 | [ 2312 | 1471291981.304574, 2313 | 0 2314 | ], 2315 | [ 2316 | 1471292041.304574, 2317 | 0 2318 | ], 2319 | [ 2320 | 1471292101.304574, 2321 | 0 2322 | ], 2323 | [ 2324 | 1471292161.304574, 2325 | 0 2326 | ], 2327 | [ 2328 | 1471292221.304574, 2329 | 0 2330 | ], 2331 | [ 2332 | 1471292281.304574, 2333 | 4 2334 | ], 2335 | [ 2336 | 1471292341.304574, 2337 | 0 2338 | ], 2339 | [ 2340 | 1471292401.304574, 2341 | 1 2342 | ], 2343 | [ 2344 | 1471292461.304574, 2345 | 0 2346 | ], 2347 | [ 2348 | 1471292521.304574, 2349 | 1 2350 | ], 2351 | [ 2352 | 1471292581.304574, 2353 | 0 2354 | ], 2355 | [ 2356 | 1471292641.304574, 2357 | 0 2358 | ], 2359 | [ 2360 | 1471292701.304574, 2361 | 0 2362 | ], 2363 | [ 2364 | 1471292761.304574, 2365 | 2 2366 | ], 2367 | [ 2368 | 1471292821.304574, 2369 | 0 2370 | ], 2371 | [ 2372 | 1471292881.304574, 2373 | 0 2374 | ], 2375 | [ 2376 | 1471292941.304574, 2377 | 0 2378 | ], 2379 | [ 2380 | 1471293001.304574, 2381 | 0 2382 | ], 2383 | [ 2384 | 1471293061.304574, 2385 | 0 2386 | ], 2387 | [ 2388 | 1471293121.304574, 2389 | 3 2390 | ], 2391 | [ 2392 | 1471293181.304574, 2393 | 0 2394 | ], 2395 | [ 2396 | 1471293241.304574, 2397 | 3 2398 | ], 2399 | [ 2400 | 1471293301.304574, 2401 | 0 2402 | ], 2403 | [ 2404 | 1471293361.304574, 2405 | 0 2406 | ], 2407 | [ 2408 | 1471293421.304574, 2409 | 2 2410 | ], 2411 | [ 2412 | 1471293481.304574, 2413 | 0 2414 | ], 2415 | [ 2416 | 1471293541.304574, 2417 | 0 2418 | ], 2419 | [ 2420 | 1471293601.304574, 2421 | 0 2422 | ], 2423 | [ 2424 | 1471293661.304574, 2425 | 3 2426 | ], 2427 | [ 2428 | 1471293721.304574, 2429 | 0 2430 | ], 2431 | [ 2432 | 1471293781.304574, 2433 | 0 2434 | ], 2435 | [ 2436 | 1471293841.304574, 2437 | 7 2438 | ], 2439 | [ 2440 | 1471293901.304574, 2441 | 0 2442 | ], 2443 | [ 2444 | 1471293961.304574, 2445 | 0 2446 | ], 2447 | [ 2448 | 1471294021.304574, 2449 | 0 2450 | ], 2451 | [ 2452 | 1471294081.304574, 2453 | 0 2454 | ], 2455 | [ 2456 | 1471294141.304574, 2457 | 2 2458 | ], 2459 | [ 2460 | 1471294201.304574, 2461 | 4 2462 | ], 2463 | [ 2464 | 1471294261.304574, 2465 | 0 2466 | ], 2467 | [ 2468 | 1471294321.304574, 2469 | 0 2470 | ], 2471 | [ 2472 | 1471294381.304574, 2473 | 0 2474 | ], 2475 | [ 2476 | 1471294441.304574, 2477 | 2 2478 | ], 2479 | [ 2480 | 1471294501.304574, 2481 | 0 2482 | ], 2483 | [ 2484 | 1471294561.304574, 2485 | 0 2486 | ], 2487 | [ 2488 | 1471294621.304574, 2489 | 0 2490 | ], 2491 | [ 2492 | 1471294681.304574, 2493 | 0 2494 | ], 2495 | [ 2496 | 1471294741.304574, 2497 | 0 2498 | ], 2499 | [ 2500 | 1471294801.304574, 2501 | 0 2502 | ], 2503 | [ 2504 | 1471294861.304574, 2505 | 0 2506 | ], 2507 | [ 2508 | 1471294921.304574, 2509 | 2 2510 | ], 2511 | [ 2512 | 1471294981.304574, 2513 | 2 2514 | ], 2515 | [ 2516 | 1471295041.304574, 2517 | 0 2518 | ], 2519 | [ 2520 | 1471295101.304574, 2521 | 0 2522 | ], 2523 | [ 2524 | 1471295161.304574, 2525 | 0 2526 | ], 2527 | [ 2528 | 1471295221.304574, 2529 | 0 2530 | ], 2531 | [ 2532 | 1471295281.304574, 2533 | 0 2534 | ], 2535 | [ 2536 | 1471295341.304574, 2537 | 0 2538 | ], 2539 | [ 2540 | 1471295401.304574, 2541 | 0 2542 | ], 2543 | [ 2544 | 1471295461.304574, 2545 | 0 2546 | ], 2547 | [ 2548 | 1471295521.304574, 2549 | 0 2550 | ], 2551 | [ 2552 | 1471295581.304574, 2553 | 0 2554 | ], 2555 | [ 2556 | 1471295641.304574, 2557 | 0 2558 | ], 2559 | [ 2560 | 1471295701.304574, 2561 | 0 2562 | ], 2563 | [ 2564 | 1471295761.304574, 2565 | 0 2566 | ], 2567 | [ 2568 | 1471295821.304574, 2569 | 0 2570 | ], 2571 | [ 2572 | 1471295881.304574, 2573 | 0 2574 | ], 2575 | [ 2576 | 1471295941.304574, 2577 | 0 2578 | ], 2579 | [ 2580 | 1471296001.304574, 2581 | 2 2582 | ], 2583 | [ 2584 | 1471296061.304574, 2585 | 0 2586 | ], 2587 | [ 2588 | 1471296121.304574, 2589 | 0 2590 | ], 2591 | [ 2592 | 1471296181.304574, 2593 | 0 2594 | ], 2595 | [ 2596 | 1471296241.304574, 2597 | 0 2598 | ], 2599 | [ 2600 | 1471296301.304574, 2601 | 0 2602 | ], 2603 | [ 2604 | 1471296361.304574, 2605 | 0 2606 | ], 2607 | [ 2608 | 1471296421.304574, 2609 | 1 2610 | ], 2611 | [ 2612 | 1471296481.304574, 2613 | 0 2614 | ], 2615 | [ 2616 | 1471296541.304574, 2617 | 1 2618 | ], 2619 | [ 2620 | 1471296601.304574, 2621 | 1 2622 | ], 2623 | [ 2624 | 1471296661.304574, 2625 | 0 2626 | ], 2627 | [ 2628 | 1471296721.304574, 2629 | 0 2630 | ], 2631 | [ 2632 | 1471296781.304574, 2633 | 0 2634 | ], 2635 | [ 2636 | 1471296841.304574, 2637 | 0 2638 | ], 2639 | [ 2640 | 1471296901.304574, 2641 | 0 2642 | ], 2643 | [ 2644 | 1471296961.304574, 2645 | 0 2646 | ], 2647 | [ 2648 | 1471297021.304574, 2649 | 0 2650 | ], 2651 | [ 2652 | 1471297081.304574, 2653 | 0 2654 | ], 2655 | [ 2656 | 1471297141.304574, 2657 | 0 2658 | ], 2659 | [ 2660 | 1471297201.304574, 2661 | 0 2662 | ], 2663 | [ 2664 | 1471297261.304574, 2665 | 0 2666 | ], 2667 | [ 2668 | 1471297321.304574, 2669 | 0 2670 | ], 2671 | [ 2672 | 1471297381.304574, 2673 | 3 2674 | ], 2675 | [ 2676 | 1471297441.304574, 2677 | 0 2678 | ], 2679 | [ 2680 | 1471297501.304574, 2681 | 0 2682 | ], 2683 | [ 2684 | 1471297561.304574, 2685 | 0 2686 | ], 2687 | [ 2688 | 1471297621.304574, 2689 | 0 2690 | ], 2691 | [ 2692 | 1471297681.304574, 2693 | 0 2694 | ], 2695 | [ 2696 | 1471297741.304574, 2697 | 0 2698 | ], 2699 | [ 2700 | 1471297801.304574, 2701 | 0 2702 | ], 2703 | [ 2704 | 1471297861.304574, 2705 | 0 2706 | ], 2707 | [ 2708 | 1471297921.304574, 2709 | 0 2710 | ], 2711 | [ 2712 | 1471297981.304574, 2713 | 0 2714 | ], 2715 | [ 2716 | 1471298041.304574, 2717 | 0 2718 | ], 2719 | [ 2720 | 1471298101.304574, 2721 | 0 2722 | ], 2723 | [ 2724 | 1471298161.304574, 2725 | 0 2726 | ], 2727 | [ 2728 | 1471298221.304574, 2729 | 0 2730 | ], 2731 | [ 2732 | 1471298281.304574, 2733 | 0 2734 | ], 2735 | [ 2736 | 1471298341.304574, 2737 | 2 2738 | ], 2739 | [ 2740 | 1471298401.304574, 2741 | 0 2742 | ], 2743 | [ 2744 | 1471298461.304574, 2745 | 0 2746 | ], 2747 | [ 2748 | 1471298521.304574, 2749 | 3 2750 | ], 2751 | [ 2752 | 1471298581.304574, 2753 | 0 2754 | ], 2755 | [ 2756 | 1471298641.304574, 2757 | 0 2758 | ], 2759 | [ 2760 | 1471298701.304574, 2761 | 0 2762 | ], 2763 | [ 2764 | 1471298761.304574, 2765 | 0 2766 | ], 2767 | [ 2768 | 1471298821.304574, 2769 | 0 2770 | ], 2771 | [ 2772 | 1471298881.304574, 2773 | 0 2774 | ], 2775 | [ 2776 | 1471298941.304574, 2777 | 0 2778 | ], 2779 | [ 2780 | 1471299001.304574, 2781 | 0 2782 | ], 2783 | [ 2784 | 1471299061.304574, 2785 | 2 2786 | ], 2787 | [ 2788 | 1471299121.304574, 2789 | 0 2790 | ], 2791 | [ 2792 | 1471299181.304574, 2793 | 0 2794 | ], 2795 | [ 2796 | 1471299241.304574, 2797 | 0 2798 | ], 2799 | [ 2800 | 1471299301.304574, 2801 | 0 2802 | ], 2803 | [ 2804 | 1471299361.304574, 2805 | 0 2806 | ], 2807 | [ 2808 | 1471299421.304574, 2809 | 0 2810 | ], 2811 | [ 2812 | 1471299481.304574, 2813 | 2 2814 | ], 2815 | [ 2816 | 1471299541.304574, 2817 | 1 2818 | ], 2819 | [ 2820 | 1471299601.304574, 2821 | 0 2822 | ], 2823 | [ 2824 | 1471299661.304574, 2825 | 2 2826 | ], 2827 | [ 2828 | 1471299721.304574, 2829 | 1 2830 | ], 2831 | [ 2832 | 1471299781.304574, 2833 | 0 2834 | ], 2835 | [ 2836 | 1471299841.304574, 2837 | 0 2838 | ], 2839 | [ 2840 | 1471299901.304574, 2841 | 0 2842 | ], 2843 | [ 2844 | 1471299961.304574, 2845 | 2 2846 | ], 2847 | [ 2848 | 1471300021.304574, 2849 | 0 2850 | ], 2851 | [ 2852 | 1471300081.304574, 2853 | 0 2854 | ], 2855 | [ 2856 | 1471300141.304574, 2857 | 0 2858 | ], 2859 | [ 2860 | 1471300201.304574, 2861 | 0 2862 | ], 2863 | [ 2864 | 1471300261.304574, 2865 | 0 2866 | ], 2867 | [ 2868 | 1471300321.304574, 2869 | 0 2870 | ], 2871 | [ 2872 | 1471300381.304574, 2873 | 4 2874 | ], 2875 | [ 2876 | 1471300441.304574, 2877 | 0 2878 | ], 2879 | [ 2880 | 1471300501.304574, 2881 | 0 2882 | ], 2883 | [ 2884 | 1471300561.304574, 2885 | 0 2886 | ], 2887 | [ 2888 | 1471300621.304574, 2889 | 0 2890 | ], 2891 | [ 2892 | 1471300681.304574, 2893 | 1 2894 | ], 2895 | [ 2896 | 1471300741.304574, 2897 | 0 2898 | ], 2899 | [ 2900 | 1471300801.304574, 2901 | 0 2902 | ], 2903 | [ 2904 | 1471300861.304574, 2905 | 0 2906 | ], 2907 | [ 2908 | 1471300921.304574, 2909 | 0 2910 | ], 2911 | [ 2912 | 1471300981.304574, 2913 | 0 2914 | ], 2915 | [ 2916 | 1471301041.304574, 2917 | 0 2918 | ], 2919 | [ 2920 | 1471301101.304574, 2921 | 0 2922 | ], 2923 | [ 2924 | 1471301161.304574, 2925 | 0 2926 | ], 2927 | [ 2928 | 1471301221.304574, 2929 | 0 2930 | ], 2931 | [ 2932 | 1471301281.304574, 2933 | 0 2934 | ], 2935 | [ 2936 | 1471301863.304574, 2937 | 3 2938 | ], 2939 | [ 2940 | 1471301923.304574, 2941 | 1 2942 | ], 2943 | [ 2944 | 1471301983.304574, 2945 | 0 2946 | ], 2947 | [ 2948 | 1471302043.304574, 2949 | 0 2950 | ], 2951 | [ 2952 | 1471302103.304574, 2953 | 0 2954 | ], 2955 | [ 2956 | 1471302163.304574, 2957 | 0 2958 | ], 2959 | [ 2960 | 1471302223.304574, 2961 | 0 2962 | ], 2963 | [ 2964 | 1471302283.304574, 2965 | 0 2966 | ], 2967 | [ 2968 | 1471302343.304574, 2969 | 0 2970 | ], 2971 | [ 2972 | 1471302403.304574, 2973 | 0 2974 | ], 2975 | [ 2976 | 1471302463.304574, 2977 | 0 2978 | ], 2979 | [ 2980 | 1471302523.304574, 2981 | 0 2982 | ], 2983 | [ 2984 | 1471302583.304574, 2985 | 0 2986 | ], 2987 | [ 2988 | 1471302643.304574, 2989 | 0 2990 | ], 2991 | [ 2992 | 1471302703.304574, 2993 | 1 2994 | ], 2995 | [ 2996 | 1471302763.304574, 2997 | 4 2998 | ], 2999 | [ 3000 | 1471302823.304574, 3001 | 0 3002 | ], 3003 | [ 3004 | 1471302883.304574, 3005 | 0 3006 | ], 3007 | [ 3008 | 1471302943.304574, 3009 | 0 3010 | ], 3011 | [ 3012 | 1471303003.304574, 3013 | 1 3014 | ], 3015 | [ 3016 | 1471303063.304574, 3017 | 0 3018 | ], 3019 | [ 3020 | 1471303123.304574, 3021 | 0 3022 | ], 3023 | [ 3024 | 1471303183.304574, 3025 | 2 3026 | ], 3027 | [ 3028 | 1471303243.304574, 3029 | 2 3030 | ], 3031 | [ 3032 | 1471303303.304574, 3033 | 0 3034 | ], 3035 | [ 3036 | 1471303363.304574, 3037 | 6 3038 | ], 3039 | [ 3040 | 1471303423.304574, 3041 | 0 3042 | ] 3043 | ], 3044 | "value_data_type":"float32" 3045 | }, 3046 | "sleep_stages":{ 3047 | "items":[ 3048 | [ 3049 | 1471271701.304574, 3050 | 87 3051 | ], 3052 | [ 3053 | 1471274101.304574, 3054 | 65 3055 | ], 3056 | [ 3057 | 1471274206.304574, 3058 | 87 3059 | ], 3060 | [ 3061 | 1471275418.304574, 3062 | 65 3063 | ], 3064 | [ 3065 | 1471275499.304574, 3066 | 87 3067 | ], 3068 | [ 3069 | 1471276018.304574, 3070 | 65 3071 | ], 3072 | [ 3073 | 1471276273.304574, 3074 | 87 3075 | ], 3076 | [ 3077 | 1471276993.304574, 3078 | 65 3079 | ], 3080 | [ 3081 | 1471277164.304574, 3082 | 87 3083 | ], 3084 | [ 3085 | 1471279243.304574, 3086 | 65 3087 | ], 3088 | [ 3089 | 1471279321.304574, 3090 | 87 3091 | ], 3092 | [ 3093 | 1471280683.304574, 3094 | 65 3095 | ], 3096 | [ 3097 | 1471280734.304574, 3098 | 87 3099 | ], 3100 | [ 3101 | 1471281061.304574, 3102 | 65 3103 | ], 3104 | [ 3105 | 1471281109.304574, 3106 | 87 3107 | ], 3108 | [ 3109 | 1471281256.304574, 3110 | 65 3111 | ], 3112 | [ 3113 | 1471281721.304574, 3114 | 87 3115 | ], 3116 | [ 3117 | 1471283761.304574, 3118 | 83 3119 | ], 3120 | [ 3121 | 1471301389.304574, 3122 | 65 3123 | ], 3124 | [ 3125 | 1471301863.304574, 3126 | 87 3127 | ], 3128 | [ 3129 | 1471303494.304574, 3130 | 87 3131 | ] 3132 | ], 3133 | "value_data_type":"uint8" 3134 | }, 3135 | "nap_periods":{ 3136 | "items":[ 3137 | 3138 | ], 3139 | "value_data_type":"uint8" 3140 | } 3141 | }, 3142 | "user":98740, 3143 | "date":"2016-08-16", 3144 | "timezone":"Asia/Tokyo", 3145 | "tips":[ 3146 | 3147 | ], 3148 | "properties":{ 3149 | "sleep_latency":2040, 3150 | "sleep_time_target":27000, 3151 | "total_sleep_score":44, 3152 | "sensor_status":1, 3153 | "sleep_score_version":3, 3154 | "short_term_average_respiration_rate":16.96982, 3155 | "primary_sleep_period_away_episode_duration":0, 3156 | "primary_sleep_period_away_episode_count":0, 3157 | "total_nap_duration":0, 3158 | "average_respiration_rate":17.83983, 3159 | "total_snoring_episode_duration":0, 3160 | "activity_index":38.39347, 3161 | "signal_amplitude":1010.591, 3162 | "short_term_resting_heart_rate":48.16772, 3163 | "evening_HRV_index":0.03485152, 3164 | "stage_duration_W":12437, 3165 | "clipping_duration":0, 3166 | "single_person_setup":1, 3167 | "resting_heart_rate":44.60449, 3168 | "all_night_HRV_index":0.0864508, 3169 | "stage_duration_N":0, 3170 | "stage_duration_A":1728, 3171 | "stage_duration_G":0, 3172 | "morning_HRV_index":0.1146395, 3173 | "stage_duration_R":0, 3174 | "stage_duration_S":17628, 3175 | "sleep_efficiency":0.8962782 3176 | }, 3177 | "end_timestamp":1471303494.304574 3178 | } 3179 | ] 3180 | -------------------------------------------------------------------------------- /tests/fixtures/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "updated":1471356194.0, 3 | "weight":60.0, 4 | "height":175.0, 5 | "sleep_time_goal":27000.0, 6 | "tip_audiences":[ 7 | "general" 8 | ], 9 | "sex":null, 10 | "id":10000, 11 | "name":"John Doe", 12 | "created":1468327763.0, 13 | "date_of_birth":"1990-01-01", 14 | "email":"beddit@example.com" 15 | } 16 | -------------------------------------------------------------------------------- /tests/test_client.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | import json 4 | import datetime 5 | from tests.compatibility import patch, Mock 6 | from beddit.client import BedditClient 7 | from beddit.sleep import Sleep 8 | from beddit.session import Session 9 | from beddit.user import User 10 | from beddit.group import Group 11 | 12 | BASE_DIR = os.path.dirname(__file__) 13 | 14 | 15 | def authenticated(testcase): 16 | def _inner(self, *args, **kwargs): 17 | response = Mock() 18 | response.json.side_effect = lambda: {'user': 10000, 'access_token': 'dummytoken'} 19 | response.status_code = 200 20 | payload = { 21 | 'grant_type': 'password', 22 | 'username': 'username', 23 | 'password': 'password' 24 | } 25 | with patch('requests.post', return_value=response) as post: 26 | retval = testcase(self, *args, **kwargs) 27 | post.assert_called_with(BedditClient.build_full_path('api/v1/auth/authorize'), data=payload) 28 | return retval 29 | return _inner 30 | 31 | 32 | class BedditClientTest(unittest.TestCase): 33 | @property 34 | def _default_client(self): 35 | return BedditClient('username', 'password') 36 | 37 | @authenticated 38 | def test_authenticate(self): 39 | client = self._default_client 40 | 41 | self.assertEqual(client.user_id, 10000) 42 | self.assertEqual(client.access_token, 'dummytoken') 43 | 44 | def test_authentication_error(self): 45 | response = Mock() 46 | response.status_code = 400 47 | response.json.side_effect = lambda: {'description': 'auth_error'} 48 | with patch('requests.post', return_value=response): 49 | self.assertRaises(BedditClient.AuthError, BedditClient, 'username', 'password') 50 | 51 | def test_argument_error(self): 52 | self.assertRaises(BedditClient.ArgumentError, BedditClient, 'username') 53 | 54 | @authenticated 55 | def test_get_sleep(self): 56 | client = self._default_client 57 | timestamp = 1471761649 58 | 59 | endpoint = BedditClient.build_full_path('/api/v1/user/10000/sleep') 60 | response = Mock() 61 | response.status_code = 200 62 | sleep_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/sleep.json'))) 63 | response.json = lambda: sleep_object 64 | with patch('requests.get', return_value=response) as get: 65 | sleeps = client.get_sleeps( 66 | start=datetime.datetime.utcfromtimestamp(timestamp), 67 | end=datetime.datetime.utcfromtimestamp(timestamp), 68 | limit=10, 69 | reverse=True 70 | ) 71 | self.assertEqual(len(sleeps), 1) 72 | self.assertEqual(type(sleeps[0]), Sleep) 73 | 74 | args, kwargs = get.call_args 75 | self.assertEqual(args[0], endpoint) 76 | self.assertDictEqual(kwargs['params'], { 77 | 'start_date': '2016-08-21', 78 | 'end_date': '2016-08-21', 79 | 'limit': 10, 80 | 'reverse': 'yes' 81 | }) 82 | 83 | @authenticated 84 | def test_get_session(self): 85 | client = self._default_client 86 | timestamp = 1471761649 87 | 88 | endpoint = BedditClient.build_full_path('/api/v1/user/10000/session') 89 | response = Mock() 90 | response.status_code = 200 91 | session_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/session.json'))) 92 | response.json = lambda: session_object 93 | dt = datetime.datetime.fromtimestamp(timestamp) 94 | with patch('requests.get', return_value=response) as get: 95 | sessions = client.get_sessions(updated_after=dt) 96 | self.assertEqual(len(sessions), 1) 97 | self.assertEqual(type(sessions[0]), Session) 98 | 99 | args, kwargs = get.call_args 100 | self.assertEqual(args[0], endpoint) 101 | self.assertDictEqual(kwargs['params'], { 102 | 'updated_after': timestamp 103 | }) 104 | 105 | @authenticated 106 | def test_get_session_with_invalid_argument(self): 107 | client = self._default_client 108 | self.assertRaises(BedditClient.ArgumentError, client.get_sessions) 109 | self.assertRaises(BedditClient.ArgumentError, client.get_sessions, start=datetime.datetime.now) 110 | self.assertRaises(BedditClient.ArgumentError, client.get_sessions, end=datetime.datetime.now) 111 | 112 | def test_reset_password(self): 113 | response = Mock() 114 | response.status_code = 200 115 | with patch('requests.post', return_value=response) as post: 116 | result = BedditClient.reset_password('new@example.com') 117 | self.assertTrue(result) 118 | 119 | post.assert_called_once_with(BedditClient.build_full_path('/api/v1/user/password_reset'), 120 | data={'email': 'new@example.com'}) 121 | 122 | @authenticated 123 | def test_get_user(self): 124 | client = self._default_client 125 | 126 | endpoint = BedditClient.build_full_path('/api/v1/user/10000') 127 | response = Mock() 128 | response.status_code = 200 129 | user_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/user.json'))) 130 | response.json = lambda: user_object 131 | with patch('requests.get', return_value=response) as get: 132 | user = client.get_user() 133 | self.assertEqual(type(user), User) 134 | 135 | args = get.call_args[0] 136 | self.assertEqual(args[0], endpoint) 137 | 138 | @authenticated 139 | def test_update_user(self): 140 | client = self._default_client 141 | 142 | endpoint = BedditClient.build_full_path('/api/v1/user/10000') 143 | response = Mock() 144 | response.status_code = 200 145 | user_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/user.json'))) 146 | response.json = lambda: user_object 147 | with patch('requests.put', return_value=response) as put: 148 | user = client.update_user(name='foo') 149 | self.assertEqual(type(user), User) 150 | 151 | args = put.call_args[0] 152 | self.assertEqual(args[0], endpoint) 153 | 154 | @authenticated 155 | def test_get_group(self): 156 | client = self._default_client 157 | 158 | endpoint = BedditClient.build_full_path('/api/v1/user/10000/group') 159 | response = Mock() 160 | response.status_code = 200 161 | group_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/group.json'))) 162 | response.json = lambda: [group_object] 163 | with patch('requests.get', return_value=response) as get: 164 | groups = client.get_groups() 165 | self.assertEqual(type(groups[0]), Group) 166 | 167 | args = get.call_args[0] 168 | self.assertEqual(args[0], endpoint) 169 | 170 | @authenticated 171 | def test_invite_to_group(self): 172 | client = self._default_client 173 | 174 | endpoint = BedditClient.build_full_path('/api/v1/group/new/invite') 175 | response = Mock() 176 | response.status_code = 200 177 | group_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/group.json'))) 178 | response.json = lambda: [group_object] 179 | with patch('requests.post', return_value=response) as post: 180 | groups = client.invite_to_group(email="user@example.com") 181 | self.assertEqual(type(groups[0]), Group) 182 | 183 | args, kwargs = post.call_args 184 | self.assertEqual(args[0], endpoint) 185 | self.assertDictEqual(kwargs['data'], { 186 | 'email': 'user@example.com' 187 | }) 188 | 189 | @authenticated 190 | def test_remove_group_invite(self): 191 | client = self._default_client 192 | 193 | endpoint = BedditClient.build_full_path('/api/v1/group/200/member/10000/remove') 194 | response = Mock() 195 | response.status_code = 200 196 | group_object = json.load(open(os.path.join(BASE_DIR, 'fixtures/group.json'))) 197 | response.json = lambda: [group_object] 198 | with patch('requests.post', return_value=response) as post: 199 | groups = client.remove_group_invite(group_id=200, user_id=10000) 200 | self.assertEqual(type(groups[0]), Group) 201 | 202 | args = post.call_args[0] 203 | self.assertEqual(args[0], endpoint) 204 | -------------------------------------------------------------------------------- /tests/test_group.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import json 3 | import os 4 | from datetime import datetime 5 | from beddit.group import Group 6 | 7 | 8 | BASE_DIR = os.path.dirname(__file__) 9 | 10 | 11 | class GroupTest(unittest.TestCase): 12 | @property 13 | def group_response(self): 14 | return json.load(open(os.path.join(BASE_DIR, 'fixtures/group.json'))) 15 | 16 | def test_group(self): 17 | group = Group(self.group_response) 18 | self.assertEqual(group.id, 1234) 19 | self.assertEqual(group.created, datetime.utcfromtimestamp(1371472503.646541)) 20 | self.assertEqual(len(group.members), 1) 21 | self.assertEqual(len(group.pending_invites), 1) 22 | 23 | pending_invite = group.pending_invites[0] 24 | self.assertEqual(pending_invite.created, datetime.utcfromtimestamp(1371472503.646541)) 25 | self.assertEqual(pending_invite.created_by, 132) 26 | self.assertEqual(pending_invite.email, 'example@beddit.com') 27 | -------------------------------------------------------------------------------- /tests/test_session.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import json 3 | import os 4 | from datetime import datetime 5 | from pytz import timezone 6 | from beddit.session import Session 7 | 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | 11 | 12 | class SessionTest(unittest.TestCase): 13 | @property 14 | def session_response(self): 15 | return json.load(open(os.path.join(BASE_DIR, 'fixtures/session.json'))) 16 | 17 | def test_session(self): 18 | raw = self.session_response[0] 19 | session = Session(raw) 20 | jst = timezone('Asia/Tokyo') 21 | self.assertEqual(session.timezone, jst) 22 | self.assertEqual(session.id, raw['id']) 23 | self.assertEqual(session.start, datetime.fromtimestamp(raw['start_timestamp'], tz=jst)) 24 | self.assertEqual(session.end, datetime.fromtimestamp(raw['end_timestamp'], tz=jst)) 25 | self.assertEqual(session.updated, datetime.fromtimestamp(raw['updated'], tz=jst)) 26 | self.assertEqual(session.hardware, raw['hardware']) 27 | self.assertEqual(session.frame_length, raw['frame_length']) 28 | self.assertEqual(session.error_code, raw['error_code']) 29 | self.assertEqual(session.sampled_tracks, {}) 30 | 31 | self.assertEqual(len(session.respiration_cycle_amplitudes), 7976) 32 | self.assertEqual(len(session.heartbeat), 5963) 33 | self.assertEqual(len(session.heart_rate), 460) 34 | self.assertEqual(len(session.signal_high_percentile), 544) 35 | self.assertEqual(len(session.repiration_cycles), 0) 36 | self.assertEqual(len(session.events), 2) 37 | self.assertEqual(len(session.actigram), 744) 38 | self.assertEqual(len(session.sensor_status), 1) 39 | self.assertEqual(len(session.snoring_events), 10) 40 | self.assertEqual(len(session.activity_segment_length), 303) 41 | self.assertEqual(len(session.high_activity_intervals), 113) 42 | self.assertEqual(len(session.activity_segment_variation), 303) 43 | 44 | def test_sampled_tracks(self): 45 | response = json.load(open(os.path.join(BASE_DIR, 'fixtures/session_sample.json'))) 46 | session = Session(response) 47 | tracks = session.sampled_tracks 48 | self.assertEqual(tracks['normal'].samples_per_frame, 28) 49 | self.assertEqual(tracks['normal'].data_url, 'https://bedditcloud-sleepdata...') 50 | self.assertEqual(tracks['normal'].data_type, 'uint16') 51 | 52 | self.assertEqual(tracks['noise'].samples_per_frame, 2) 53 | self.assertEqual(tracks['noise'].data_url, 'https://bedditcloud-sleepdata...') 54 | self.assertEqual(tracks['noise'].data_type, 'float32') 55 | 56 | -------------------------------------------------------------------------------- /tests/test_sleep.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import json 3 | import os 4 | from datetime import datetime 5 | from pytz import timezone 6 | from beddit.sleep import Sleep 7 | 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | 11 | 12 | class SleepTest(unittest.TestCase): 13 | @property 14 | def sleep_response(self): 15 | return json.load(open(os.path.join(BASE_DIR, 'fixtures/sleep.json'))) 16 | 17 | def test_sleep(self): 18 | raw = self.sleep_response[0] 19 | sleep = Sleep(raw) 20 | jst = timezone('Asia/Tokyo') 21 | self.assertEqual(sleep.timezone, jst) 22 | self.assertEqual(sleep.date, datetime(2016, 8, 16).replace(tzinfo=jst)) 23 | self.assertEqual(sleep.start, datetime.fromtimestamp(raw['start_timestamp'], tz=jst)) 24 | self.assertEqual(sleep.end, datetime.fromtimestamp(raw['end_timestamp'], tz=jst)) 25 | self.assertEqual(sleep.session_range_start, datetime.fromtimestamp(raw['session_range_start'], tz=jst)) 26 | self.assertEqual(sleep.session_range_end, datetime.fromtimestamp(raw['session_range_end'], tz=jst)) 27 | self.assertEqual(sleep.updated, datetime.fromtimestamp(raw['updated'], tz=jst)) 28 | 29 | self.assertEqual(len(sleep.actigram), 497) 30 | self.assertEqual(len(sleep.sleep_event), 21) 31 | self.assertEqual(len(sleep.presence), 20) 32 | self.assertEqual(len(sleep.snoring_episodes), 20) 33 | self.assertEqual(len(sleep.nap_periods), 0) 34 | self.assertEqual(len(sleep.heart_rate_curve), 89) 35 | self.assertEqual(len(sleep.sleep_cycles), 146) 36 | 37 | properties = [ 38 | "sleep_latency", 39 | "sleep_time_target", 40 | "total_sleep_score", 41 | "sensor_status", 42 | "sleep_score_version", 43 | "short_term_average_respiration_rate", 44 | "primary_sleep_period_away_episode_duration", 45 | "primary_sleep_period_away_episode_count", 46 | "total_nap_duration", 47 | "average_respiration_rate", 48 | "total_snoring_episode_duration", 49 | "activity_index", 50 | "signal_amplitude", 51 | "short_term_resting_heart_rate", 52 | "evening_HRV_index", 53 | "stage_duration_W", 54 | "clipping_duration", 55 | "single_person_setup", 56 | "resting_heart_rate", 57 | "all_night_HRV_index", 58 | "stage_duration_N", 59 | "stage_duration_A", 60 | "stage_duration_G", 61 | "morning_HRV_index", 62 | "stage_duration_R", 63 | "stage_duration_S", 64 | "sleep_efficiency" 65 | ] 66 | for p in properties: 67 | self.assertTrue(hasattr(sleep.property, p)) 68 | -------------------------------------------------------------------------------- /tests/test_user.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import json 3 | import os 4 | from datetime import datetime, timedelta 5 | from beddit.user import User, Sex 6 | 7 | 8 | BASE_DIR = os.path.dirname(__file__) 9 | 10 | 11 | class UserTest(unittest.TestCase): 12 | @property 13 | def user_response(self): 14 | return json.load(open(os.path.join(BASE_DIR, 'fixtures/user.json'))) 15 | 16 | def test_user(self): 17 | user = User(self.user_response) 18 | self.assertEqual(user.id, 10000) 19 | self.assertEqual(user.updated, datetime.utcfromtimestamp(1471356194)) 20 | self.assertEqual(user.weight, 60.0) 21 | self.assertEqual(user.height, 175.0) 22 | self.assertEqual(user.sleep_time_goal, timedelta(seconds=27000)) 23 | self.assertIn('general', user.tip_audiences) 24 | self.assertEqual(user.sex, Sex.Unknown) 25 | self.assertEqual(user.date_of_birth, datetime(1990, 1, 1)) 26 | self.assertEqual(user.email, 'beddit@example.com') 27 | self.assertEqual(user.created, datetime.utcfromtimestamp(1468327763)) 28 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = 3 | py{27,33,34,35} 4 | 5 | [testenv] 6 | basepython = 7 | py27: python2.7 8 | py33: python3.3 9 | py34: python3.4 10 | py35: python3.5 11 | deps= 12 | py27: enum34 13 | py27: mock 14 | py33: enum34 15 | -rrequirements.txt 16 | coverage 17 | commands = 18 | {envbindir}/coverage run --source=beddit runtests.py [] 19 | coverage report 20 | 21 | --------------------------------------------------------------------------------