Playing with the Fitbit API

A little over a week ago I had major back surgery (spinal fusion of L4-L5 and a laminectomy on both L1 and L2) and as part of my recovery plan I bought a Fitbit so that I could game myself, by which I mean that I’d have something to measure (daily steps) as part of my recovery plan, which I have been since I got home last Thursday after a three night stay in the hospital. The first couple days I could barely walk (5 minutes every 5 hours) but since then I’ve really been improving on the walking side and by doing my 3x daily workout plan provided by the hospital (each workout takes about 1.5 hours including 10 minutes of walking), all of which I’m recording via the fitbit website as “activities” in addition to recording my sleep (happens automatically via the device), the steps I take per day (ditto) and my weight.

One of the things that I started in December, after reading about it on Rafe’s site, was the notion of using a spreadsheet to record your weight so that you could see your trend of weight over time, the thinking (and reality for me) being that your weight fluctuates up and down every day but if you’re doing things right, you’ll slowly start to lose weight which will show up on the graph as a downward trend. I slowly ballooned up to 210lbs over the last couple years as a result of eating poorly, no exercise (I stopped walking nightly because my legs would go numb / have sharp shooting pains, see above back surgery) and being busy at work and since putting the line diet in place back on December 1st, I’ve lost 14 pounds. And since the Fitbit website has web version of the line diet and an API I thought it would make sense to try and take all the date –> weight pairs in my Excel spreadsheet and pump them into the Fitbit website so that I wouldn’t be duplicating data. Because it was a one time thing I wanted to do it from the command line at first (maybe I’ll build a web application later) but it ended up only taking me a couple days (I can only sit in front of the computer for 30 minutes at a time) and I finally got it working last night. Here’s a rundown of the path I took:

1) Visited https://dev.fitbit.com/ to get started. It’s been so long since I did anything non-Jive, was interesting to see how developer communities are structured (or not structured? one web app / main page for app registration / description of the API, a Confluence instance for documentation and a Google Group for discussions) but step 1 (registering my application with fitbit.com) was really easy. Got my consumer key and consumer secret and I was off and running.

2) I downloaded the fitbit Java library, as well as the required commons logging, joda-time and JSON Java libraries. Ran into an issue downloading the JSON lib, which recently got moved over to Github but had everything downloaded and a project started in Eclipse in a couple minutes.

3) Next, I headed over to the client reference app page and read through that and the OAuth Authentication documentation. Couple problems I ran into with the client reference app:

a) it assumed a web-based application (specifically one built on top of Stripes) and I was building a desktop / command line client and

b) they provided the source code for the example application but then included source code snippets from the Java client, which they (Fitbit) do not provide the source code for. There were a number of times where I wanted to see how something was done in the client but couldn’t because the source isn’t available. Would be helpful (IMHO) to see that posted (and I asked as much on the Confluence doc page).

c) the client reference app source code shows the initialization of the Fitbit client happening like this:

client =
new FitbitAPIClientService(
getApiBaseUrl(),
getFitbitSiteBaseUrl(),
getEnvironmentPrefix() + "fitbit-example-client-application",
"e388e4f4d6f4cc10ff6dc0fd1637da370478e49e2",
credentialsCache,
entityCache,
subscriptionStore
);

but the it looks like the Fitbit Java API had since changed to require an instance of FitbitApiClientAgent as part of the constructor.

4) After wading through the docs, I wanted to sling some code… first step, since I was writing a desktop / command line client, was to request that my user account on fitbit.com grant my application the ability to read / write to it. Again, since I was doing this all manually, the code I needed looked like this:


String userID = "224B2Q";
LocalUserDetail ud = new LocalUserDetail(userID);
String url = client.getResourceOwnerAuthorizationURL(ud, "http://cephas.net/projects/fitbit/callback");

and then I printed out the resulting URL, which looks like this (and is now expired so I don’t mind showing you here):

http://www.fitbit.com/oauth/authorize?oauth_token=80ea75550b338a754f1d1a5393ac561c

copied that into my browser and the resulting page (after clicking the “Allow” button), contained a PIN which I then needed to programmatically submit back to Fitbit.com to complete the process:


AccessToken at = agent.getOAuthAccessToken(
"80ea75550b338a754f1d1a5393ac561c", // <-- oauth_token created in step1
consumerSecret, // <-- consumer secret created via registration of app
"6gelilrnqoggdkkqfss3ombodl"); // <-- PIN returned via web page

