def withings_get_data(healthdevice):
    height = None
    weight = None
    daily_exercise = None

    creds = WithingsCredentials(
        access_token=healthdevice.access_token,
        access_token_secret=healthdevice.meta['access_token_secret'],
        consumer_key=WITHINGS_SETTINGS['CONSUMER_KEY'],
        consumer_secret=WITHINGS_SETTINGS['CONSUMER_SECRET'],
        user_id=healthdevice.meta['user_id'])

    client = WithingsApi(creds)
    try:
        measures = client.get_measures(limit=1,
                                       meastype='1')  # measure type: weight
        weight = measures[0].weight
    except:
        pass

    try:
        measures = client.get_measures(limit=1,
                                       meastype='4')  # mesuare type: height
        height = measures[0].height * 100
    except:
        pass

    try:
        workouts_params = {
            'userid': healthdevice.meta['user_id'],
            'startdateymd':
            (date.today() - timedelta(days=PERIOD)).isoformat(),
            'enddateymd': date.today().isoformat()
        }
        workouts = client.request('v2/measure',
                                  'getworkouts',
                                  params=workouts_params)
        if 'series' in workouts:
            total_seconds = reduce(
                lambda acc, item: acc + withings_get_item_duration(item),
                workouts['series'], 0)
            daily_exercise = round(total_seconds / (PERIOD * 60), 0)
    except:
        pass

    if height is None and weight is None and daily_exercise is None:
        return None
    else:
        return {
            'height': height,
            'weight': weight,
            'daily_exercise': daily_exercise
        }
Exemple #2
0
def store_measures(creds):
    client = WithingsApi(creds)
    # lastupdate = int(time.time())
    measures = client.get_measures()
    with db_connection() as db_conn:
        for m in measures:
            with db_conn.cursor() as c:
                c.execute('SELECT 1 FROM withings_measures WHERE grpid = %s', (m.grpid,))
                if c.fetchone():
                    continue
                # grpid, wuserid, weight, height, fat_free_mass, fat_ratio, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, heart_pulse, created_at
                c.execute('INSERT INTO withings_measures (grpid, wuserid, weight, height, fat_free_mass, fat_ratio, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, heart_pulse, wdate) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', (m.grpid, creds.user_id, m.weight, m.height, m.fat_free_mass, m.fat_ratio, m.fat_mass_weight, m.diastolic_blood_pressure, m.systolic_blood_pressure, m.heart_pulse, m.date))
Exemple #3
0
def refresh_weight(cfg_file, engine, db_df):
    print("REFRESHING WEIGHT...")
    parser = configparser.ConfigParser()
    parser.read(cfg_file)
    consumer_key = parser.get('withings', 'consumer_key')
    consumer_secret = parser.get('withings', 'consumer_secret')
    access_token = parser.get('withings', 'access_token')
    access_token_secret = parser.get('withings', 'access_token_secret')
    user_id = parser.get('withings', 'user_id')

    credentials = WithingsCredentials(access_token=access_token,
                                      access_token_secret=access_token_secret,
                                      consumer_key=consumer_key,
                                      consumer_secret=consumer_secret,
                                      user_id=user_id)
    client = WithingsApi(credentials)

    [date_start, date_end] = get_target_date_endpoints('Weight', db_df)
    date_query = date_start
    date_diff = date_end - date_query
    days = date_diff.days + 2

    measures = client.get_measures(meastype=1, limit=days)
    measures.pop(0)
    weight_json = [{
        'weight': (float("{:.1f}".format(x.weight * 2.20462))),
        'date': x.date.strftime('%Y-%m-%d')
    } for x in measures]
    date_values = [[pd.tseries.offsets.to_datetime(x['date']), x['weight']]
                   for x in weight_json]
    updated_df = insert_values(date_values, 'Weight', db_df)

    with engine.connect() as conn, conn.begin():
        updated_df.to_sql('fitness', conn, if_exists='replace')

    return updated_df
Exemple #4
0
# copied from https://github.com/maximebf/python-withings/blob/master/README.md

from withings import WithingsAuth, WithingsApi
from settings import CONSUMER_KEY, CONSUMER_SECRET

auth = WithingsAuth(CONSUMER_KEY, CONSUMER_SECRET)
authorize_url = auth.get_authorize_url()
print "Go to %s allow the app and copy your oauth_verifier" % authorize_url

oauth_verifier = raw_input('Please enter your oauth_verifier: ')
creds = auth.get_credentials(oauth_verifier)

