Garmin Connect - acquire data

For more than a year I’ve been using Garmin Smartwatch it collects lots of data some of them a pretty valuable for me. So I started to figure out how can I visualize them better than what Garmin offers, it’s not bad at all, but extensively using monitoring tools was a kind of temptation to work the same ;) After a quick research, I found GarminDB, a pretty nice tool to grab data, store them in SQLite and visualize in Jupyter Notebook. SQLite can be used as ie. a data source in Grafana, but I’m not a big fan of simulating time-series databases with SQL commands. So the workaround was to export the data from SQLite into let’s say… InfluxDB, because it supports importing data from CSV. When you grab all the data using GarminDB you can start exporting them to CSV:

$ cd ~/HealthData/DBs
$ sqlite3 garmin.db
SQLite version 3.36.0 2021-06-18 18:58:49
Enter ".help" for usage hints.
sqlite> .tables
_attributes       device_info_view  resting_hr        weight
attributes        devices           sleep
daily_summary     files             sleep_events
device_info       files_view        stress
sqlite> .headers on
sqlite> .mode csv
sqlite> .output rhr.csv
sqlite> select * from resting_hr order by day;
sqlite> .quit

than we can start working with the InfluxDB instance:

$ docker run -d -v $(pwd):/data -p 127.0.0.1:8086:8086 --name  influxdb influxdb
# do initial configuration via http://127.0.0.1:8086:
# create organization
# create bucket
# get admin the api token
$ docker exec -ti influxdb bash
root@babc99c1ab2c:/# export INFLUX_TOKEN=<your_token>
root@babc99c1ab2c:/# influx write -f /data/rhr.csv -o test -b garmin --header "#constant measurement,rhr" --header "#datatype dateTime:2006-01-02,double"

Now you’ve imported your resting heart rate into InfluxDB to garmin bucket. So we can start exploring data using Flux language. I’m pretty new with Flux, so I was surprised by the verbosity and how many functions it presents. The goal for me was the prepare the difference year-to-year in resting heart rate, to visualize the data you can use built-in explorer or use Grafana. I choose the second option with the final query for last 30 days:

current = from(bucket: "garmin")
  |> range(start: -30d)
  |> filter(fn: (r) => r["_measurement"] == "rhr")

past = from(bucket: "garmin")
  |> range(start: -395d, stop: -365d)
  |> filter(fn: (r) => r["_measurement"] == "rhr")
  |> timeShift(duration: 365d)

join(tables: {curr: current, past: past}, on: ["_time"])
    |> map(fn: (r) => ({_time: r._time, _value: r._value_curr - r._value_past}))

Effect:

garminconnect-rhr

Pretty nice alternative to visualize your health data, of course, there are a lot of opportunities to make importing much smoother.

comments powered by Disqus

powered by Hugo and Noteworthy theme