Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visualisation #18

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ To download all your Garmin workouts in TCX format (basically XML), perform the

Again, you should see activities downloading in a few seconds.

To download wellness data (e.g., step count, calories burned, floors ascended and descended), use the download script as follows:

```
python download.py -c garmin_login.csv --start-date 2017-08-18 --end-date 2017-08-20 --displayname 1abcde23-f45a-678b-cdef-90123a45bcd
```

Start date and end date can be the same date to only download one day. Displayname is the part of the url if you go to Activities > Steps on Garmin Connect and look at the part: ../daily-summary/[displayname]/2017-08-20/steps

To visualise the downloaded wellness information, use `visualisation.py`, for example like:

```
python visualisation.py -i /home/youruser/garmin/Results/[email protected]/Wellness -o /home/youruser/www/garmin
```

This creates a file called wellness.html with graphs and statistics. Just open it with your browser, or upload it to your website.

If you run into any problems, please create a ticket!

Packages
Expand All @@ -48,3 +64,5 @@ If any of the following packages require dependencies, they will be listed. To i
- **download.py**: A script for downloading all Garmin Connect data as TCX files for offline parsing. *Dependencies: mechanize*

- **monthly.py**: A script for updating one's Twitter account with monthly statistics. Currently, the statistics and format are identical to those seen on [DailyMile](http://www.dailymile.com) for their weekly statistics. I just thought it'd be neat to have monthly updates, too. *Dependencies: tweepy, mechanize*

- **visualisation.py**: A script to generate graphs and statistics overviews from the Wellness data downloaded with download.py. *Dependencies: jinja2*
209 changes: 209 additions & 0 deletions templates/wellness.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
<!DOCTYPE html>
<html>
<head>
<title>Garmin Wellness</title>
<meta charset="utf-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<style>
body
{
background-color: #F2F2F2;
}
h1, h2, p, .contentblock
{
font-family: Verdana, sans-serif;
color: #141414;
}
h2
{
color: #AAA;
border-bottom: 1px solid #AAA;
clear: both;
}
i
{
width: 2em;
display: inline-block;
text-align: center;
}
ul
{
list-style: none;
}
.contentblock
{
width: 800px;
float: left;
padding: 5px;
margin-bottom: 10px;
margin-right: 10px;
/* background-color: #1f1d1d;
border: 1px solid #292929;*/
}
.contentblock h2
{
font-weight: normal;
}
.contentblock p
{
font-size: .75em;
margin: 0;
}
.contentblock td
{
background-color: #141414;
font-size: .6em;
color: #D8D9DA;
}
.warning
{
color: #F00;
}
.goal
{
color: #AAA;
}
</style>
</head>
<body>

<h1>Garmin Wellness</h1>

{% for datestamp, summary in summaries %}

<h2>{{ datestamp }}</h2>
<div class="contentblock">

<canvas id="{{ datestamp }}"></canvas>