client = WithingsApi(creds)
measures = client.get_measures(limit=1)
print "Your last measured weight: %skg" % measures[0].weight
class TestWithingsApi(unittest.TestCase):
    def setUp(self):
        self.mock_api = True
        if self.mock_api:
            self.creds = WithingsCredentials()
        else:
            config = ConfigParser.ConfigParser()
            config.read('withings.conf')
            self.creds = WithingsCredentials(
                consumer_key=config.get('withings', 'consumer_key'),
                consumer_secret=config.get('withings', 'consumer_secret'),
                access_token=config.get('withings', 'access_token'),
                access_token_secret=config.get('withings',
                                               'access_token_secret'),
                user_id=config.get('withings', 'user_id'))
        self.api = WithingsApi(self.creds)

    def test_attributes(self):
        """ Make sure the WithingsApi objects have the right attributes """
        assert hasattr(WithingsApi, 'URL')
        creds = WithingsCredentials(user_id='FAKEID')
        api = WithingsApi(creds)
        assert hasattr(api, 'credentials')
        assert hasattr(api, 'oauth')
        assert hasattr(api, 'client')

    def test_attribute_defaults(self):
        """
        Make sure WithingsApi object attributes have the correct defaults
        """
        self.assertEqual(WithingsApi.URL, 'http://wbsapi.withings.net')
        creds = WithingsCredentials(user_id='FAKEID')
        api = WithingsApi(creds)
        self.assertEqual(api.credentials, creds)
        self.assertEqual(api.client.auth, api.oauth)
        self.assertEqual(api.client.params, {'userid': creds.user_id})

    def test_request(self):
        """
        Make sure the request method builds the proper URI and returns the
        request body as a python dict.
        """
        self.mock_request({})
        resp = self.api.request('fake_service', 'fake_action')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/fake_service',
            params={'action': 'fake_action'})
        self.assertEqual(resp, {})

    def test_request_params(self):
        """
        Check that the request method passes along extra params and works
        with different HTTP methods
        """
        self.mock_request({})
        resp = self.api.request('user', 'getbyuserid', params={'p2': 'p2'},
                                method='POST')
        Session.request.assert_called_once_with(
            'POST', 'http://wbsapi.withings.net/user',
            params={'p2': 'p2', 'action': 'getbyuserid'})
        self.assertEqual(resp, {})

    def test_request_error(self):
        """ Check that requests raises an exception when there is an error """
        self.mock_request('', status=1)
        self.assertRaises(Exception, self.api.request, ('user', 'getbyuserid'))

    def test_get_user(self):
        """ Check that the get_user method fetches the right URL """
        self.mock_request({
            'users': [
                {'id': 1111111, 'birthdate': 364305600, 'lastname': 'Baggins',
                 'ispublic': 255, 'firstname': 'Frodo', 'fatmethod': 131,
                 'gender': 0, 'shortname': 'FRO'}
            ]
        })
        resp = self.api.get_user()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/user',
            params={'action': 'getbyuserid'})
        self.assertEqual(type(resp), dict)
        assert 'users' in resp
        self.assertEqual(type(resp['users']), list)
        self.assertEqual(len(resp['users']), 1)
        self.assertEqual(resp['users'][0]['firstname'], 'Frodo')
        self.assertEqual(resp['users'][0]['lastname'], 'Baggins')

    def test_get_sleep(self):
        """
        Check that get_sleep fetches the appropriate URL, the response looks
        correct, and the return value is a WithingsSleep object with the
        correct attributes
        """
        body = {
            "series": [{
                "startdate": 1387235398,
                "state": 0,
                "enddate": 1387235758
            }, {
                "startdate": 1387243618,
                "state": 1,
                "enddate": 1387244518
            }],
            "model": 16
        }
        self.mock_request(body)
        resp = self.api.get_sleep()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/sleep',
            params={'action': 'get'})
        self.assertEqual(type(resp), WithingsSleep)
        self.assertEqual(resp.model, body['model'])
        self.assertEqual(type(resp.series), list)
        self.assertEqual(len(resp.series), 2)
        self.assertEqual(type(resp.series[0]), WithingsSleepSeries)
        self.assertEqual(time.mktime(resp.series[0].startdate.timetuple()),
                         body['series'][0]['startdate'])
        self.assertEqual(time.mktime(resp.series[0].enddate.timetuple()),
                         body['series'][0]['enddate'])
        self.assertEqual(resp.series[1].state, 1)


    def test_get_activities(self):
        """
        Check that get_activities fetches the appropriate URL, the response
        looks correct, and the return value is a list of WithingsActivity
        objects
        """
        body = {
           "date": "2013-04-10",
           "steps": 6523,
           "distance": 4600,
           "calories": 408.52,
           "elevation": 18.2,
           "soft": 5880,
           "moderate": 1080,
           "intense": 540,
           "timezone": "Europe/Berlin"
        }
        self.mock_request(body)
        resp = self.api.get_activities()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/measure',
            params={'action': 'getactivity'})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 1)
        self.assertEqual(type(resp[0]), WithingsActivity)
        # No need to assert all attributes, that happens elsewhere
        self.assertEqual(resp[0].data, body)

        # Test multiple activities
        new_body = {
            'activities': [
                body, {
                   "date": "2013-04-11",
                   "steps": 223,
                   "distance": 400,
                   "calories": 108.52,
                   "elevation": 1.2,
                   "soft": 160,
                   "moderate": 42,
                   "intense": 21,
                   "timezone": "Europe/Berlin"
                }
            ]
        }
        self.mock_request(new_body)
        resp = self.api.get_activities()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/measure',
            params={'action': 'getactivity'})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 2)
        self.assertEqual(type(resp[0]), WithingsActivity)
        self.assertEqual(type(resp[1]), WithingsActivity)
        self.assertEqual(resp[0].data, new_body['activities'][0])
        self.assertEqual(resp[1].data, new_body['activities'][1])

    def test_get_measures(self):
        """
        Check that get_measures fetches the appriate URL, the response looks
        correct, and the return value is a WithingsMeasures object
        """
        body = {
            'updatetime': 1409596058,
            'measuregrps': [
                {'attrib': 2, 'measures': [
                    {'unit': -1, 'type': 1, 'value': 860}
                ], 'date': 1409361740, 'category': 1, 'grpid': 111111111},
                {'attrib': 2, 'measures': [
                    {'unit': -2, 'type': 4, 'value': 185}
                ], 'date': 1409361740, 'category': 1, 'grpid': 111111112}
            ]
        }
        self.mock_request(body)
        resp = self.api.get_measures()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/measure',
            params={'action': 'getmeas'})
        self.assertEqual(type(resp), WithingsMeasures)
        self.assertEqual(len(resp), 2)
        self.assertEqual(type(resp[0]), WithingsMeasureGroup)
        self.assertEqual(resp[0].weight, 86.0)
        self.assertEqual(resp[1].height, 1.85)

        # Test limit=1
        body['measuregrps'].pop()
        self.mock_request(body)
        resp = self.api.get_measures(limit=1)
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/measure',
            params={'action': 'getmeas', 'limit': 1})
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0].weight, 86.0)

    def test_subscribe(self):
        """
        Check that subscribe fetches the right URL and returns the expected
        results
        """
        self.mock_request(None)
        resp = self.api.subscribe('http://www.example.com/', 'fake_comment')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'subscribe', 'appli': 1,
                    'comment': 'fake_comment',
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)

    def test_unsubscribe(self):
        """
        Check that unsubscribe fetches the right URL and returns the expected
        results
        """
        self.mock_request(None)
        resp = self.api.unsubscribe('http://www.example.com/')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'revoke', 'appli': 1,
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)


    def test_is_subscribed(self):
        """
        Check that is_subscribed fetches the right URL and returns the
        expected results
        """
        url = 'http://wbsapi.withings.net/notify'
        params = {
            'callbackurl': 'http://www.example.com/',
            'action': 'get',
            'appli': 1
        }
        self.mock_request({'expires': 2147483647, 'comment': 'fake_comment'})
        resp = self.api.is_subscribed('http://www.example.com/')
        Session.request.assert_called_once_with('GET', url, params=params)
        self.assertEquals(resp, True)

        # Not subscribed
        self.mock_request(None, status=343)
        resp = self.api.is_subscribed('http://www.example.com/')
        Session.request.assert_called_once_with('GET', url, params=params)
        self.assertEquals(resp, False)

    def test_list_subscriptions(self):
        """
        Check that list_subscriptions fetches the right URL and returns the
        expected results
        """
        self.mock_request({'profiles': [
            {'comment': 'fake_comment', 'expires': 2147483647}
        ]})
        resp = self.api.list_subscriptions()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'list', 'appli': 1})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0]['comment'], 'fake_comment')
        self.assertEqual(resp[0]['expires'], 2147483647)

        # No subscriptions
        self.mock_request({'profiles': []})
        resp = self.api.list_subscriptions()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'list', 'appli': 1})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 0)

    def mock_request(self, body, status=0):
        if self.mock_api:
            json_content = {'status': status}
            if body != None:
                json_content['body'] = body
            response = MagicMock()
            response.content = json.dumps(json_content).encode('utf8')
            Session.request = MagicMock(return_value=response)
