Fitbit dashboard setup

By Arpan Ghosh on Sep 22, 2022.

Reading time: 4 minutes.



How it looks like?


Heart rate data

Image_slide

Sleep data analytics

Image_slide

Hourly walking data visualization

Image_slide


Influxdb database setup


Influxdb is quite easy to set up using docker image. I used the following to launch a influxdb docker container in my machine.

Preconfigure

1
docker run --rm influxdb:1.8 influxd config > /home/arpan/docker-containers/influxdb/influxdb.conf

Docker-compose configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
version: '3.3'
services:
    influxdb:
        restart: unless-stopped
        container_name: influxdb
        ports:
            - '8086:8086'
        volumes:
            - '/home/arpan/docker-containers/influxdb:/var/lib/influxdb'
            - '/home/arpan/docker-containers/influxdb/influxdb.conf:/etc/influxdb/influxdb.conf'
        image: 'influxdb:1.8'

Now to get access of the shell within container, you should run the following command from your terminal.

1
docker exec -it influxdb /bin/bash

Run the influx command in the bash shell of the influxdb container and then follow the influxdb documentation to create a user ( in my case it was arpan ) and create a database named fitbit. Grant both read and write access on the database to the username.

Now your database is ready to use.


Fetching data


You need to get a API token from the fitbit dev tools. The detailed process of getting the Oauth token is given here

You also need to install influxdb, pandas, xmltodict and pytz modules using pip

This python script can help you to gather the data from your fitbit account.

You need to replace the ‘YOUR ACCESS TOKEN HERE’ part with your access token in line 14. You should also replace the ‘INFLUXDB_USERNAME_HERE’ and ‘INFLUXDB_PASSWORD_HERE’ with your influxdb username and password.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
import requests, sys, os, pytz, time
from datetime import datetime, date, timedelta
from influxdb import InfluxDBClient
from influxdb.exceptions import InfluxDBClientError
import pandas as pd
import datetime as DT
import xmltodict # for GPS xml analysis

LOCAL_TIMEZONE = pytz.timezone('Asia/Calcutta')
FITBIT_LANGUAGE = 'en_US'
FITBIT_CLIENT_ID = ''
FITBIT_CLIENT_SECRET = ''
FITBIT_ACCESS_TOKEN = 'YOUR ACCESS TOKEN HERE'
FITBIT_INITIAL_CODE = ''
REDIRECT_URI = 'http://localhost/8080'
INFLUXDB_HOST = 'localhost'
INFLUXDB_PORT = 8086
INFLUXDB_USERNAME = 'INFLUXDB_USERNAME_HERE'
INFLUXDB_PASSWORD = 'INFLUXDB_PASSWORD_HERE'
INFLUXDB_DATABASE = 'fitbit'
points = []

The following code in the end of the script helps in gathering all the data using the pre-defined functions in the code.

547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
fetch_data_spo2('spo2',same_date)
fetch_data_br('br',same_date)
fetch_data('activities', 'steps', same_date )
fetch_data('activities', 'distance', same_date)
fetch_data('activities', 'floors', same_date)
fetch_data('activities', 'elevation', same_date)
fetch_data('activities', 'distance', same_date)
fetch_data('activities', 'minutesSedentary', same_date)
fetch_data('activities', 'minutesLightlyActive', same_date)
fetch_data('activities', 'minutesFairlyActive', same_date)
fetch_data('activities', 'minutesVeryActive', same_date)
fetch_data('activities', 'calories', same_date)
fetch_data('activities', 'activityCalories', same_date)
fetch_data('body', 'weight', same_date)
fetch_data('body', 'fat', same_date)
fetch_data('body', 'bmi', same_date)
fetch_data('foods/log', 'water', same_date)
fetch_data('foods/log', 'caloriesIn', same_date)
fetch_heartrate(same_date)
fetch_hourly_steps(same_date)
fetch_activities(next_date)

Then we write the data to the fitbit database using the client.write_points(points) method

569
570
571
572
573
574
575
576
points.append({"measurement": "last_database_update", "time": LOCAL_TIMEZONE.localize(datetime.now()).astimezone(pytz.utc).isoformat(), "fields": {"value": 1}})

try:
    client.write_points(points)
except InfluxDBClientError as err:
    filehandle.write("\nUnable to write points to InfluxDB: %s \n" % (err))
    print("\nUnable to write points to InfluxDB: %s \n" % (err))
    sys.exit()

Grafana server setup


Grafana is very easy to set up using docker image. I used the following to launch a grafana docker container in my machine.

Run this command first to set 472 as the owner of the grafana folder ( currently empty )

1
2
3
sudo chown -R 472:472 /home/arpan/docker-containers/grafana

docker-compose up

Docker-compose configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
version: '3.3'
services:
    grafana:
        restart: unless-stopped
        volumes:
            - '/home/arpan/docker-containers/grafana:/var/lib/grafana'
        ports:
            - '3000:3000'
        container_name: grafana
        image: 'grafana/grafana:latest'

Then you can open localhost:3000 or your remote-server-ip:3000 to access the webserver.

set up the database source with the details of your fitbit database. Then create a new dashboard and use the following quaries to get the nice and cute plot of your HR.

1
SELECT moving_average(mean("value"), 6) FROM "heartrate" WHERE $timeFilter GROUP BY time($__interval) fill(null)

If you want to have the HR above 95 to be color coded as red ( as in the above pictures ) you need to use multiple quaries and plot them one over the other. There is the code to plot only the above 95 values as red.

1
select above from (SELECT moving_average(mean("value"), 6) as above FROM "heartrate" WHERE $timeFilter GROUP BY time($__interval) fill(null)) where above > 95

You can directly replicate the dashboard I am using with this dashboard json file. You just need to import the json to get the dashboard up and running.



Final result


With the help of this I was able to gather months of data and very useful insights.



Please consider sharing this page