which resulted in a OAuth token and token secret that I could then use to make any requests for my user going forward.

5) One of the confusing things about the API / examples: most of the example application API invocations are doing using the FitbitAPIClientService class, which is relatively limited (only a couple useful methods, none for modifying / deleting data) versus the FitbitApiClientAgent, which contains the kitchen sink. Either way, the first thing I tried to do was to simply retrieve my activities using code that looked like this (reminder that if this was backed by a web app that I'd be retrieving the oauth token and secret from a persistent store and not just hardcoding in the construction):

APIResourceCredentials creds = new APIResourceCredentials(userID, "", "");
creds.setAccessToken(oauth_token);
creds.setAccessTokenSecret(oauth_secret);
client.saveResourceCredentials(ud, creds);
Activities o = client.getActivities(ud, new LocalDate());

which resulted in this:


Exception in thread "main" java.lang.NullPointerException at com.fitbit.api.client.FitbitApiClientAgent.setAccessToken(FitbitApiClientAgent.java:694) at com.fitbit.api.client.FitbitApiClientAgent.getCollectionResponseForDate(FitbitApiClientAgent.java:456) at com.fitbit.api.client.FitbitApiClientAgent.getActivities(FitbitApiClientAgent.java:203) at com.fitbit.api.client.FitbitApiClientAgent.getCollectionForDate(FitbitApiClientAgent.java:477) at com.fitbit.api.client.service.FitbitAPIClientService.getCollectionForDate(FitbitAPIClientService.java:134) at com.fitbit.api.client.service.FitbitAPIClientService.getActivities(FitbitAPIClientService.java:118)

This is the point at which I wish I had had source code access for the fitbit Java client but short of that, my guess was that the FitbitApiClientAgent (which the FitbitAPIClientService contained a reference to) wasn't being given the ResourceCredentials necessary to make the request, so I changed the initialization code so that the agent was directly made aware of the resource credentials for my user:


APIResourceCredentials creds = new APIResourceCredentials(userID, "", "");
creds.setAccessToken(oauth_token);
creds.setAccessTokenSecret(oauth_secret);
client.saveResourceCredentials(ud, creds); // <-- apparently wasn't getting through to the agent
agent.getCredentialsCache().saveResourceCredentials(ud, creds); // <-- key: had to do this
Activities o = client.getActivities(ud, new LocalDate());

which solved the problem. Next, since the end goal was saving a bunch of weight values of a period of a couple months, I thought it would be good to attempt to retrieve my weight:


double currentWeight = agent.getWeight(ud, new FitbitUser(userID), new LocalDate());

which worked... except my weight was coming back in kilograms. Apparently they default to using the metric system for any request that doesn't contain this:


agent.setRequestHeader("Accept-Language", "en_US");

except there's a bug with that where either the client isn't sending that header along or the server isn't honoring that header, details were available in the discussion forums. Really not that big of a deal though, relatively easy to convert between kilograms and pounds so finally...

6) Loop over the date / weight value pairs in the CSV file export, reading it line by line and set my weight for each date:


File file = new File(args[1]);
BufferedReader isr = new BufferedReader(new FileReader(file));
String line = "";
while ((line = isr.readLine()) != null) {
String[] parts = line.split(",");
String date = parts[0];
String weight = parts[1];
String[] dateParts = date.split("/");
LocalDate d = new LocalDate(Integer.parseInt(dateParts[2]),
Integer.parseInt(dateParts[0]),
Integer.parseInt(dateParts[1]));
Float newWeight = Float.parseFloat(weight) * new Float(0.45359237); // convert pounds to kilograms
agent.logWeight(ud, newWeight, d);
}

and everything worked just like it should.