Exemple #6
0
class WITHINGclass:
    """
    Get informations about withing
    """
    # -------------------------------------------------------------------------------------------------
    def __init__(self, log, api_id, api_secret, period, dataPath):
        try:
            """
            Create a withing instance, allowing to use withing api
            """
            self._log = log
            self.api_id = api_id
            self.api_secret = api_secret
            self.period = period
	    self._sensors = []

	    self._dataPath = dataPath 

            if not os.path.exists(self._dataPath) :
                self._log.info(u"Directory data not exist, trying create : %s" , self._dataPath)
                try :
                    os.mkdir(self._dataPath)
                    self._log.info(u"Withings data directory created : %s"  %self._dataPath)
                except Exception as e:
                    self._log.error(e.message)
                    raise withingException ("Withings data directory not exist : %s" % self._dataPath)
	    if not os.access(self._dataPath, os.W_OK) :
                self._log.error("User %s haven't write access on data directory : %s"  %(user,  self._dataPath))
    	        raise withingException ("User %s haven't write access on data directory : %s"  %(user,  self._dataPath))

            self.withing_config_file = os.path.join(os.path.dirname(__file__), '../data/withings.json')
	    self.auth = WithingsAuth(self.api_id, self.api_secret)
#	    self.open_token(self.auth)

            try:
    	        with open(self.withing_config_file, 'r') as withing_token_file:
                    self._log.debug(u"Opening File")
                    self.creds = pickle.load(withing_token_file)
                    self._log.debug(u"Getting user")
		    self.client = WithingsApi(self.creds)
		    self.user = self.client.get_user()
                    if self.user == None :
                        self.auth = WithingsAuth(self.api_key, self.api_secret)
		        self.authorize_url = self.auth.get_authorize_url()
		        print("Go to %s allow the app and copy your oauth_verifier" %self.authorize_url)
		        self.oauth_verifier = raw_input('Please enter your oauth_verifier: ')
		        self.creds = auth.get_credentials(self.oauth_verifier)
		        self.client = WithingsApi(creds)
		        self.user = self.client.get_user()
                        if user == None :
                            self._log.error(u"Error getting user, from code")
                            self._log.error(error)
                            sys.exit("refreshing token failed from refresh_token")
                            #TODO stop plugin
                        else :
                            self._log.warning(u"Token succesfully refresh with token_refresh from file")
                with open(self.withing_config_file, 'w') as withing_token_file:
                    pickle.dump(self.creds, withing_token_file)

            except ValueError:
                self._log.error(u"error reading Withing.")
                return
        except ValueError:
            self._log.error(u"error reading Withing.")


    def open_token(self, auth):
            try:
    	        with open(withing_config_file, 'r') as withing_token_file:
                    self._log.debug(u"Opening File")
                    self.creds = pickle.load(withing_token_file)
                    self._log.debug(u"Getting user")
		    self.client = WithingsApi(self.creds)
		    self.user = self.client.get_user()
                    if user == None :
                        self.auth = WithingsAuth(self.api_key, self.api_secret)
		        self.authorize_url = self.auth.get_authorize_url()
		        print("Go to %s allow the app and copy your oauth_verifier" %self.authorize_url)
		        self.oauth_verifier = raw_input('Please enter your oauth_verifier: ')
		        self.creds = auth.get_credentials(self.oauth_verifier)
		        self.client = WithingsApi(creds)
		        self.user = self.client.get_user()
                        if user == None :
                            self._log.error(u"Error getting user, from code")
                            self._log.error(error)
                            sys.exit("refreshing token failed from refresh_token")
                            #TODO stop plugin
                        else :
                            self._log.warning(u"Token succesfully refresh with token_refresh from file")
                with open(withing_config_file, 'w') as withing_token_file:
                    pickle.dump(self.creds, withing_token_file)

            except:
                self._log.error(u"Error with file saved or no file saved")
                self._log.error(u"Go to Advanced page to generate a new token file")
                #TODO stop plugin

    # -------------------------------------------------------------------------------------------------
    def add_sensor(self, device_id, device_name, device_type, user_id):
        """
        Add a sensor to sensors list.
        """
        self._sensors.append({'device_id': device_id, 'device_name': device_name, 'device_type': device_type,
                              'user_id': user_id})


    # -------------------------------------------------------------------------------------------------
    def readWithingApi(self, userid):
        """
        read the withing api for user information
        """
        try:
            user = self.client.get_user()
            self._log.debug(user)
            return user
        except AttributeError:
            self._log.error(u"### USERid '%s', ERROR while reading client value." % userid)
            return "failed"

    # -------------------------------------------------------------------------------------------------
    def readWithingMeasureApi(self, userid):
        """
        read the withing measure api information
        """
        try:
            measures = self.client.get_measures()
            return measures[0].data
        except AttributeError:
            self._log.error(u"### USERid '%s', ERROR while reading measure value." % userid)
            return "failed"


    # -------------------------------------------------------------------------------------------------
    def loop_read_sensor(self, send, send_sensor, stop):
        """
        """
        while not stop.isSet():
	    for sensor in self._sensors:
		self._log.debug(sensor)
                if sensor['device_type'] == "withing.user":
                    val = self.readWithingApi(sensor['user_id'])
		    self._log.debug(val)
                    if val != "failed":
			self._log.debug(val)
			self._log.debug(sensor)
                        send(sensor['device_id'], {'firstname': val['users'][0]['firstname'], 'lastname': val['users'][0]['lastname'], 'id': val['users'][0]['id']})
                elif sensor['device_type'] == "withing.measure":
                    val = self.readWithingMeasureApi(sensor['user_id'])
		    self._log.debug(val)
                    if val != "failed":
			timestamp = val['date']
			for measure in val['measures']:
                            sensor_name = u''
			    self._log.debug(measure)
                            if measure['type'] == 1:
                                sensor_name = "weight"
                            elif measure['type'] == 4:
                                sensor_name = "height"
                            elif measure['type'] == 5:
                                sensor_name = "fat_free_mass"
                            elif measure['type'] == 6:
                                sensor_name = "fat_ratio"
                            elif measure['type'] == 8:
                                sensor_name = "fat_free_mass"
                            elif measure['type'] == 9:
                                sensor_name = "diastolic_blood_pressure"
                            elif measure['type'] == 10:
                                sensor_name = "systolic_blood_pressure"
                            elif measure['type'] == 11:
                                sensor_name = "heart_pulse"
                            if sensor_name != u'':
                                #timestamp = calendar.timegm(sensors.date.timetuple())
				#timestamp=time.time()
				self._log.debug("Sending value to binary")
				value=float(measure['value'])/pow(10, abs(measure['unit']))
			        send_sensor(sensor['device_id'], sensor_name, value, timestamp)

                self._log.debug(u"=> '{0}' : wait for {1} seconds".format(sensor['device_name'], self.period))
    	    stop.wait(self.period)