<script>
var ctx = document.getElementById('{{ datestamp }}').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [
{% for datetime in summary['datetime'] %}
'{{ datetime }}',
{% endfor %}
],
datasets: [{
label: 'sleeping',
data: [
{% for steps in summary['sleeping_steps'] %}
'{{ steps }}',
{% endfor %}
],
backgroundColor: "rgba(0,0,153,0.9)"
}, {
label: 'sedentary',
data: [
{% for steps in summary['sedentary_steps'] %}
'{{ steps }}',
{% endfor %}
],
backgroundColor: "rgba(255,153,0,0.9)"
}, {
label: 'active',
data: [
{% for steps in summary['active_steps'] %}
'{{ steps }}',
{% endfor %}
],
backgroundColor: "rgba(255,255,0,0.9)"
}, {
label: 'highly active',
data: [
{% for steps in summary['highlyactive_steps'] %}
'{{ steps }}',
{% endfor %}
],
backgroundColor: "rgba(153,255,51,0.9)"
}, {
label: 'various',
data: [
{% for steps in summary['generic_steps'] %}
'{{ steps }}',
{% endfor %}
],
backgroundColor: "rgba(153,153,153,0.9)"
}, {
label: 'totalsteps',
data: [
{% for steps in summary['totalsteps'] %}
'{{ steps }}',
{% endfor %}
],
borderColor: "rgba(0,0,0,0.4)",
type: 'line'
}, {
label: 'step goal',
data: [
{% for steps in summary['totalsteps'] %}
'{{ wellness['total_step_goal'][datestamp] }}',
{% endfor %}
],
backgroundColor: "rgba(0,0,0,0.0)",
borderColor: "rgba(201, 203, 207,0.9)",
type: 'line'
},
/*
"backgroundColor": ["rgba(255, 99, 132, 0.2)", "rgba(255, 159, 64, 0.2)", "rgba(255, 205, 86, 0.2)", "rgba(75, 192, 192, 0.2)", "rgba(54, 162, 235, 0.2)", "rgba(153, 102, 255, 0.2)", "rgba(201, 203, 207, 0.2)"],
"borderColor": ["rgb(255, 99, 132)", "rgb(255, 159, 64)", "rgb(255, 205, 86)", "rgb(75, 192, 192)", "rgb(54, 162, 235)", "rgb(153, 102, 255)", "rgb(201, 203, 207)"],
"borderWidth": 1
*/
]
},
options: {
scales: {
xAxes: [{
type: 'time',
}]
},
layout: {
padding: {
left: 50,
right: 0,
top: 0,
bottom: 0
}
},
animation: {
duration: 0
}
}
});
</script>

</div>

<div class="contentblock">
<ul>
<li><span title="Steps taken"><i class="fi-foot" aria-hidden="true"></i> {{ wellness['total_steps'][datestamp] }}</span> <span class="goal" title="Steps goal">/ {{ wellness['total_step_goal'][datestamp] }}</span></li>
<li title="Total distance"><i class="fa fa-map" aria-hidden="true"></i> {{ wellness['total_distance'][datestamp] }}m</li>
<li><i class="fa fa-arrow-up" aria-hidden="true"></i> <span title="Floors ascended">{{ wellness['floors_ascended'][datestamp] }}</span> <span class="goal" title="Floors ascend goal">/ {{ wellness['user_floors_ascended_goal'][datestamp] }}</span> <i class="fa fa-arrow-down" aria-hidden="true"></i> <span title="Floors descended">{{ wellness['floors_descended'][datestamp] }}</span></li>
{% if wellness['vigorous_intensity_minutes'][datestamp] %}
<li><span title="Vigorous intensity"><i class="fa fa-forward" aria-hidden="true"></i> {{ wellness['vigorous_intensity_minutes'][datestamp] }} minutes</span></li>
{% endif %}
{% if wellness['moderate_intensity_minutes'][datestamp] %}
<li><span title="Moderate intensity"><i class="fa fa-play" aria-hidden="true"></i> {{ wellness['moderate_intensity_minutes'][datestamp] }} minutes</span></li>
{% endif %}
<li><i class="fa fa-bolt" aria-hidden="true"></i> <span title="Total Calories">{{ wellness['total_calories'][datestamp] }}</span> / <span title="Active Calories">{{ wellness['active_calories'][datestamp] }}</span> / <span title="BMR Calories">{{ wellness['bmr_calories'][datestamp] }}</span></li>
{% if wellness['max_heart_rate'] %}
<li><i class="fa fa-heartbeat" aria-hidden="true"></i>
<span title="Max heart rate">{{ wellness['max_heart_rate'][datestamp] }}</span> /
<span title="Min heart rate">{{ wellness['min_heart_rate'][datestamp] }}</span> /
<span title="Resting heart rate">{{ wellness['resting_heart_rate'][datestamp] }}</span>
</li>
{% endif %}
{% if wellness['sleep_duration'][datestamp] %}
<li title="Sleep duration"><i class="fa fa-bed" aria-hidden="true"></i> {{ (wellness['sleep_duration'][datestamp] / 3600) | round(1, 'common') }} hours</li>
{% endif %}
</ul>
</div>
{% endfor %}

</body>
</html>
Loading