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 selectOAuth Client ID
. If it is the first time setting up OAth, you might need toConfigure consent screen
- When creating the new OAth Client ID, under
Application type
selectWeb 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 examplehttps://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, selectUse your own OAuth credentials
, and input yourselfClient ID
andClient 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
andrefresh 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 thdLOG.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 Nonedef 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 Nonedef 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 Nonedef 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 Noneif __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.