FitBit HR Data Raw

Excited by the Fitbit Charge 2’s second by second heart rate data, but frustrated by the lack of an easy export function for accessing this data in raw form, I rolled a very quick Node.js app to give me CSV-formatted raw data from Fitbit.  Note that to access the APIs I am using, you either need special approval, or a Personal application registered on the Fitbit developer portal.

It looks like this, after the app is initially authorized:

Clicking the “Get HR for Today” link gives me this raw CSV:

And so on.

Here’s the bare bones code, posted as a gist on GitHub:

1 thought on “FitBit HR Data Raw

  1. I am stuck in implementing this and when I tried your solution the issue still persists.
    The issue is when I try to get data the first time it works but the second time i click to get data it does not show any data and simply the browser keeps on loading. Please help me out. I am sure I am missing something here

    here is my code:::

    var express = require(‘express’);
    var path = require(‘path’);
    var favicon = require(‘serve-favicon’);
    var logger = require(‘morgan’);
    var cookieParser = require(‘cookie-parser’);
    var bodyParser = require(‘body-parser’);
    var cors = require(‘cors’);
    var routes = require(‘./routes/index’);
    var users = require(‘./routes/users’);
    var sql=require(‘mssql’);
    var app = express();

    // view engine setup
    app.set(‘views’, path.join(__dirname, ‘views’));
    app.set(‘view engine’, ‘ejs’);

    // uncomment after placing your favicon in /public
    //app.use(favicon(path.join(__dirname, ‘public’, ‘favicon.ico’)));
    app.use(logger(‘dev’));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser());
    app.use(require(‘stylus’).middleware(path.join(__dirname, ‘public’)));
    app.use(express.static(path.join(__dirname, ‘public’)));

    app.use(cors({origin: ‘https://www.fitbit.com’}));

    app.use(‘/users’, users);

    var config = {
    user: ‘sa’,
    password: ‘*****’,
    server: ‘localhost’, // You can use ‘localhost\\instance’ to connect to named instance
    database: ‘BadmintonCG’,

    options: {
    encrypt: true // Use this if you’re on Windows Azure
    }
    }

    app.get(‘/getFitbitAccounts’,function(req,res)
    {
    sql.connect(config).then(function() {

    new sql.Request()
    .query(“select * from FitBitUserAccount”).then(function(data){
    return res.send(data);
    }).catch(function(err){
    console.log(err);
    });

    });
    });

    var FitbitApiClient = require(“fitbit-node”);
    var client = new FitbitApiClient(“”, “”);

    app.get(“/logout”,function(req,res){
    return res.redirect(“https://www.fitbit.com/logout”)
    });
    // redirect the user to the Fitbit authorization page
    app.get(“/authorize/:id”, function (req, res) {
    // request access to the user’s activity, heartrate, location, nutrion, profile, settings, sleep, social, and weight scopes

    sql.connect(config).then(function() {

    new sql.Request()
    .input(‘id’, sql.Int, req.params.id)
    .query(“select * from FitBitUserAccount where id=@id”).then(function(data){
    console.log(data[0].ClientId);
    client=new FitbitApiClient(data[0].ClientId.toString(),data[0].ClientSecret)
    //return res.send(data);
    }).catch(function(err){
    console.log(err);
    });

    var returnUrl=client.getAuthorizeUrl(‘activity heartrate location nutrition profile settings sleep social weight’, ‘http://localhost:3000/Fitbit/Callback’);
    //console.log(returnUrl);
    return res.send(returnUrl);
    })

    });

    // handle the callback from the Fitbit authorization flow
    app.get(“/Fitbit/Callback”, function (req, res) {
    // // exchange the authorization code we just received for an access token
    // client.getAccessToken(req.query.code, ‘http://localhost:3000/Fitbit/Callback’).then(function (result) {
    // // use the access token to fetch the user’s information
    // // client.get(“/activities/heart/date/2016-10-26/1d.json”, result.access_token).then(function (results) {
    // // //results[0].replace(“activities-heart-intraday”,”heartrate”)
    // // var str=JSON.stringify(results[0]);
    // // str=str.replace(“activities-heart-intraday”,”heartrate”)
    // // var heartrate=JSON.parse(str);
    console.log(“return”)
    res.sendFile(‘public/index.html’, { root: __dirname });

    });
    //});

    app.get(“/getheartbeats”,function(req,res){
    console.log(req.params.code)
    var code=req.query.code;
    client.getAccessToken(code, ‘http://localhost:3000/Fitbit/Callback’).then(function (result) {

    // use the access token to fetch the user’s information
    client.get(“/activities/heart/date/2016-10-26/1d.json”, result.access_token).then(function (results) {

    //results[0].replace(“activities-heart-intraday”,”heartrate”)
    var str=JSON.stringify(results[0]);
    str=str.replace(“activities-heart-intraday”,”heartrate”)
    var heartrate=JSON.parse(str);
    res.send(heartrate);
    });
    });
    });

    app.all(‘/*’, function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile(‘public/index.html’, { root: __dirname });
    });

    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
    var err = new Error(‘Not Found’);
    err.status = 404;
    next(err);
    });

    // error handlers

    // development error handler
    // will print stacktrace
    if (app.get(‘env’) === ‘development’) {
    app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render(‘error’, {
    message: err.message,
    error: err
    });
    });
    }

    // production error handler
    // no stacktraces leaked to user
    app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render(‘error’, {
    message: err.message,
    error: {}
    });
    });

    module.exports = app;

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Posts

Categories

Archives

GiottoPress by Enrique Chavez