class TestWithingsApi(unittest.TestCase):
    def setUp(self):
        self.mock_api = True
        if self.mock_api:
            self.creds = WithingsCredentials()
        else:
            config = ConfigParser.ConfigParser()
            config.read('withings.conf')
            self.creds = WithingsCredentials(
                consumer_key=config.get('withings', 'consumer_key'),
                consumer_secret=config.get('withings', 'consumer_secret'),
                access_token=config.get('withings', 'access_token'),
                access_token_secret=config.get('withings',
                                               'access_token_secret'),
                user_id=config.get('withings', 'user_id'))
        self.api = WithingsApi(self.creds)

    def test_attributes(self):
        """ Make sure the WithingsApi objects have the right attributes """
        assert hasattr(WithingsApi, 'URL')
        creds = WithingsCredentials(user_id='FAKEID')
        api = WithingsApi(creds)
        assert hasattr(api, 'credentials')
        assert hasattr(api, 'oauth')
        assert hasattr(api, 'client')

    def test_attribute_defaults(self):
        """
        Make sure WithingsApi object attributes have the correct defaults
        """
        self.assertEqual(WithingsApi.URL, 'http://wbsapi.withings.net')
        creds = WithingsCredentials(user_id='FAKEID')
        api = WithingsApi(creds)
        self.assertEqual(api.credentials, creds)
        self.assertEqual(api.client.auth, api.oauth)
        self.assertEqual(api.client.params, {'userid': creds.user_id})

    def test_request(self):
        """
        Make sure the request method builds the proper URI and returns the
        request body as a python dict.
        """
        self.mock_request({})
        resp = self.api.request('fake_service', 'fake_action')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/fake_service',
            params={'action': 'fake_action'})
        self.assertEqual(resp, {})

    def test_request_params(self):
        """
        Check that the request method passes along extra params and works
        with different HTTP methods
        """
        self.mock_request({})
        resp = self.api.request('user', 'getbyuserid', params={'p2': 'p2'},
                                method='POST')
        Session.request.assert_called_once_with(
            'POST', 'http://wbsapi.withings.net/user',
            params={'p2': 'p2', 'action': 'getbyuserid'})
        self.assertEqual(resp, {})

    def test_request_error(self):
        """ Check that requests raises an exception when there is an error """
        self.mock_request('', status=1)
        self.assertRaises(Exception, self.api.request, ('user', 'getbyuserid'))

    def test_get_user(self):
        """ Check that the get_user method fetches the right URL """
        self.mock_request({
            'users': [
                {'id': 1111111, 'birthdate': 364305600, 'lastname': 'Baggins',
                 'ispublic': 255, 'firstname': 'Frodo', 'fatmethod': 131,
                 'gender': 0, 'shortname': 'FRO'}
            ]
        })
        resp = self.api.get_user()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/user',
            params={'action': 'getbyuserid'})
        self.assertEqual(type(resp), dict)
        assert 'users' in resp
        self.assertEqual(type(resp['users']), list)
        self.assertEqual(len(resp['users']), 1)
        self.assertEqual(resp['users'][0]['firstname'], 'Frodo')
        self.assertEqual(resp['users'][0]['lastname'], 'Baggins')

    def test_get_sleep(self):
        """
        Check that get_sleep fetches the appropriate URL, the response looks
        correct, and the return value is a WithingsSleep object with the
        correct attributes
        """
        body = {
            "series": [{
                "startdate": 1387235398,
                "state": 0,
                "enddate": 1387235758
            }, {
                "startdate": 1387243618,
                "state": 1,
                "enddate": 1387244518
            }],
            "model": 16
        }
        self.mock_request(body)
        resp = self.api.get_sleep()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/sleep',
            params={'action': 'get'})
        self.assertEqual(type(resp), WithingsSleep)
        self.assertEqual(resp.model, body['model'])
        self.assertEqual(type(resp.series), list)
        self.assertEqual(len(resp.series), 2)
        self.assertEqual(type(resp.series[0]), WithingsSleepSeries)
        self.assertEqual(resp.series[0].startdate.timestamp,
                         body['series'][0]['startdate'])
        self.assertEqual(resp.series[0].enddate.timestamp,
                         body['series'][0]['enddate'])
        self.assertEqual(resp.series[1].state, 1)


    def test_get_activities(self):
        """
        Check that get_activities fetches the appropriate URL, the response
        looks correct, and the return value is a list of WithingsActivity
        objects
        """
        body = {
           "date": "2013-04-10",
           "steps": 6523,
           "distance": 4600,
           "calories": 408.52,
           "elevation": 18.2,
           "soft": 5880,
           "moderate": 1080,
           "intense": 540,
           "timezone": "Europe/Berlin"
        }
        self.mock_request(body)
        resp = self.api.get_activities()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/measure',
            params={'action': 'getactivity'})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 1)
        self.assertEqual(type(resp[0]), WithingsActivity)
        # No need to assert all attributes, that happens elsewhere
        self.assertEqual(resp[0].data, body)

        # Test multiple activities
        new_body = {
            'activities': [
                body, {
                   "date": "2013-04-11",
                   "steps": 223,
                   "distance": 400,
                   "calories": 108.52,
                   "elevation": 1.2,
                   "soft": 160,
                   "moderate": 42,
                   "intense": 21,
                   "timezone": "Europe/Berlin"
                }
            ]
        }
        self.mock_request(new_body)
        resp = self.api.get_activities()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/v2/measure',
            params={'action': 'getactivity'})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 2)
        self.assertEqual(type(resp[0]), WithingsActivity)
        self.assertEqual(type(resp[1]), WithingsActivity)
        self.assertEqual(resp[0].data, new_body['activities'][0])
        self.assertEqual(resp[1].data, new_body['activities'][1])

    def test_get_measures(self):
        """
        Check that get_measures fetches the appriate URL, the response looks
        correct, and the return value is a WithingsMeasures object
        """
        body = {
            'updatetime': 1409596058,
            'measuregrps': [
                {'attrib': 2, 'measures': [
                    {'unit': -1, 'type': 1, 'value': 860}
                ], 'date': 1409361740, 'category': 1, 'grpid': 111111111},
                {'attrib': 2, 'measures': [
                    {'unit': -2, 'type': 4, 'value': 185}
                ], 'date': 1409361740, 'category': 1, 'grpid': 111111112}
            ]
        }
        self.mock_request(body)
        resp = self.api.get_measures()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/measure',
            params={'action': 'getmeas'})
        self.assertEqual(type(resp), WithingsMeasures)
        self.assertEqual(len(resp), 2)
        self.assertEqual(type(resp[0]), WithingsMeasureGroup)
        self.assertEqual(resp[0].weight, 86.0)
        self.assertEqual(resp[1].height, 1.85)

        # Test limit=1
        body['measuregrps'].pop()
        self.mock_request(body)
        resp = self.api.get_measures(limit=1)
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/measure',
            params={'action': 'getmeas', 'limit': 1})
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0].weight, 86.0)

    def test_subscribe(self):
        """
        Check that subscribe fetches the right URL and returns the expected
        results
        """
        # Unspecified appli
        self.mock_request(None)
        resp = self.api.subscribe('http://www.example.com/', 'fake_comment')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'subscribe', 'comment': 'fake_comment',
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)

        # appli=1
        self.mock_request(None)
        resp = self.api.subscribe('http://www.example.com/', 'fake_comment',
                                  appli=1)
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'subscribe', 'appli': 1,
                    'comment': 'fake_comment',
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)

    def test_unsubscribe(self):
        """
        Check that unsubscribe fetches the right URL and returns the expected
        results
        """
        # Unspecified appli
        self.mock_request(None)
        resp = self.api.unsubscribe('http://www.example.com/')
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'revoke',
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)

        # appli=1
        self.mock_request(None)
        resp = self.api.unsubscribe('http://www.example.com/', appli=1)
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'revoke', 'appli': 1,
                    'callbackurl': 'http://www.example.com/'})
        self.assertEqual(resp, None)


    def test_is_subscribed(self):
        """
        Check that is_subscribed fetches the right URL and returns the
        expected results
        """
        url = 'http://wbsapi.withings.net/notify'
        params = {
            'callbackurl': 'http://www.example.com/',
            'action': 'get',
            'appli': 1
        }
        self.mock_request({'expires': 2147483647, 'comment': 'fake_comment'})
        resp = self.api.is_subscribed('http://www.example.com/')
        Session.request.assert_called_once_with('GET', url, params=params)
        self.assertEquals(resp, True)

        # Not subscribed
        self.mock_request(None, status=343)
        resp = self.api.is_subscribed('http://www.example.com/')
        Session.request.assert_called_once_with('GET', url, params=params)
        self.assertEquals(resp, False)

    def test_list_subscriptions(self):
        """
        Check that list_subscriptions fetches the right URL and returns the
        expected results
        """
        self.mock_request({'profiles': [
            {'comment': 'fake_comment', 'expires': 2147483647}
        ]})
        resp = self.api.list_subscriptions()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'list', 'appli': 1})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 1)
        self.assertEqual(resp[0]['comment'], 'fake_comment')
        self.assertEqual(resp[0]['expires'], 2147483647)

        # No subscriptions
        self.mock_request({'profiles': []})
        resp = self.api.list_subscriptions()
        Session.request.assert_called_once_with(
            'GET', 'http://wbsapi.withings.net/notify',
            params={'action': 'list', 'appli': 1})
        self.assertEqual(type(resp), list)
        self.assertEqual(len(resp), 0)

    def mock_request(self, body, status=0):
        if self.mock_api:
            json_content = {'status': status}
            if body != None:
                json_content['body'] = body
            response = MagicMock()
            response.content = json.dumps(json_content).encode('utf8')
            Session.request = MagicMock(return_value=response)