Overall I'm been really please with the Fitbit: it's given me something to measure on a daily basis (easy) but it does it all in the background without me really having to do much at all (hard) and they've built a TON of functionality into the site (I'm using maybe 1/4 of the functionality). Being able to enter my weight has been great (easy to enter your weight via your mobile device in the morning after you weight yourself) and has replaced the Excel / Line Diet thing I was doing before. I already dropped it (the little Fitbit device that you clip to your pants / shirt) in the toilet once by accident (ha!) but it didn't skip a beat. The API has a couple wrinkles, mostly around the examples and documentation, which isn't all that surprising since it's brand new and currently listed as "beta". The specific things I'd want to see improved in / around the API:

  • get rid of the examples based on Stripes and concentrate more on the code necessary to 1) create a web application and 2) a mobile / desktop application especially as it relates to OAuth (since the workflow is different between each)
  • trim down the fitbit Java client: there are 89 classes in the jar, no JavaDoc (that I could find) on any of them, no source and very few examples outside of the Stripes web application which, as I mentioned above, didn't use the agent API at all
  • could go either way on this one but the requirement that you set a request header to determine which unit system you want to use seems like it might make more sense to be part of the API, ie: it would be clearer if the API simple forced you to declare which unit of measure of you wanted to use on the method, agent.logWeight(user, weight, date, "pounds"), but don't feel that strongly about that one.

and the only thing so far with the tracker that I'd like to see improved is the interface for starting / stopping sleep. I might have just run into the going to bed after midnight issue but it's not entirely obvious when I start / stop something.

Well worth the $99 if you're thinking about buying one.

14 thoughts on “Playing with the Fitbit API”

    1. Very cool… fitbit actually has a withings import feature… apparently there’s a withings wireless weight scale too.

      Recovery going well, I’ll upload pictures of the screws in my back to Brewspace when I get back. :)

  1. Hi, I ran into this blog while looking for some fitbit extraction methods. I’m trying to get step data in 1-min intervals (currently we can only get step data in 5-min intervals, and activity data in 1-min intervals if we set a sleep period). If you have any ideas or thoughts, we’d really appreciate it!

    1. What exactly do you need?
      Yesterday I sucessfully ran basic fitbit project and it shows User info to me.

      I also dveloped in Eclipse IDE.

  2. Hi! I am trying to get access to the data as well. What I need it is to create a desktop app (I dont need to create a web-service) for accesing to the activity data and keep it in my computer in a .CSV format which is very similar to that A. Johnson has done.

    Since I am not so familiar to Java, I am having a lot of problems with the FITBIT libraries. I don’t know how to make the whole thing work, so I would appreciate any kind of help. A complete coding with the A. J. program would be perfect, since it is exactly what I need.

    Thanks in advance!

  3. Hi!

    I’m also trying to set basic fitbit project and running in the IntelliJ Idea.
    I have this example servlet FitbitApiAuthExample servelet and in it: init and doGet method. However when I debug this it goes well through init method, but I don’t get in “doGet” method. What seems to be wrong?
    Do I have to make special request to “fire” doGet method?

    then my: fitbitApiAuthExample.jsp shows the labels without data.
    e.g.:

    Full Name:
    Display Name:

    ….

    Can you please help me?

  4. Ok, I started developing in Eclipse and it seems debugger can get access to doGet method … I also got access to Fitbit, it shows Welcome Fitbit page in browser, it wants to have an authorisation with my email and password.

    I’ll keep you posted.

  5. I’ve already solved the problem :)

    When you get oath andverifier tokens, you have to invoke fitbitApiAuthExampleServlet again and it will show User info ;)

    1. Hi, Thorusan, I am still working on the userInfo display, it shows the welcome page and then the authentication email and password, then the “http://your.application.host//fitbitApiAuthExample?completeAuthorization=&oauth_token=7301cee4957401eb9f3fb52ac7c3fa5d&oauth_verifier=fpu5sgvrmsu4fi5b05jhc246t5″ was get redirected, then the error shows “cannot find the server”…….
      Would you please help me with this problem, how to invoke the fitbitApiAuthExampleServlet again….thank you!

      1. If possible, can I have a look on your deployed Eclipse project, I am in urgent need to get the fitbit User Info and Sleep Info to build my processing data visualization project as my undergraduate final project, I tried this on my Eclipse j2ee, but I know limit knowledge about Java web,I used to programming in the Processing language, looking forward for your reply, thank you!!

  6. Nice article. I’m trying to set up an example fitbit application in Eclipse. I keep getting the following exception after a call to FitbitApiClientAgent():

    Exception in thread “main” java.lang.NoClassDefFoundError: org/json/JSONException
    at FitbitConsoleApplication.main(FitbitConsoleApplication.java:34)
    Caused by: java.lang.ClassNotFoundException: org.json.JSONException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    … 1 more

    I’m sure I don’t have something set up correctly. I am relatively new to Java.

    Does anyone have a base fitbit project for Eclipse I could use to ensure I have everything set up correctly?

    Thanks,

    Marty

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>