FitBit sleep tracking

I’ve been on the fence about replacing my broken FitBit for a couple years. What finally pushed me off that fence was the recent unlocking of intraday data for developers’ personal projects. This makes it possible for me to access my minute-by-minute activity and sleep data. What follows is a quick rundown of my initial foray into FitBit sleep tracking.

The first hurdle was getting at the data. I have a free FitBit account, which means the downloadable CSV files from fitbit.com will only include summary data (i.e., not minute-by-minute). There are a few ways to get around this, including:

  1. Bluetooth packet sniffing. This is pretty difficult and also violates FitBit terms of use.
  2. Fitbit.com website scraping. This is less difficult but still violates FitBit terms of use.
  3. Fitbit.com Application Programming Interface (API). Now that intraday data are available to developers, this is the easiest and also FitBit-friendliest method.

Many thanks to Paul Weeks for posting a walkthrough and the Python code that he used to access the API! I can’t get the refresh tokens to work quite right, so I have to manually reauthorize the API every half hour or so. (I’ll post the updated code to Github after I troubleshoot a bit more.)

One tricky thing about FitBit intraday sleep data is that it is categorical. So in any given minute, I’m either (1) not moving, (2) moving a little bit, or (3) moving a lot. The other tricky thing is that the default sensitivity settings don’t pick up small movements. This is okay for estimating the overall number minutes that I was asleep, but not so good for more precise measurement of restlessness. Sensitivity can be changed in the user settings (Devices menu >>> set Sleep Tracking to Sensitive), which provides a little more precision to FitBit’s chunky categorical data:

AnnotatedSideBySide

The downside is that my sleep quality now appears to be much worse on FitBit’s native web interface. Consequently, I had to lower my nightly sleep goal to ~4.5 hours so that I don’t get harassed for what appear to be poor sleep patterns. 2016-01-24_combinedThe upside is that I now have enough variation to make some use of the data. After a little munging in the Python code, I was able to smooth the chunky sleep data into something that provides a better sense of my oscillating sleep phases. Using the newly smoothed data, I can now map peaks and valleys and begin to predict the ideal time to wake up. With that information, I should be able to automate an adaptive wake-up alarm via the FitBit API. That way, my FitBit will vibrate when my body is ready to wake up, rather than waiting for a static alarm to stir me from a deep sleep.

Sleep quality is more complex than the data from my FitBit or other commercially available sleep monitors, and there are many other factors that impact sleep quality far more than when the morning alarm goes off. Still, it’s interesting to visualize my sleep patterns! As I log more data (from FitBit and elsewhere), I may even get a better sense of the factors that have the most impact my own sleep quality. Sweet dreams!

2 thoughts on “FitBit sleep tracking

  1. Steve02476

    I’m curious what the raw sleep data looks like that you receive using tha API. Can you show a few lines of it, as received from the server? It looks from your graph that motion is represented by a whole number that must be 1.0 or 2.0 or 3.0, did I understand that right? And the frequency is one reading per minute, is that right? Thanks very much.

    Reply
  2. Pete

    Hi Steve, in case this is still of interest to you, an example is pasted below. Values are integers, 1-3 from asleep to awake, one reading per minute.

    {‘value’: ‘1’, ‘dateTime’: ’01:24:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:25:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:26:00′}
    {‘value’: ‘2’, ‘dateTime’: ’01:27:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:28:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:29:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:30:00′}
    {‘value’: ‘2’, ‘dateTime’: ’01:31:00′}
    {‘value’: ‘2’, ‘dateTime’: ’01:32:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:33:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:34:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:35:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:36:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:37:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:38:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:39:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:40:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:41:00′}
    {‘value’: ‘3’, ‘dateTime’: ’01:42:00′}
    {‘value’: ‘2’, ‘dateTime’: ’01:43:00′}
    {‘value’: ‘2’, ‘dateTime’: ’01:44:00′}
    {‘value’: ‘1’, ‘dateTime’: ’01:45:00′}

    Reply

Leave a Reply

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