def _fetch_withings():

    results = []

    creds = WithingsCredentials()
    creds.access_token = ACCESS_TOKEN
    creds.access_token_secret = ACCESS_TOKEN_SECRET
    creds.user_id = USER_ID
    creds.consumer_key = CONSUMER_KEY
    creds.consumer_secret = CONSUMER_SECRET
    client = WithingsApi(creds)

    readings = {
        # predictions
        'future' : {
            'x': '',
            'diastolic': '',
            'systolic': '',
            'pulse': '',
            'simple_moving_average' : {
                'diastolic': '',
                'pulse': '',
                'systolic': '',
            }
        },
        # analysis of past readings
        'past': {
            'x': '',
            'diastolic': '',
            'systolic': '',
            'pulse': '',
            'simple_moving_average' : {
                'diastolic': '',
                'pulse': '',
                'systolic': '',
            }
        }
    }

    measures = client.get_measures()

    # make sure the graph goes left to right
    measures.reverse()

    last_reading_date = measures[-1].date
    counter = 1

    raw_readings = {
        'systolic': [],
        'diastolic': [],
        'pulse': [],
    }

    for measure in measures:

        if measure.systolic_blood_pressure\
           and measure.diastolic_blood_pressure:

            next_date = last_reading_date + timedelta(days=counter)

            # sort out date times
            readings['past']['x'] += '"' + measure.date.strftime('%Y-%m-%d %H:%M:%S') + '",'
            readings['future']['x'] += '"' + next_date.strftime('%Y-%m-%d %H:%M:%S') + '",'

            readings['past']['systolic'] += str(measure.systolic_blood_pressure) + ','
            readings['past']['diastolic'] += str(measure.diastolic_blood_pressure) + ','

            # keep ints for for sending to ALGORITHMIA
            # should really rename it...
            raw_readings['systolic'].append(measure.systolic_blood_pressure)
            raw_readings['diastolic'].append(measure.diastolic_blood_pressure)

            if measure.heart_pulse and measure.heart_pulse > 30:
                raw_readings['pulse'].append(measure.heart_pulse)
                readings['past']['pulse'] += str(measure.heart_pulse) + ','

            counter += 1

        if measure.weight:
            pass

    # trim that last ,
    readings['past']['diastolic'] = readings['past']['diastolic'][:-1]
    readings['past']['systolic'] = readings['past']['systolic'][:-1]
    readings['past']['pulse'] = readings['past']['pulse'][:-1]

    # simple moving average of existing data
    readings['past']['simple_moving_average']['diastolic'], average_diastolic = _get_simple_moving_average(raw_readings['diastolic'])
    readings['past']['simple_moving_average']['systolic'], average_systolic = _get_simple_moving_average(raw_readings['systolic'])
    readings['past']['simple_moving_average']['pulse'], average_pulse = _get_simple_moving_average(raw_readings['pulse'])

    global FORECAST_ON_AVERAGE

    if FORECAST_ON_AVERAGE:
        readings['future']['diastolic'], future_diastolic = _get_forecast(average_diastolic)
        readings['future']['systolic'], future_systolic = _get_forecast(average_systolic)
        readings['future']['pulse'], future_pulse = _get_forecast(average_pulse)
    else:
        # populate the standard graphs and get the raw data to feed into thenext algorithm
        readings['future']['diastolic'], future_diastolic = _get_forecast(raw_readings['diastolic'])
        readings['future']['systolic'], future_systolic = _get_forecast(raw_readings['systolic'])
        readings['future']['pulse'], future_pulse = _get_forecast(raw_readings['pulse'])

    # simple moving average of future data
    readings['future']['simple_moving_average']['diastolic'], average_diastolic = _get_simple_moving_average(future_diastolic)
    readings['future']['simple_moving_average']['systolic'], average_systolic = _get_simple_moving_average(future_systolic)
    readings['future']['simple_moving_average']['pulse'], average_pulse = _get_simple_moving_average(future_pulse)

    return readings
