diff --git a/README.md b/README.md
index 54bc16f..56fd665 100644
--- a/README.md
+++ b/README.md
@@ -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/youruser@example.com/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
@@ -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*
diff --git a/download.py b/download.py
index 190107d..44ee26b 100644
--- a/download.py
+++ b/download.py
@@ -29,14 +29,18 @@
SSO = "https://sso.garmin.com/sso"
CSS = "https://static.garmincdn.com/com.garmin.connect/ui/css/gauth-custom-v1.2-min.css"
REDIRECT = "https://connect.garmin.com/post-auth/login"
+
ACTIVITIES = "http://connect.garmin.com/proxy/activity-search-service-1.2/json/activities?start=%s&limit=%s"
WELLNESS = "https://connect.garmin.com/modern/proxy/userstats-service/wellness/daily/%s?fromDate=%s&untilDate=%s"
DAILYSUMMARY = "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailySummaryChart/%s?date=%s"
-
+STRESS = "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailyStress/%s"
+HEARTRATE = "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailyHeartRate/%s?date=%s"
+SLEEP = "https://connect.garmin.com/modern/proxy/wellness-service/wellness/dailySleep/user/%s?date=%s"
TCX = "https://connect.garmin.com/modern/proxy/download-service/export/tcx/activity/%s"
GPX = "https://connect.garmin.com/modern/proxy/download-service/export/gpx/activity/%s"
+
def login(agent, username, password):
global BASE_URL, GAUTH, REDIRECT, SSO, CSS
@@ -153,7 +157,7 @@ def wellness(agent, start_date, end_date, display_name, outdir):
try:
response = agent.open(url)
except:
- print('Wrong credentials for user {}. Skipping.'.format(username))
+ print('Wrong credentials for user {}. Skipping wellness for {}.'.format(username, start_date))
return
content = response.get_data()
@@ -168,7 +172,7 @@ def dailysummary(agent, date, display_name, outdir):
try:
response = agent.open(url)
except:
- print('Wrong credentials for user {}. Skipping.'.format(username))
+ print('Wrong credentials for user {}. Skipping daily summary for {}.'.format(username, date))
return
content = response.get_data()
@@ -178,6 +182,51 @@ def dailysummary(agent, date, display_name, outdir):
f.write(content)
+def dailystress(agent, date, outdir):
+ url = STRESS % (date)
+ try:
+ response = agent.open(url)
+ except:
+ print('Wrong credentials for user {}. Skipping daily stress for {}.'.format(username, date))
+ return
+ content = response.get_data()
+
+ file_name = '{}_stress.json'.format(date)
+ file_path = os.path.join(outdir, file_name)
+ with open(file_path, "w") as f:
+ f.write(content)
+
+
+def dailyheartrate(agent, date, display_name, outdir):
+ url = HEARTRATE % (display_name, date)
+ try:
+ response = agent.open(url)
+ except:
+ print('Wrong credentials for user {}. Skipping daily heart rate for {}.'.format(username, date))
+ return
+ content = response.get_data()
+
+ file_name = '{}_heartrate.json'.format(date)
+ file_path = os.path.join(outdir, file_name)
+ with open(file_path, "w") as f:
+ f.write(content)
+
+
+def dailysleep(agent, date, display_name, outdir):
+ url = SLEEP % (display_name, date)
+ try:
+ response = agent.open(url)
+ except:
+ print('Wrong credentials for user {}. Skipping daily sleep for {}.'.format(username, date))
+ return
+ content = response.get_data()
+
+ file_name = '{}_sleep.json'.format(date)
+ file_path = os.path.join(outdir, file_name)
+ with open(file_path, "w") as f:
+ f.write(content)
+
+
def login_user(username, password):
# Create the agent and log in.
agent = me.Browser()
@@ -208,8 +257,11 @@ def download_wellness_for_user(agent, username, start_date, end_date, display_na
# Scrape all wellness data.
wellness(agent, start_date, end_date, display_name, download_folder)
- # Daily summary does not do ranges, only fetch for `startdate`
+ # Daily summary, stress and heart rate do not do ranges, only fetch for `startdate`
dailysummary(agent, start_date, display_name, download_folder)
+ dailystress(agent, start_date, download_folder)
+ dailyheartrate(agent, start_date, display_name, download_folder)
+ dailysleep(agent, start_date, display_name, download_folder)
if __name__ == "__main__":
diff --git a/templates/wellness.html b/templates/wellness.html
new file mode 100644
index 0000000..8e03e20
--- /dev/null
+++ b/templates/wellness.html
@@ -0,0 +1,299 @@
+
+
+