Sell personal fitness data on the Streamr Marketplace

Streamr Marketplace is a global data exchange platform offering easy integration APIs. In the Marketplace, any application can easily setup a stream to exchange/monetize data such as weather condition, traffic status and personal fitness for example.

Their explainer video is here:

One very important note is that data can be anonymised before being pushed to Marketplace, so privacy is not violated. This blog post will showcase how to integrate Google Fitness sensors data into the Streamr Marketplace so you can sell that information to potential buyers!

Preparations

  • Get a Google Account: To use the Fitness REST API, you need a Google Account. If you already have an account, then you’re all set.
  • Get a Streamr Account: If you do not have a Streamr account, please sign up here.
  • Download the Google Fit APP: You need a smartphone with the Google Fit APP to record data such as daily steps, calories, heartbeat, weight and other information. (Note: type of data available will depend on the sensors owned by each individual user)

Getting Started

I. Request a Google OAuth 2.0 client ID

To use the Google Fit REST API, you need an OAuth 2.0 client ID for Web or Android applications. Follow these steps to request a Google OAuth 2.0 client ID for the Fitness API.

  • Go to the Google API Console.
  • It will prompt to create a project if you don’t have one already or select an existing one. (Note: use the same project for the Android and REST versions of your app.)
  • Click Continue to enable the Fitness API.
  • Click Go to credentials.
  • Click New credentials, then select OAuth Client ID. If it is the first time setting up OAth, you might need to Configure consent screen
  • When creating the new OAth Client ID, under Application type select Web application.
  • Under Authorized JavaScript origins, enter the base URL of the site from which requests will originate (for examplehttps://developers.google.com is the URL used by the OAuth Playground).
  • Under Authorized redirect URI, enter the URL (for example https://developers.google.com/oauthplayground is the URL used by the OAuth Playground).
  • Click Create. Your new OAuth 2.0 Client ID and secret appear in the list of IDs for your project. An OAuth 2.0 Client ID is a string of characters, something like this:

780816631155-gbvyo1o7r2pn95qc4ei9d61io4uh48hl.apps.googleusercontent.com

II. Request the Google access token and refresh token

An access token is a credential that can be used by an application to access an API. A refresh token can be used to obtain a renewed access token when the access token has expired. To request the tokens, you can authorize the Fitness REST API in the OAuth Playground:

  • Go to the Google OAuth Playground.
  • Under Step 1 Select & authorize APIs, expand Fitness v1 and select the Fitness scopes to use.
  • Click the Setting button, select Use your own OAuth credentials , and input yourself Client ID and Client secret.
  • Click the Authorize APIs button, select the Google API Console project to use, and click Allow when prompted. You will be able to access and modify data associated with the selected Google API Console account.
  • Click the Exchange authorization code for tokens button.
  • After that, you will get the access token and refresh token, please write them down.

III. Create a Streamr stream

Using the aforementioned access token, client ID and secret, you can get Google Fitness Data in the type of JSON object. To upload the data to the Streamr, you need to create a stream in the Streamr Network. The stream (topic) is an ordered sequence of events (timestamped data points). Event payloads are JSON objects, or in other words, a set of key-value pairs. You can find the tutorial how to create a stream here. After that, please write down the Stream ID and API Keys.

IV. Run the python script

Please copy the following code to your host, replace the $YOUR_LOGFILE_PATH, $YOUR_STREAM_ID, $YOUR_API_KEY, $YOUR_CLIENT_ID, $YOUR_CLIENT_SECRET, $YOUR_REFERSH_TOKEN with yours, and keep running the script for live data to appear in a stream. Note that, this particular script has been coded in python 2.7. If you use python 3.x or other script languages, you will need to re-code it first.

# -*- coding: utf-8 -*-
import requests
import json
import logging as LOG
import time
import threading as thd
LOG.basicConfig(level=LOG.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='$YOUR_LOGFILE_PATH',
filemode='a')
# global variable
token = ''
# Get the following infomation from the Streamr
STREAM_ID = '$YOUR_STREAM_ID'
API_KEY = '$YOUR_API_KEY'
# Get the following information from the Google Fitness Platform
CLIENT_ID = '$YOUR_CLIENT_ID'
CLIENT_SECRET = '$YOUR_CLIENT_SECRET'
REFRESH_TOKEN = '$YOUR_REFERSH_TOKEN'
def get_user_token():
""" Request Google Fitness API token using the refresh token
NOTE: Update every 45min
"""
global token
global CLIENT_ID
global CLIENT_SECRET
global REFRESH_TOKEN

thd.Timer(2700,get_user_token).start()
url = 'https://www.googleapis.com/oauth2/v4/token'
body = ('{"client_secret":"%s", "grant_type":"refresh_token", "refresh_token":"%s", "client_id":"%s"}'%(CLIENT_SECRET, REFRESH_TOKEN, CLIENT_ID))
headers = '{"Content-Type":"application/x-www-form-urlencoded"}'
try:
req = requests.post(url, params=headers, data=body)
token = req.json()['access_token']
LOG.info("Get user token successfully: %s", token)
return token
except:
import traceback
LOG.error("Unable to get user token")
traceback.print_exc()
return None
def get_user_steps(access_token):
""" Request User Daily Steps stored in Google Fitness Platform.
"""
# unix timestamp: xxx seconds. Note: Google fitness update steps data one day later.
start_time = time.time() - (time.time() % 86400) + time.timezone - 86400
end_time = time.time() - 86400
url = 'https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate'
body = ('{"aggregateBy": [{"dataTypeName": "com.google.step_count.delta","dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"}],"bucketByTime": { "durationMillis": 86400000 },"startTimeMillis": %s, "endTimeMillis": %s}'%(start_time*1000, end_time*1000))
headers = {"Content-Type":"application/json","Authorization":"Bearer %s" % access_token}
try:
req = requests.post(url, headers=headers, data=body)
results_steps = req.json()
LOG.info("Get user daily steps successfully: %s", results_steps)
if len(results_steps['bucket'][0]['dataset'][0]['point']):
return results_steps['bucket'][0]['dataset'][0]['point'][0]['value'][0]['intVal']
else:
return None
except:
import traceback
LOG.error("Unable to get user daily steps.")
traceback.print_exc()
return None
def get_user_calories(access_token):
""" Request User Daily Consumed Calories stored in Google Fitness Platform.
"""
# unix timestamp: xxx seconds. Note: Google fitness update steps data one day later.
start_time = time.time() - (time.time() % 86400) + time.timezone - 86400
end_time = time.time() - 86400
url = 'https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate'
body = ('{"aggregateBy": [{"dataTypeName": "com.google.calories.expended","dataSourceId": "derived:com.google.calories.expended:com.google.android.gms:platform_calories_expended"}],"bucketByTime": { "durationMillis": 86400000 },"startTimeMillis": %s, "endTimeMillis": %s}'%(start_time*1000, end_time*1000))
headers = {"Content-Type":"application/json","Authorization":"Bearer %s" % access_token}
try:
req = requests.post(url, headers=headers, data=body)
results_calories = req.json()
LOG.info("Get user daily consumed calories successfully: %s", results_calories)
if len(results_calories['bucket'][0]['dataset'][0]['point']):
return results_calories['bucket'][0]['dataset'][0]['point'][0]['value'][0]['fpVal']
else:
return None
except:
import traceback
LOG.error("Unable to get user daily consumed calories.")
traceback.print_exc()
return None
def upload_to_streamr():
""" Upload Google Fitness Data to Streamr
NOTE: Upload per minute
"""
global token
global STREAM_ID
global API_KEY
url = 'https://www.streamr.com/api/v1/streams/'+STREAM_ID+'/data'
headers = {"Authorization":"token %s" % API_KEY}
steps = get_user_steps(token)
calories = get_user_calories(token)
if steps and calories:
body = ('{"Daily Steps": %s, "Daily Calories": %s}'%(steps,calories))
elif steps:
body = ('{"Daily Steps": %s, "Daily Calories": "Zero or not update"}'%steps)
elif calories:
body = ('{"Daily Steps": "Zero or not update", "Daily Calories": %s}'%calories)
else:
body = ('{"Daily Steps": "Zero or not update", "Daily Calories": "Zero or not update"}')
LOG.info("Google fitness data is: %s",body)
thd.Timer(60, upload_to_streamr).start()
try:
req = requests.post(url, headers=headers, data=body)
if req.status_code == 200 or req.status_code == 201:
LOG.info("Upload google fitness data to Streamr successfully.")
return req.status_code
else:
LOG.info("Fail to upload google fitness data to Streamr. ERROR: %s", req.status_code)
except:
import traceback
LOG.error("Fail to Upload Google Fitness Data to Streamr.")
traceback.print_exc()
return None
if __name__=="__main__":  
get_user_token()
upload_to_streamr()

Unless an error has occurred, you should be able to see your personal data in the stream!

V. Publish the stream to the Streamr Marketplace

To sell your Google Fitness Data on the Streamr Marketplace, you can follow the tutorial called “Creating a Product for the Streamr Data Marketplace”. It is important to keep in mind not to send any personal identifiable data to the Marketplace in order to protect users’ privacy right.