Exemple #9
0
def _fetch_withings():

    results = []

    creds = WithingsCredentials()
    creds.access_token = ACCESS_TOKEN
    creds.access_token_secret = ACCESS_TOKEN_SECRET
    creds.user_id = USER_ID
    creds.consumer_key = CONSUMER_KEY
    creds.consumer_secret = CONSUMER_SECRET
    client = WithingsApi(creds)

    readings = {
        # predictions
        'future': {
            'x': '',
            'diastolic': '',
            'systolic': '',
            'pulse': '',
            'simple_moving_average': {
                'diastolic': '',
                'pulse': '',
                'systolic': '',
            }
        },
        # analysis of past readings
        'past': {
            'x': '',
            'diastolic': '',
            'systolic': '',
            'pulse': '',
            'simple_moving_average': {
                'diastolic': '',
                'pulse': '',
                'systolic': '',
            }
        }
    }

    measures = client.get_measures()

    # make sure the graph goes left to right
    measures.reverse()

    last_reading_date = measures[-1].date
    counter = 1

    raw_readings = {
        'systolic': [],
        'diastolic': [],
        'pulse': [],
    }

    for measure in measures:

        if measure.systolic_blood_pressure\
           and measure.diastolic_blood_pressure:

            next_date = last_reading_date + timedelta(days=counter)

            # sort out date times
            readings['past']['x'] += '"' + measure.date.strftime(
                '%Y-%m-%d %H:%M:%S') + '",'
            readings['future']['x'] += '"' + next_date.strftime(
                '%Y-%m-%d %H:%M:%S') + '",'

            readings['past']['systolic'] += str(
                measure.systolic_blood_pressure) + ','
            readings['past']['diastolic'] += str(
                measure.diastolic_blood_pressure) + ','

            # keep ints for for sending to ALGORITHMIA
            # should really rename it...
            raw_readings['systolic'].append(measure.systolic_blood_pressure)
            raw_readings['diastolic'].append(measure.diastolic_blood_pressure)

            if measure.heart_pulse and measure.heart_pulse > 30:
                raw_readings['pulse'].append(measure.heart_pulse)
                readings['past']['pulse'] += str(measure.heart_pulse) + ','

            counter += 1

        if measure.weight:
            pass

    # trim that last ,
    readings['past']['diastolic'] = readings['past']['diastolic'][:-1]
    readings['past']['systolic'] = readings['past']['systolic'][:-1]
    readings['past']['pulse'] = readings['past']['pulse'][:-1]

    # simple moving average of existing data
    readings['past']['simple_moving_average'][
        'diastolic'], average_diastolic = _get_simple_moving_average(
            raw_readings['diastolic'])
    readings['past']['simple_moving_average'][
        'systolic'], average_systolic = _get_simple_moving_average(
            raw_readings['systolic'])
    readings['past']['simple_moving_average'][
        'pulse'], average_pulse = _get_simple_moving_average(
            raw_readings['pulse'])

    global FORECAST_ON_AVERAGE

    if FORECAST_ON_AVERAGE:
        readings['future']['diastolic'], future_diastolic = _get_forecast(
            average_diastolic)
        readings['future']['systolic'], future_systolic = _get_forecast(
            average_systolic)
        readings['future']['pulse'], future_pulse = _get_forecast(
            average_pulse)
    else:
        # populate the standard graphs and get the raw data to feed into thenext algorithm
        readings['future']['diastolic'], future_diastolic = _get_forecast(
            raw_readings['diastolic'])
        readings['future']['systolic'], future_systolic = _get_forecast(
            raw_readings['systolic'])
        readings['future']['pulse'], future_pulse = _get_forecast(
            raw_readings['pulse'])

    # simple moving average of future data
    readings['future']['simple_moving_average'][
        'diastolic'], average_diastolic = _get_simple_moving_average(
            future_diastolic)
    readings['future']['simple_moving_average'][
        'systolic'], average_systolic = _get_simple_moving_average(
            future_systolic)
    readings['future']['simple_moving_average'][
        'pulse'], average_pulse = _get_simple_moving_average(future_pulse)

    return readings