This commit is contained in:
2024-10-14 00:11:55 +02:00
parent 9a4d4c549b
commit 4eaceb8b4d
37 changed files with 11551 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
2022-12-21 22:00:17,681 [INFO ] Starting gcexport.py version 4.0.0, using Python version 3.10.6
2022-12-21 22:00:17,681 [INFO ] New logfile level: INFO
2022-12-21 22:00:17,682 [WARNING] Output directory ./2022-12-21_garmin_connect_export already exists. Will skip already-downloaded files and append to the CSV file.

View File

@@ -0,0 +1,14 @@
# develop branch
The [master](https://github.com/pe-st/garmin-connect-export) branch;
it is the default branch. This is where my tinkering happens, and always contains the latest version of `gcexport.py`
Other notable branches in this repo:
- [develop](https://github.com/pe-st/garmin-connect-export/tree/develop)
Former develop branch of my repo, kept for for the time being for compatibility
for the existing clones of my repo out there somewhere
- [moderation](https://github.com/pe-st/garmin-connect-export/tree/moderation)
Copy of the master branch of **@moderation**'s repo, kept for reference and comparison purposes
- [revert-csv-to-kjkjava](https://github.com/pe-st/garmin-connect-export/tree/feature/revert-csv-to-kjkjava)
Backport of **@moderation**'s and my changes to the original repo, using the original CSV format ([PR 42](https://github.com/kjkjava/garmin-connect-export/pull/42))

View File

@@ -0,0 +1,249 @@
# Changelog for the Garmin Connect Exporter
This changelog is inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 4.0.0 - 2022-10-06
- added: new option `--logpath` (BREAKING change, you might need `--logpath=.` for the old behaviour)
([Pull Request #74](https://github.com/pe-st/garmin-connect-export/pull/74) by @cristian5th and @bxsx)
- removed: Python 2 leftovers
([Pull Request #73](https://github.com/pe-st/garmin-connect-export/pull/73) by @bxsx)
- added: configurations for flake8, pylint and black (including the needed improvements of the code for them)
- changed: Github Actions now execute also flake8, pylint and black tasks
## 3.3.0 - 2021-12-26
- added: support for time spent in HR zones (feature request)
([Issue #68](https://github.com/pe-st/garmin-connect-export/issues/68)
- fixed: adapt display name parsing because of change Garmin Connect behaviour
([Pull Request #69](https://github.com/pe-st/garmin-connect-export/pull/69) by @hannesweisbach)
- added: Github Action to execute the tests automatically
## 3.2.1 - 2021-08-15
- fixed: make the display name parsing work also for email addresses
([Issue #65](https://github.com/pe-st/garmin-connect-export/issues/65)
## 3.2.0 - 2021-07-18
- changed: [Python 2.x is not supported anymore](https://github.com/pe-st/garmin-connect-export/issues/64)
- changed: the `--verbose` option now also saves some intermediate responses from Garmin
- changed: Improve logging for HTTP connection requests
- fixed: handle the case where an original file has a different extension than `.fit`
([Pull Request #61](https://github.com/pe-st/garmin-connect-export/pull/61) by @cristian5th)
- fixed: don't write a record to the CSV file for already downloaded activities
([Issue #34](https://github.com/pe-st/garmin-connect-export/issues/34),
[Pull Request #62](https://github.com/pe-st/garmin-connect-export/pull/62) by @cristian5th)
## 3.1.0 - 2021-06-03
- added: export of the parts of multi-sport activities
- added: `--exclude` option to exclude activities from the download
([Pull Request #58](https://github.com/pe-st/garmin-connect-export/pull/58) by @chs8691)
## 3.0.3 - 2021-02-24
- fixed: `HTTP Error 402: Payment Required` (started appearing 2021-02-23)
([Pull Request #55](https://github.com/pe-st/garmin-connect-export/pull/55) by @reto)
- changed: [detached from kjkjava's repo](https://github.com/pe-st/garmin-connect-export/issues/53)
## 3.0.2 - 2020-11-15
- fixed: unzipped filename was changed by Garmin, breaking redownload check (issue #48)
## 3.0.1 - 2020-05-23
- fixed: `--subdir` was broken in 3.0.0 by the migration to Python 3 (reported by @jamorris, issue #37)
- changed: moved unit tests for `resolve_path` from **unittest** framework to **pytest**
## 3.0.0 - 2020-05-16
- added: support for Python 3, thanks to @telemaxx and @bartskowron
- added: file `CONTRIBUTING.md` and moved some parts of `README.md` into it
- changed: with Windows the script now uses backslashes as path separator
- changed: default Git branch is now `master` (the old `develop` branch is kept for the time being)
- fixed: `-fp` option for `original` format
## 2.3.3 - 2020-01-30
- fixed: skipping existing `.fit` files didn't work (reported by @fellrnr, issue #25)
## 2.3.2 - 2019-08-25
- added: parent activity type "Winter Sports"
## 2.3.1 - 2019-08-18
- added: new command line switch `--subdir` / `-s` (courtesy of Christian Schulzendorff @chs8691):
Exported activity files now can be saved in subdirectories, optionally grouped by year (and/or month) of the activity start time. Usually this is used together with the parameter `directory`, which is the root directory for DIR. `--subdir` supports the two placeholders `{YYYY}` and `{MM}` which can be used within DIR. Examples:
```
--directory downloads --subdir {YYYY} --> downloads/2019/
--directory downloads --subdir {YYYY}/{MM} --> downloads/2019/03/
--directory downloads --subdir myTcxFiles/{YYYY} -f tcx --> downloads/myTcxFiles/2019/
--directory downloads --subdir activities{YYYY}/GPX -f gpx --> downloads/activities2019/GPX/
```
Note that only the activity files go into the subdirectory, the CSV and other files remain in the main directory
- added: new command line switch `--start_activity_no` / `-sa` (courtesy of Josef K @jkall):
This is a minor fix to allow user to restart downloading where it crashed. Example:
First download:
```
$ python gcexport.py --count all ~/Downloads/garmin
Garmin Connect activity (657/2098) [activity_id] ...
...some error...
```
Second run:
```
$ python gcexport.py --count all --start_activity_no 657 ~/Downloads/garmin
...
Skipping Garmin Connect activity (656/2098) [activity_id]
Garmin Connect activity (657/2098) [activity_id]
```
## 2.3.0 - 2019-04-18
- changed: the HTTP request to login to Garmin Connect (the old one didn't work anymore)
## 2.2.1 - 2019-03-30
- added: new command line switch `--fileprefix` / `-fp` (courtesy of Christian Schulzendorff @chs8691):
A downloaded activity file can now have a date/time prefix, e.g. "20190301-065831-activity_3424910202.tcx". This works for all export types (tcx, gpx, json and original).
Existing downloaded files will not be touched. If downloaded twice, once with and once without the parameter, two files will be created.
## 2.2.0 - 2018-11-09
- added: new exported fields
- `vo2max` the VO2 Max (maximum volume of oxygen, cardiovascular fitness indicator)
- `aerobicEffect` aerobic training effect (value between 0 and 5)
- `anaerobicEffect` anaerobic training effect (value between 0 and 5)
- `averageRunCadence` average number of steps per minute. Excludes time spent standing
- `maxRunCadence` maximum number of steps per minute
- `strideLength` average length of the stride from one footfall to the next (in meters)
- `steps` number of steps
- `privacy` who can see your activity
- `fileFormat` the format of the original upload (fit, gpx or tcx)
- `locationName` location determined by Garmin
- `gear` the gear used (only tested for shoes); nickname if set, the brand/model otherwise
- `elevationCorrected` flag telling if the elevation correction is applied
- changed: new default CSV template with different CSV output;
to get the old CSV format use `-t csv_header_moderation.properties`
- added: Python version to the log file
- changed: improved exception logging
## 2.1.5 - 2018-09-24
- added: command line switches `-v` (verbosity) and `--desc` (description)
## 2.1.4 - 2018-09-21
- added: command line switches `-e` and `-a` to pass the CSV output to an external programm
(merged from @moderation's commit from 2018-09-09)
## 2.1.3 - 2018-09-17
- added: CHANGELOG.md file
- changed: improved detection if device information is unknown or missing
(i.e. they once were known, but the information got lost somehow)
- changed: the default CSV template (csv_header_default.properties) makes no difference
anymore between corrected and uncorrected elevation
- changed: the URL_GC_ACTIVITY_DETAIL endpoint isn't called anymore when the chosen
CSV template doesn't contain the `sampleCount` column
## 2.1.2 - 2018-09-11
- added: switch `-ot` to set file time to activity time (original
[Pull Request](https://github.com/kjkjava/garmin-connect-export/pull/8) by @tobiaslj)
## 2.1.1 - 2018-09-10
- added: Python module `logging` to write log files
- changed: console output is less verbose
- changed: remove most Pylint warning
## 2.1.0 - 2018-09-08
- added: CSV templates (csv_header_default.properties and csv_header_running.properties)
to make the CSV output configurable
## 2.0.3 - 2018-08-30
- changed: Fix regex for displayName to allow dots (original
[Pull Request](https://github.com/moderation/garmin-connect-export/pull/19) by @chmoelders)
## 2.0.2 - 2018-08-24
- changed: use the User Stats to discover the number of activities
(the old `activity-search-service-1.2` endpoint doesn't work anymore)
## 2.0.1 - 2018-06-15
- added: first unit tests
- changed: refactor into a Python module having a `main` function and using
the `if __name__ == "__main__":` incantation
- changed: fixed some Pylint issues
- changed: note about using the user name or email address for logging in
- changed: fixed user name prompt (reported by
[@TheKiteRunning](https://github.com/pe-st/garmin-connect-export/issues/6))
## 2.0.0 - 2018-04-17 - pe-st | branch develop
- changed: aligned with the current state of the **moderation** fork, but still using Python 2 for now
- changed: fixed distance and elapsedDuration parsing
([Pull Request](https://github.com/pe-st/garmin-connect-export/pull/3) by @lindback)
## 2018-04-06 - pe-st | branch develop
- changed: login ticket is now extracted from HTML response (the cookie doesn't contain the ticket anymore)
## 2018-03-10..2018-04-10 - pe-st | branch develop
- changed: various tunings to the CSV output
## 2018-03-10 - pe-st | branch develop
- added: using `activitylist-service` to get the list of activities
- changed: using **moderation**'s master as base using newer Garmin endpoints
(`activity-search-service-1.2`)
## 2017-06-14 - pe-st | branch develop
- added: JSON export format
([Pull Request](https://github.com/kjkjava/garmin-connect-export/pull/6) by @yohcop)
- changed: use newer endpoints for GPX/TCX downloads (`modern/.../download-service`)
([Pull Request](https://github.com/kjkjava/garmin-connect-export/pull/30) by @julienr)
- changed: don't abort for HTTP status 204 (empty GPX file)
## 2015-12-23 - kjkjava | branch master
- last commit in original repo of **kjkjava**
- using `activity-search-service-1.0` for the list and `activity-service-1.1` for GPX/TCX exports

View File

@@ -0,0 +1,86 @@
# Welcome!
If you are here, it means you are interested in helping this small project out.
A hearty welcome and thank you! There are many ways you can contribute:
- Offer PR's to fix bugs or implement new features.
- Give feedback and bug reports regarding the software or the documentation.
- Setting up an automated toolchain with mock endpoints for the HTTP calls for easier testing
- Improve our examples, tutorials, and documentation.
## Python Versions
### Python 2 vs 3
At the time of this writing (2021-07) Python 2 has long passed its [sunset](https://python3statement.org/).
And the effort to still support Python 2 has become too big (see https://github.com/pe-st/garmin-connect-export/issues/64);
the script now uses features from Python 3 which Python 2 doesn't understand,
so if you try to run the script with Python 2 you will get complaints about
invalid syntax or other similar error messages.
### Python 3.x Versions
The script should be usable for a wide range of users and Python versions.
For that reason the script should be compatible with the oldest still [supported
Python version](https://devguide.python.org/versions/). At the time of this writing
(July 2022) this is Python 3.7, whose end-of-life is currently scheduled for June 2023.
The Github Actions (see `github/workflows/python-app.yml`) thus run all steps twice,
once with the oldest supported Python version, and once with the newest released version.
## Getting started
### Pull requests
If you are new to GitHub [here](https://help.github.com/categories/collaborating-with-issues-and-pull-requests/)
is a detailed help source on getting involved with development on GitHub.
### Testing
There is a small set of unit test, using [pytest](https://docs.pytest.org/en/latest/);
these tests are executed automatically whenever a commit is pushed or when a pull request is updated.
I found that the free [PyCharm Community](https://www.jetbrains.com/pycharm/download/) is well suited for running the
tests.
Unfortunately there are no mocks yet for simulating Garmin Connect during development, so for real tests you'll have to
run the script against your own Garmin account.
## REST endpoints
As this script doesn't use the paid API, the endpoints to use are known by reverse engineering browser sessions. And as
the Garmin Connect website changes over time, chances are that this script gets broken.
Small history of the endpoints used by `gcexport.py` to get a list of activities:
- [activity-search-service-1.0](https://connect.garmin.com/proxy/activity-search-service-1.0/json/activities):
initial endpoint used since 2015, worked at least until January 2018
- [activity-search-service-1.2](https://connect.garmin.com/proxy/activity-search-service-1.2/json/activities):
endpoint introduced in `gcexport.py` in August 2016. In March 2018 this still works, but doesn't allow you to fetch
more than 20 activities, even split over multiple calls (when doing three consecutive calls with 1,19,19 as `limit`
parameter, the third one fails with HTTP error 500).
In August 2018 it stopped working altogether. The JSON returned by this endpoint however was quite rich
(see example `activity-search-service-1.2.json` in the `json` folder).
- [Profile page](https://connect.garmin.com/modern/profile) and
[User Stats page](https://connect.garmin.com/modern/proxy/userstats-service/statistics/user_name)
were introduced in August 2018 when activity-search-service-1.2 stopped working. Their purpose in this script is
solely to get the number of activities which I didn't find elsewhere.
- [activitylist-service](https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities):
endpoint introduced in `gcexport.py` in March 2018. The JSON returned by this endpoint is very different from the
activity-search-service-1.2 one (also here see the example in the `json` folder), e.g.
- it is concise and offers no redundant information (e.g. only speed, not speed and pace)
- the units are not explicitly given and must be deducted (e.g. the speed unit is m/s)
- there is less information, e.g. there is only one set of elevation values (not both corrected and uncorrected), and other values like minimum heart rate are missing.
- some other information is available only as an ID (e.g. `timeZoneId` or `deviceId`), and more complete information
is available by further REST calls (one for each activity and additional ones for device information)
Endpoints to get information about a specific activity:
- [activity-service](https://connect.garmin.com/modern/proxy/activity-service/activity/nnnn): A kind of summary of the activity, most values are present in their canonical format.
- [activity-service-1.3 details](https://connect.garmin.com/modern/proxy/activity-service-1.3/json/activityDetails/nnnn): A detailed list of measurements, with a list of the metrics available for each measurement.
### Limitations of Data Provided by Current Endpoints and Choices Made
- The timezones provided are just the names (e.g. for Central European Time CET you can get either "Europe/Paris" or "(GMT+01:00) Central European Time"), but not the exact offset. Note that the "GMT+01:00" part of the name is hardcoded, so in summer (daylight savings time) Garmin Connect still uses +01:00 in the name even if the offset then is +02:00. To get the offset you need to calculate the difference between the startTimeLocal and the startTimeGMT.

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Kyle Krafka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,207 @@
# garmin-connect-export script
:exclamation: | This script [now requires Python 3.7 or newer](https://github.com/pe-st/garmin-connect-export/issues/64)
---|---
:exclamation: | There is a [report of a deactivated user account that might by caused by using this script](https://github.com/pe-st/garmin-connect-export/issues/60). The exact reasons are not known, and my account has never been deactivated. But be aware that I can give no guarantee that Garmin tolerates requests made from this script. I believe though that this script is fair use (it doesn't do anything other than automating stuff that you do in the browser). But be careful if you plan to run the script as periodical task (with `cron` etc)
---|---
Download a copy of your Garmin Connect data, including stats and GPX tracks.
Note that Garmin introduced a while ago (around May 2018, for GDPR compatibility) a possibility to [download all of your Garmin Connect data](https://www.garmin.com/en-US/account/datamanagement/exportdata/) in one zip file. Depending on your needs this might be enough, but the script here offers additional features like getting GPX tracks instead of the original upload format or limiting the export to just a couple of activities.
## Forks and Branches
Before going into the details of this script itself, some meta information.
There exist many [forks](https://help.github.com/articles/fork-a-repo/) of this script repository:
- [pe-st](https://github.com/pe-st/garmin-connect-export)
This is my (**pe-st**) repository, the one you're looking at (or the source of the copy you're looking at).
It was [detached from **kjkjava**'s repo](https://github.com/pe-st/garmin-connect-export/issues/53)
(see below) in February 2021, after more than 5 years of inactivity of the upstream repo.
- [kjkjava](https://github.com/kjkjava/garmin-connect-export)
The original repo (mother repo) of my (**pe-st**) repo. It seems not maintained anymore (last commit in 2015, see also: [pr#42](https://github.com/kjkjava/garmin-connect-export/pull/42) and [issues#46](https://github.com/kjkjava/garmin-connect-export/issues/46))
- [moderation](https://github.com/moderation/garmin-connect-export)
After some inactivity of the **@kjkjava** repo, **@moderation** made some corrections in his own fork to have a working script again. His fork is primarily designed for his use which is cycling, while mine (**pe-st**) is running.
In March 2018 I integrated **@moderation**'s work into my own repo, so logically **@moderation** is now the
father repo of my repo. In April 2018 **@moderation** migrated his script to Python 3. Unfortunately
**@moderation**'s script [didn't work for me for a couple of months](https://github.com/moderation/garmin-connect-export/issues/11),
probably because of different Garmin Connect REST endpoints (URLs).
For the [branches](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging) in **pe-st**'s repo see [BRANCH.md](BRANCH.md)
## Description
This script will backup your personal Garmin Connect data. All downloaded data will go into a directory called `YYYY-MM-DD_garmin_connect_export/` in the current working directory. Activity records and details will go into a CSV file called `activities.csv`. GPX files (or whatever format you specify) containing track data, activity title, and activity descriptions are saved as well, using the Activity ID.
If there is no GPS track data (e.g., due to an indoor treadmill workout), a data file is still saved. If the GPX format is used, activity title and description data are saved. If the original format is used, Garmin may not provide a file at all and an empty file will be created. For activities where a GPX file was uploaded, Garmin may not have a TCX file available for download, so an empty file will be created. Since GPX is the only format Garmin should have for every activity, it is the default and preferred download format.
If you have many activities, you may find that this script crashes with an "Operation timed out" message. Just run the script again and it will pick up where it left off.
## Installation
- If you're comfortable using Git, just clone the repo from github
- Otherwise get the latest `zip` (or `tar.gz`) from the [releases page](https://github.com/pe-st/garmin-connect-export/releases)
and unpack it where it suits you.
## Usage
You will need a little experience running things from the command line to use this script. That said, here are the usage details from the `--help` flag:
```
usage: gcexport.py [-h] [--version] [-v] [--username USERNAME]
[--password PASSWORD] [-c COUNT] [-e EXTERNAL] [-a ARGS]
[-f {gpx,tcx,original,json}] [-d DIRECTORY] [-s SUBDIR]
[-lp LOGPATH] [-u] [-ot] [--desc [DESC]] [-t TEMPLATE]
[-fp] [-sa START_ACTIVITY_NO] [-ex FILE]
Garmin Connect Exporter
optional arguments:
-h, --help show this help message and exit
--version print version and exit
-v, --verbosity increase output and log verbosity, save more intermediate files
--username USERNAME your Garmin Connect username or email address (otherwise, you will be prompted)
--password PASSWORD your Garmin Connect password (otherwise, you will be prompted)
-c COUNT, --count COUNT
number of recent activities to download, or 'all' (default: 1)
-e EXTERNAL, --external EXTERNAL
path to external program to pass CSV file too
-a ARGS, --args ARGS additional arguments to pass to external program
-f {gpx,tcx,original,json}, --format {gpx,tcx,original,json}
export format; can be 'gpx', 'tcx', 'original' or 'json' (default: 'gpx')
-d DIRECTORY, --directory DIRECTORY
the directory to export to (default: './YYYY-MM-DD_garmin_connect_export')
-s SUBDIR, --subdir SUBDIR
the subdirectory for activity files (tcx, gpx etc.), supported placeholders are {YYYY} and {MM}
(default: export directory)
-lp LOGPATH, --logpath LOGPATH
the directory to store logfiles (default: same as for --directory)
-u, --unzip if downloading ZIP files (format: 'original'), unzip the file and remove the ZIP file
-ot, --originaltime will set downloaded (and possibly unzipped) file time to the activity start time
--desc [DESC] append the activity's description to the file name of the download; limit size if number is given
-t TEMPLATE, --template TEMPLATE
template file with desired columns for CSV output
-fp, --fileprefix set the local time as activity file name prefix
-sa START_ACTIVITY_NO, --start_activity_no START_ACTIVITY_NO
give index for first activity to import, i.e. skipping the newest activities
-ex FILE, --exclude FILE
JSON file with Array of activity IDs to exclude from download.
Format example: {"ids": ["6176888711"]}
```
### Examples
- `python gcexport.py --count all`
will download all of your data to a dated directory.
- `python gcexport.py -c all -f gpx -ot --desc 20`
will export all of your data in GPX format, set the timestamp of the GPX files to the start time of the activity and append the 20 first characters of the activity's description to the file name.
- `python gcexport.py -c all -e /Applications/LibreOffice.app/Contents/MacOS/soffice -a calc`
will download all of your data and then use LibreOffice to open the CSV file with the list of your activities (the path to LibreOffice is platform-specific; the example is for macOS).
- `python gcexport.py -d ~/MyActivities -c 3 -f original -u --username bobbyjoe --password bestpasswordever1`
will download your three most recent activities in the FIT file format (or whatever they were uploaded as) into the `~/MyActivities` directory (unless they already exist). Using the `--password` flags is not recommended because your password will be stored in your command line history. Instead, omit it to be prompted (and note that nothing will be displayed when you type your password). Equally you might not want to have the username stored in your command line history; in this case avoid also to give the `--username` option, and you'll be prompted for it. Note also that depending on the age of your garmin account your username is the email address (I myself still can login both with username and email address, but I've had a report that for some users the email address is mandatory to login).
Alternatively, you may run it with `./gcexport.py` if you set the file as executable (i.e., `chmod u+x gcexport.py`).
### Notes on the Usage
- The `-c COUNT` option might appear to count wrongly when exporting multi-sport activities;
they count as one activity, but the incrementing counter displayed on the console counts
also the individual parts of a multi-sport activity
### Python
Of course, you must have Python installed to run this, any recent 3.x version should work
(see also [Python 3.x Versions](./CONTRIBUTING.md#python-3x-versions)).
Most Mac and Linux users should already have Python.
Note that if you run into the [TLSV1 ALERT problem](https://github.com/pe-st/garmin-connect-export/issues/16)
or the [HTTP 403 Authentication Error](https://github.com/pe-st/garmin-connect-export/issues/59),
your Python installation might not be recent enough).
In this case you can install a more recent Python on your Mac using [Homebrew](https://docs.brew.sh/Homebrew-and-Python)
and/or [pyenv](https://github.com/pyenv/pyenv).
Also, as stated above, you should have some basic command line experience.
## Data
This tool is not guaranteed to get all of your data, or even download it correctly. I have only tested it with my account and it works fine, but different account settings or different data types could potentially cause problems. Also, because this is not an official feature of Garmin Connect, Garmin may very well make changes that break this utility (and they certainly have since I created this project).
If you want to see all of the raw data that Garmin hands to this script, just choose the JSON export format (`-f json`); in this case only metadata is exported, no track data.
The format of the CSV export file can be customized with template files (in Properties format, see the `--template` option); three examples are included:
- `csv_header_default.properties` (the default) gives you my preferred selection of columns, mainly targeted at running and hiking
- `csv_header_all.properties` gives you all available columns, handy as starting point for your own selection
- `csv_header_moderation.properties` gives you the same output as **@moderation**'s fork, mainly targeted at cycling
- `csv_header_kjkjava.properties` gives you an output similar as **@kjkjava**'s original script, mainly targeted at running
You can easily create a template file for your needs, just copy one of the examples and change the appearing columns, their order and/or their title.
Some important columns explained:
- `raw` (e.g. `durationRaw`) columns usually give you unformatted data as provided by the Garmin API, other columns (e.g. `duration`) often format the data more readable
- speed columns (e.g. `averageSpeedRaw` and `averageSpeedPace`): when there is `Pace` in the column name the value given is a speed (km/) or pace (minutes per kilometer) depending on the activity type (e.g. pace for running, hiking and walking activities, speed for other activities)
- The elevation is either uncorrected or corrected, with a flag telling which. The current API doesn't provide both sets of elevations
## Garmin Connect API
This script is for personal use only. It simulates a standard user session (i.e., in the browser), logging in using cookies and an authorization ticket. This makes the script pretty brittle. If you're looking for a more reliable option, particularly if you wish to use this for some production service, Garmin does offer a paid API service.
More information about the API endpoints used in the script is available in [CONTRIBUTING.md](CONTRIBUTING.md)
## History
The original project was written in PHP (formerly in the `old` directory, now deleted), based on "Garmin Connect export to Dailymile" code at <http://www.ciscomonkey.net/gc-to-dm-export/> (link has been down for a while). It no longer works due to the way Garmin handles logins. It could be updated, but I (**kjkjava**) decided to rewrite everything in Python for the latest version.
After 2015, when the original repo stopped being maintained, several forks from **kjkjava** started appearing (see
Forks and Branches section above).
In 2021 this fork was [detached from the original repo](https://github.com/pe-st/garmin-connect-export/issues/53);
in what concerns Github, the repo isn't a fork anymore, but a new "original".
For the history of this fork see the [CHANGELOG](CHANGELOG.md)
## Contributions
Contributions are welcome, see [CONTRIBUTING.md](CONTRIBUTING.md)
Contributors as of 2021-12 (Hope I didn't forget anyone,
see also [Contributors](https://github.com/pe-st/garmin-connect-export/graphs/contributors)):
- Kyle Krafka @kjkjava
- Jochem Wichers Hoeth @jowiho
- Andreas Loeffler @lefty01
- @sclub
- Yohann Coppel @yohcop
- Tobias Ljunggren @tobiaslj
- @cdstrachan
- Michael Payne @moderation
- Chris McCarty @cmccarty
- Julien Rebetez @julienr
- Peter Steiner @pe-st
- @lindback
- @TheKiteRunning
- Jens Diemer @jedie
- Christian Moelders @chmoelders
- Christian Schulzendorff @chs8691
- Josef K @jkall
- Thomas Th @telemaxx
- Bart Skowron @bxsx
- @reto
- Cristian @cristian5th
- @hannesweisbach
## License
[MIT](https://github.com/pe-st/garmin-connect-export/blob/master/LICENSE) &copy; 2015 Kyle Krafka and contributors
## Thank You
Thanks for using this script and I hope you find it as useful as I do! :smile:

View File

@@ -0,0 +1,92 @@
# column template with all known columns
id=Activity ID
url=Activity URL
activityName=Activity Name
description=Description
startTimeIso=Start Time
startTime1123=Begin Timestamp
startTimeMillis=Begin Timestamp (ms)
startTimeRaw=Begin Timestamp (raw)
endTimeIso=End Time
endTime1123=End Timestamp
endTimeMillis=End Timestamp (ms)
locationName=Location Name
durationRaw=Duration (raw)
duration=Duration (h:m:s)
elapsedDurationRaw=Elapsed Duration (raw)
elapsedDuration=Elapsed Duration (h:m:s)
movingDurationRaw=Moving Duration (raw)
movingDuration=Moving Duration (h:m:s)
distanceRaw=Distance (km)
averageSpeedRaw=Average Speed (km/h)
averageSpeedPaceRaw=Average Speed or Pace (raw)
averageSpeedPace=Average Speed (km/h or min/km)
averageMovingSpeedRaw=Average Moving Speed (km/h)
averageMovingSpeedPaceRaw=Average Moving Speed or Pace (raw)
averageMovingSpeedPace=Average Moving Speed (km/h or min/km)
maxSpeedRaw=Max. Speed (km/h)
maxSpeedPaceRaw=Max. Speed or Pace (raw)
maxSpeedPace=Max. Speed (km/h or min/km)
elevationGain=Elevation Gain (m)
elevationGainUncorr=Elevation Gain (m, uncorr)
elevationGainCorr=Elevation Gain (m, corrected)
elevationLoss=Elevation Loss (m)
elevationLossUncorr=Elevation Loss (m, uncorr)
elevationLossCorr=Elevation Loss (m, corrected)
minElevation=Elevation Min. (m)
minElevationUncorr=Elevation Min. (m, uncorr)
minElevationCorr=Elevation Min. (m, corrected)
minElevation=Elevation Min. (m)
minElevationUncorr=Elevation Min. (m, uncorr)
maxElevationCorr=Elevation Max. (m, corrected)
elevationCorrected=Elevation Corrected
maxHRRaw=Max. Heart Rate (raw)
maxHR=Max. Heart Rate (bpm)
averageHRRaw=Average Heart Rate (raw)
averageHR=Average Heart Rate (bpm)
caloriesRaw=Calories (raw)
calories=Calories
vo2max=VO2max
aerobicEffect=Aerobic Training Effect
anaerobicEffect=Anaerobic Training Effect
hrZone1Low=Low Boundary HR Zone 1
hrZone1Seconds=Seconds in HR Zone 1
hrZone2Low=Low Boundary HR Zone 2
hrZone2Seconds=Seconds in HR Zone 2
hrZone3Low=Low Boundary HR Zone 3
hrZone3Seconds=Seconds in HR Zone 3
hrZone4Low=Low Boundary HR Zone 4
hrZone4Seconds=Seconds in HR Zone 4
hrZone5Low=Low Boundary HR Zone 5
hrZone5Seconds=Seconds in HR Zone 5
averageRunCadence=Avg. Run Cadence
maxRunCadence=Max. Run Cadence
strideLength=Stride Length
steps=Steps
averageCadence=Avg. Cadence (rpm)
maxCadence=Max. Cadence (rpm)
strokes=Strokes
averageTemperature=Avg. Temp (°C)
minTemperature=Min. Temp (°C)
maxTemperature=Max. Temp (°C)
device=Device
gear=Gear
activityTypeKey=Activity Type Key
activityType=Activity Type
activityParent=Activity Parent
eventTypeKey=Event Type Key
eventType=Event Type
privacy=Privacy
fileFormat=File Format
tz=Time Zone
tzOffset=Offset
locationName=Location Name
startLatitudeRaw=Begin Latitude (raw)
startLatitude=Begin Latitude (°DD)
startLongitudeRaw=Begin Longitude (raw)
startLongitude=Begin Longitude (°DD)
endLatitudeRaw=End Latitude (raw)
endLatitude=End Latitude (°DD)
endLongitudeRaw=End Longitude (raw)
endLongitude=End Longitude (°DD)
sampleCount=Sample count

View File

@@ -0,0 +1,51 @@
# default column template trying to fit multiple sports
startTimeIso=Start Time
endTimeIso=End Time
id=Activity ID
activityName=Activity Name
description=Description
locationName=Location Name
tz=Time Zone
tzOffset=Offset
duration=Duration (h:m:s)
elapsedDuration=Elapsed Duration (h:m:s)
movingDuration=Moving Duration (h:m:s)
activityParent=Activity Parent
activityType=Activity Type
eventType=Event Type
device=Device
gear=Gear
privacy=Privacy
fileFormat=File Format
distanceRaw=Distance (km)
averageSpeedRaw=Average Speed (km/h)
averageSpeedPace=Average Speed (km/h or min/km)
averageMovingSpeedRaw=Average Moving Speed (km/h)
averageMovingSpeedPace=Average Moving Speed (km/h or min/km)
maxSpeedRaw=Max. Speed (km/h)
maxSpeedPace=Max. Speed (km/h or min/km)
elevationGain=Elevation Gain (m)
elevationLoss=Elevation Loss (m)
minElevation=Elevation Min. (m)
maxElevation=Elevation Max. (m)
elevationCorrected=Elevation Corrected
startLatitude=Begin Latitude (°DD)
startLongitude=Begin Longitude (°DD)
endLatitude=End Latitude (°DD)
endLongitude=End Longitude (°DD)
maxHR=Max. Heart Rate (bpm)
averageHR=Average Heart Rate (bpm)
calories=Calories
vo2max=VO2max
aerobicEffect=Aerobic Training Effect
anaerobicEffect=Anaerobic Training Effect
averageRunCadence=Avg. Run Cadence
maxRunCadence=Max. Run Cadence
strideLength=Stride Length
steps=Steps
averageCadence=Avg. Cadence (rpm)
maxCadence=Max. Cadence (rpm)
strokes=Strokes
averageTemperature=Avg. Temp (°C)
minTemperature=Min. Temp (°C)
maxTemperature=Max. Temp (°C)

View File

@@ -0,0 +1,42 @@
# column template mostly for running, matching the (old) output from https://github.com/kjkjava/garmin-connect-export
id=Activity ID
activityName=Activity Name
description=Description
startTime1123=Begin Timestamp
startTimeMillis=Begin Timestamp (ms)
endTime1123=End Timestamp
endTimeMillis=End Timestamp (ms)
device=Device
activityParent=Activity Parent
activityType=Activity Type
eventType=Event Type
tzOffset=Time Zone
maxElevationUnit=Max. Elevation (m)
maxElevation=Max. Elevation (Raw)
startLatitude=Begin latitude (°DD)
startLongitude=Begin longitude (°DD)
endLatitude=End latitude (°DD)
endLongitude=End longitude (°DD)
averageMovingSpeedPace=Average moving speed (km/h or min/km)
averageMovingSpeedPaceRaw=Average moving speed (Raw)
maxHR=Max. Heart Rate (bpm)
averageHR=Average Heart Rate (bpm)
maxSpeedPace=Max. speed (km/h or min/km)
maxSpeedPaceRaw=Max. speed (Raw)
calories=Calories
caloriesRaw=Calories (Raw)
elapsedDuration=Duration (h:m:s)
elapsedDurationRaw=Duration (Raw Seconds)
movingDuration=Moving Duration (h:m:s)
movingDurationRaw=Moving Duration (Raw Seconds)
averageSpeedPace=Average Speed (km/h or min/km)
averageSpeedPaceRaw=Average Speed (Raw)
distance=Distance (km)
distanceRaw=Distance (Raw)
minHR=Min. Heart Rate (bpm)
minElevationUnit=Min. Elevation (m)
minElevation=Min. Elevation (Raw)
elevationGainUnit=Elevation Gain (m)
elevationGain=Elevation Gain (Raw)
elevationLossUnit=Elevation Loss (m)
elevationLoss=Elevation Loss (Raw)

View File

@@ -0,0 +1,43 @@
# column template mostly for cycling, matching the output from https://github.com/moderation/garmin-connect-export
activityName=Activity name
description=Description
startTimeRaw=Begin timestamp
elapsedDuration=Duration (h:m:s)
movingDuration=Moving duration (h:m:s)
distanceRaw=Distance (km)
averageSpeedRaw=Average speed (km/h)
averageMovingSpeedRaw=Average moving speed (km/h)
maxSpeedRaw=Max. speed (km/h)
elevationLoss=Elevation loss uncorrected (m)
elevationGain=Elevation gain uncorrected (m)
minElevation=Elevation min. uncorrected (m)
maxElevation=Elevation max. uncorrected (m)
minHRRaw=Min. heart rate (bpm)
maxHRRaw=Max. heart rate (bpm)
averageHRRaw=Average heart rate (bpm)
caloriesRaw=Calories
averageCadence=Avg. cadence (rpm)
maxCadence=Max. cadence (rpm)
strokes=Strokes
averageTemperature=Avg. temp (°C)
minTemperature=Min. temp (°C)
maxTemperature=Max. temp (°C)
url=Map
# the following 3 columns are currently always empty
endTimeRaw=End timestamp
emptyStartTime=Begin timestamp (ms)
emptyEndTime=End timestamp (ms)
device=Device
activityTypeKey=Activity type
eventTypeKey=Event type
tz=Time zone
startLatitudeRaw=Begin latitude (°DD)
startLongitudeRaw=Begin longitude (°DD)
endLatitudeRaw=End latitude (°DD)
endLongitudeRaw=End longitude (°DD)
# the following 4 columns are currently always empty
emptyElevationGainCorr=Elevation gain corrected (m)
emptyElevationLossCorr=Elevation loss corrected (m)
emptyMaxElevationCorr=Elevation max. corrected (m)
emptyMinElevationCorr=Elevation min. corrected (m)
sampleCount=Sample count

View File

@@ -0,0 +1,77 @@
"""
Helper functions for filtering the list of activities to download.
"""
import json
import logging
import os
DOWNLOADED_IDS_FILE_NAME = "downloaded_ids.json"
KEY_IDS = "ids"
def read_exclude(file):
"""
Returns list with ids from json file. Errors will be printed
:param file: String with file path to exclude
:return: List with IDs or, if file not found, None.
"""
if not os.path.exists(file):
print("File not found:", file)
return None
if not os.path.isfile(file):
print("Not a file:", file)
return None
with open(file, 'r', encoding='utf-8') as json_file:
try:
obj = json.load(json_file)
return obj['ids']
except json.JSONDecodeError:
print("No valid json in:", file)
return None
def update_download_stats(activity_id, directory):
"""
Add item to download_stats file, if not already there. Call this for every successful downloaded activity.
The statistic is independent of the downloaded file type.
:param activity_id: String with activity ID
:param directory: Download root directory
"""
file = os.path.join(directory, DOWNLOADED_IDS_FILE_NAME)
# Very first time: touch the file
if not os.path.exists(file):
with open(file, 'w', encoding='utf-8') as read_obj:
read_obj.write(json.dumps(""))
# read file
with open(file, 'r', encoding='utf-8') as read_obj:
data = read_obj.read()
try:
obj = json.loads(data)
except json.JSONDecodeError:
obj = ""
# Sanitize wrong formats
obj = dict(obj)
if KEY_IDS not in obj:
obj[KEY_IDS] = []
if activity_id in obj[KEY_IDS]:
logging.info("%s already in %s", activity_id, file)
return
obj[KEY_IDS].append(activity_id)
obj[KEY_IDS].sort()
with open(file, 'w', encoding='utf-8') as write_obj:
write_obj.write(json.dumps(obj))

View File

@@ -0,0 +1,120 @@
# Standard library imports
import json
import tempfile
import unittest
from os import path
from os import remove
# Local application/library specific imports
import filtering
from filtering import DOWNLOADED_IDS_FILE_NAME
from filtering import KEY_IDS
DIR = tempfile.gettempdir()
class TestExcludeFile(unittest.TestCase):
@property
def file_under_test(self):
return path.join(DIR, "exclude.json")
@property
def non_existing_file(self):
return path.join(DIR, "non_existing_exclude.json")
@property
def dir(self):
return DIR
def setUp(self):
if path.exists(self.file_under_test):
remove(self.file_under_test)
if path.exists(self.non_existing_file):
remove(self.non_existing_file)
def test_read_exclude(self):
self.assertIsNone(filtering.read_exclude(self.non_existing_file))
with open(self.file_under_test, 'w') as f:
json.dump(dict(ids=["1001", "1002", "1010", "1003"]), f)
ids = filtering.read_exclude(self.file_under_test)
self.assertEqual(len(ids), 4)
self.assertIn("1001", ids)
self.assertIn("1002", ids)
self.assertIn("1003", ids)
self.assertIn("1010", ids)
class TestDownloadStats(unittest.TestCase):
@property
def file_under_test(self):
return path.join(DIR, DOWNLOADED_IDS_FILE_NAME)
@property
def dir(self):
return DIR
def setUp(self):
if path.exists(self.file_under_test):
remove(self.file_under_test)
def test_new_file(self):
filtering.update_download_stats('1000', self.dir)
with open(self.file_under_test, 'r') as actual_file:
actual = json.load(actual_file)
self.assertEqual(actual[KEY_IDS][0], '1000')
def test_1000_items(self):
r = range(1, 1000)
for i in r:
filtering.update_download_stats(str(i), self.dir)
with open(self.file_under_test, 'r') as actual_file:
actual = json.load(actual_file)
self.assertEqual(len(actual[KEY_IDS]), len(r))
def test_new_item(self):
filtering.update_download_stats('1000', self.dir)
filtering.update_download_stats('1010', self.dir)
with open(self.file_under_test, 'r') as actual_file:
actual = json.load(actual_file)
self.assertEqual(actual[KEY_IDS][0], '1000')
self.assertEqual(actual[KEY_IDS][1], '1010')
def test_corrupted_file(self):
with open(self.file_under_test, 'w') as corrupted_file:
corrupted_file.write("HUGO")
filtering.update_download_stats('1000', self.dir)
with open(self.file_under_test, 'r') as actual_file:
actual = json.load(actual_file)
self.assertEqual(actual[KEY_IDS][0], '1000')
def test_sort(self):
filtering.update_download_stats('1010', self.dir)
filtering.update_download_stats('1000', self.dir)
filtering.update_download_stats('1005', self.dir)
with open(self.file_under_test, 'r') as actual_file:
actual = json.load(actual_file)
self.assertEqual(actual[KEY_IDS][0], '1000')
self.assertEqual(actual[KEY_IDS][1], '1005')
self.assertEqual(actual[KEY_IDS][2], '1010')
if __name__ == '__main__':
unittest.main()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,248 @@
# -*- coding: utf-8 -*-
"""
Tests for gcexport.py; Call them with this command line:
py.test gcexport_test.py
"""
from gcexport import *
from io import StringIO
def test_pace_or_speed_raw_cycling():
# 10 m/s is 36 km/h
assert pace_or_speed_raw(2, 4, 10.0) == 36.0
def test_pace_or_speed_raw_running():
# 3.33 m/s is 12 km/h is 5 min/km
assert pace_or_speed_raw(1, 4, 10.0 / 3) == 5.0
def test_pace_or_speed_formatted_cycling():
# 10 m/s is 36 km/h
assert pace_or_speed_formatted(2, 4, 10.0) == '36.0'
def test_pace_or_speed_formatted_running():
# 3.33 m/s is 12 km/h is 5 min/km
assert pace_or_speed_formatted(1, 4, 10.0 / 3) == '05:00'
def test_trunc6_more():
assert trunc6(0.123456789) == '0.123456'
def test_trunc6_less():
assert trunc6(0.123) == '0.123000'
def test_offset_date_time():
assert offset_date_time("2018-03-08 12:23:22", "2018-03-08 11:23:22") == datetime(
2018, 3, 8, 12, 23, 22, 0, FixedOffset(60, "LCL")
)
assert offset_date_time("2018-03-08 12:23:22", "2018-03-08 12:23:22") == datetime(
2018, 3, 8, 12, 23, 22, 0, FixedOffset(0, "LCL")
)
def test_datetime_from_iso():
assert datetime_from_iso("2018-03-08 12:23:22") == datetime(2018, 3, 8, 12, 23, 22, 0)
assert datetime_from_iso("2018-03-08 12:23:22.0") == datetime(2018, 3, 8, 12, 23, 22, 0)
assert datetime_from_iso("2018-03-08T12:23:22") == datetime(2018, 3, 8, 12, 23, 22, 0)
assert datetime_from_iso("2018-03-08T12:23:22.0") == datetime(2018, 3, 8, 12, 23, 22, 0)
def test_epoch_seconds_from_summary():
# activity with a beginTimestamp
with open('json/activity_2541953812_overview.json') as json_timestamp:
summary = json.load(json_timestamp)
assert summary['beginTimestamp'] == 1520508202000
assert epoch_seconds_from_summary(summary) == 1520508202
# activity with a startTimeLocal without fractions
with open('json/activity_multisport_overview.json') as json_timestamp:
summary = json.load(json_timestamp)
assert summary['beginTimestamp'] == None
assert summary['startTimeLocal'] == '2021-04-11 11:50:49'
assert epoch_seconds_from_summary(summary) == 1618134649
# activity with a startTimeLocal with fractions
summary['startTimeLocal'] = '2021-04-11 11:50:50.3'
assert epoch_seconds_from_summary(summary) == 1618134650
def test_hhmmss_from_seconds():
# check/document that no rounding happens in hhmmss_from_seconds and the caller must round itself:
# 2969.6 s are 49 minutes and 29.6 seconds
assert hhmmss_from_seconds(2969.6) == "00:49:29"
assert hhmmss_from_seconds(round(2969.6)) == "00:49:30"
def test_sanitize_filename():
assert 'all_ascii' == sanitize_filename(u'all_ascii')
assert 'deja_funf' == sanitize_filename(u'déjà fünf')
assert 'deja_' == sanitize_filename(u'déjà fünf', 5)
assert '' == sanitize_filename(u'')
assert '' == sanitize_filename(None)
with open('json/activity_emoji.json') as json_data:
details = json.load(json_data)
assert 'Biel__Pavillon' == sanitize_filename(details['activityName'])
def test_load_properties_keys():
with open('csv_header_default.properties', 'r') as prop:
csv_header_props = prop.read()
csv_columns = []
csv_headers = load_properties(csv_header_props, keys=csv_columns)
assert csv_columns[0] == 'startTimeIso'
assert csv_headers['startTimeIso'] == "Start Time"
def test_csv_write_record():
with open('json/activitylist-service.json') as json_data_1:
activities = json.load(json_data_1)
with open('json/activity_emoji.json') as json_data_2:
details = json.load(json_data_2)
with open('json/activity_types.properties', 'r') as prop_1:
activity_type_props = prop_1.read()
activity_type_name = load_properties(activity_type_props)
with open('json/event_types.properties', 'r') as prop_2:
event_type_props = prop_2.read()
event_type_name = load_properties(event_type_props)
extract = {}
extract['start_time_with_offset'] = offset_date_time("2018-03-08 12:23:22", "2018-03-08 11:23:22")
extract['end_time_with_offset'] = offset_date_time("2018-03-08 12:23:22", "2018-03-08 12:23:22")
extract['elapsed_duration'] = 42.43
extract['elapsed_seconds'] = 42
extract['samples'] = None
extract['device'] = "some device"
extract['gear'] = "some gear"
extract['hrZones'] = HR_ZONES_EMPTY
extract['hrZones'][1] = json.loads('{ "secsInZone": 1689.269, "zoneLowBoundary": 138 }')
csv_file = StringIO()
csv_filter = CsvFilter(csv_file, 'csv_header_all.properties')
csv_write_record(csv_filter, extract, activities[0], details, activity_type_name, event_type_name)
expected = '"Biel 🏛 Pavillon"'
assert csv_file.getvalue()[69 : 69 + len(expected)] == expected
def write_to_file_mock(filename, content, mode, file_time=None):
pass
def http_req_mock_device(url, post=None, headers=None):
with open('json/device_856399.json') as json_device:
return json_device.read()
def test_extract_device():
args = parse_arguments([])
with open('json/activity_2541953812.json') as json_detail:
details = json.load(json_detail)
assert u'fēnix 5 10.0.0.0' == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
with open('json/activity_154105348_gpx_device_null.json') as json_detail:
details = json.load(json_detail)
assert None == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
with open('json/activity_995784118_gpx_device_0.json') as json_detail:
details = json.load(json_detail)
assert None == extract_device({}, details, None, args, http_req_mock_device, write_to_file_mock)
def http_req_mock_zones(url, post=None, headers=None):
with open('json/activity_2541953812_zones.json') as json_zones:
return json_zones.read()
def test_load_zones():
args = parse_arguments([])
zones = load_zones('2541953812', None, args, http_req_mock_zones, write_to_file_mock)
assert 5 == len(zones)
assert 100 == zones[0]['zoneLowBoundary']
assert 138 == zones[1]['zoneLowBoundary']
assert 148 == zones[2]['zoneLowBoundary']
assert 168 == zones[3]['zoneLowBoundary']
assert 182 == zones[4]['zoneLowBoundary']
assert 2462.848 == zones[0]['secsInZone']
def test_extract_display_name():
with open('html/profile_simple.html') as html:
profile_page = html.read()
assert 'John.Doe' == extract_display_name(profile_page)
# some users reported (issue #65) to have an email address as display name
with open('html/profile_email.html') as html:
profile_page = html.read()
assert 'john.doe@email.org' == extract_display_name(profile_page)
# some users reported to have a UUID as display name:
# https://github.com/moderation/garmin-connect-export/issues/31
with open('html/profile_uuid.html') as html:
profile_page = html.read()
assert '36e29d65-715c-456b-9115-84f0b9a0c0ba' == extract_display_name(profile_page)
def test_resolve_path():
assert resolve_path('root', 'sub/{YYYY}', '2018-03-08 12:23:22') == 'root/sub/2018'
assert resolve_path('root', 'sub/{MM}', '2018-03-08 12:23:22') == 'root/sub/03'
assert resolve_path('root', 'sub/{YYYY}/{MM}', '2018-03-08 12:23:22') == 'root/sub/2018/03'
assert resolve_path('root', 'sub/{yyyy}', '2018-03-08 12:23:22') == 'root/sub/{yyyy}'
assert resolve_path('root', 'sub/{YYYYMM}', '2018-03-08 12:23:22') == 'root/sub/{YYYYMM}'
assert resolve_path('root', 'sub/all', '2018-03-08 12:23:22') == 'root/sub/all'
mock_details_multi_counter = 0
def http_req_mock_details_multi(url, post=None, headers=None):
global mock_details_multi_counter
mock_details_multi_counter += 1
if mock_details_multi_counter == 1:
with open('json/activity_multisport_detail.json') as json_stream:
return json_stream.read()
elif mock_details_multi_counter >= 2 & mock_details_multi_counter <= 6:
with open('json/activity_multisport_child.json') as json_stream:
json_string = json_stream.read()
activity_id = url.split('/')[-1]
return json_string.replace('6588349076', activity_id)
else:
raise Exception('mock_details_multi_counter has invalid value ' + str(mock_details_multi_counter))
def test_fetch_multisports():
args = parse_arguments([])
with open('json/activities-list.json') as json_detail:
activity_summaries = json.load(json_detail)
# assert state before fetch_multisports
assert activity_summaries[0]['activityId'] == 6609987243
assert activity_summaries[1]['activityId'] == 6588349056
assert activity_summaries[2]['activityId'] == 6585943400
global mock_details_multi_counter
mock_details_multi_counter = 0
fetch_multisports(activity_summaries, http_req_mock_details_multi, args)
# the entries 0/1/2 from before are now 0/1/7
assert activity_summaries[0]['activityId'] == 6609987243
assert activity_summaries[1]['activityId'] == 6588349056
assert activity_summaries[7]['activityId'] == 6585943400
# at indexes 2..6 are now the five child activities
assert activity_summaries[2]['activityId'] == 6588349067
assert activity_summaries[3]['activityId'] == 6588349072
assert activity_summaries[4]['activityId'] == 6588349076
assert activity_summaries[5]['activityId'] == 6588349079
assert activity_summaries[6]['activityId'] == 6588349081

View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html class="signed-in" lang="de">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Garmin Connect</title>
<link rel="shortcut icon" href="/modern/images/favicon.ico" />
<!-- Connect Styles -->
<link rel="stylesheet" type="text/css" href="/modern/css/dropzone.min.css?bust=4.49.4.0" />
<link rel="stylesheet" type="text/css" href="/web-react/styles/global.css?bust=4.49.4.0" />
<!-- to be modify the google fonts in cdn here -->
<!--garmin.cn-->
<!-- FONTS -->
<link rel='stylesheet' type='text/css' href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;subset=latin,cyrillic-ext,greek-ext,vietnamese" />
<title>Connect</title>
</head>
<body>
<a href="connectagent://launch" id="notify-agent" style="display: none" tabindex="-1"><!-- dummy comment --></a>
<div class="connect-container">
<nav class="main-nav hide"><!-- main navigation --></nav>
<div class="react-global-modal"><!-- react-global-modal --></div>
<div class="main-body">
<!-- Header -->
<header class="header hide">
<!-- placeholder -->
</header>
<section class="beta-testers-survey-banner takeover-container">
<!-- placeholder -->
</section>
<div class="main-header"></div>
<!-- Content Container -->
<div class="content clearfix">
<script>
window.VIEWER_USERPREFERENCES = {"heartRateFormat":{"formatKey":"bpm","formatId":21,"maxFraction":0,"displayFormat":null,"groupingUsed":false,"minFraction":0},"golfSpeedUnit":null,"dateFormat":{"formatKey":"ddmmyyyy","formatId":24,"maxFraction":0,"displayFormat":"EEE, d MMM yyyy","groupingUsed":false,"minFraction":0},"displayName":"john.doe@email.org","golfDistanceUnit":"statute_us","timeZone":"Europe/Paris","hydrationContainers":[],"hydrationMeasurementUnit":"milliliter","powerFormat":{"formatKey":"watt","formatId":30,"maxFraction":0,"displayFormat":null,"groupingUsed":true,"minFraction":0},"numberFormat":"decimal_period","firstDayOfWeek":{"dayName":"monday","isPossibleFirstDay":true,"sortOrder":3,"dayId":3},"timeFormat":{"formatKey":"time_twenty_four_hr","formatId":33,"maxFraction":0,"displayFormat":"H:mm","groupingUsed":false,"minFraction":0},"measurementSystem":"metric","golfElevationUnit":null,"preferredLocale":"de"};
window.VIEWER_SOCIAL_PROFILE = {"runningTrainingSpeed":0,"swimmingTrainingSpeed":0,"showRecentDevice":false,"twitterUrl":null,"levelIsViewed":false,"bio":null,"activityStartVisibility":"private","cyclingTrainingSpeed":0,"showHeight":false,"showBadges":true,"levelUpdateDate":"2001-01-01T18:20:08.0","id":2999999,"showRecentFavorites":false,"makeGolfScorecardsPrivate":false,"activityHeartRateVisibility":"public","profileVisibility":"following","nameApproved":true,"garminGUID":"00000000-5555-4444-8888-333333333333","otherMotivation":null,"showAgeRange":false,"showLifetimeTotals":true,"favoriteCyclingActivityTypes":[],"cyclingClassification":null,"otherPrimaryActivity":null,"userPointOffset":1,"userRoles":["ROLE_OUTDOOR_USER","ROLE_CONNECTUSER","ROLE_FITNESS_USER","ROLE_WELLNESS_USER","ROLE_CONNECT_2_USER"],"profileId":2888888,"showActivityClass":false,"profileImageUrlSmall":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/ccccccc-aaaa-4444-8888-bbbbbbbbbbbb-2888888.png","showRecentGear":false,"showLast12Months":false,"showGender":false,"displayName":"john.doe@email.org","personalWebsite":null,"motivation":null,"primaryActivity":null,"facebookUrl":null,"userLevel":5,"userPro":false,"favoriteActivityTypes":[],"courseVisibility":"public","userPoint":408,"badgeVisibility":"following","fullName":"John Doe","showWeightClass":false,"allowGolfScoringByConnections":true,"levelPointThreshold":0,"userName":"johndoe","showVO2Max":false,"allowGolfLiveScoring":false,"profileImageUrlMedium":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/11111111-2222-4444-aaaa-999999999999-2888888.png","otherActivity":null,"showUpcomingEvents":false,"showAge":false,"profileImageUrlLarge":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/55555555-2222-4444-8888-888888888888-2888888.png","location":"","showPersonalRecords":false,"activityMapVisibility":"public","userProfileFullName":"John Doe","cyclingMaxAvgPower":0,"showWeight":false,"activityPowerVisibility":"public"};
window.VIEWER_DASHBOARDS = [{"dashboardTitle":"","dashboardId":61111,"dashboardOrder":0,"ownerId":2888888,"dashboardTitleKey":"fitness_dashboard"},{"dashboardTitle":"","dashboardId":19999999,"dashboardOrder":1,"ownerId":2888888,"dashboardTitleKey":"wellness_dashboard"}];
window.queueNotificationTimeout = 600000;
window.queuePollRate = 600000;
window.ERROR_VIEW = null;
window.USER_PROFILE = null;
window.viewerIsAuthenticated = true;
window.SYSTEM_TIME_GMT = 1640367355945;
window.SESSION_LENGTH = 2700000;
window.GAUTH_HOST = "https:\/\/sso.garmin.com\/sso";
window.GARMIN_APP_URL = "https:\/\/apps.garmin.com\/connect?locale={locale}";
window.WEB_TOKEN = "";
window.URL_BUST_VALUE = "4.49.4.0";
window.JS_ERROR = true;
window.DI_OAUTH = true;
window.DI_BACKENDS = {"gcapi":"connectapi.garmin.com","ghs":""};
</script>
<script src="/web-react/static/js/vendor.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/backbone-lib.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/bundle.js?bust=4.49.4.0"></script>
</div>
<!-- END .content -->
<!-- Footer -->
<div class="main-footer"></div>
<!-- END .footer -->
<p style="display: none;" id="garmin-connect-version">4.49.4.0</p>
</div>
<!-- END .container -->
</div>
<style>
.privacy-overlay {
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
background-color: #fff;
z-index: 9999; /* Specify a stack order in case you're using a different order for other elements */
}
</style>
<div id="overlay" class="privacy-overlay">
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652ea1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a" integrity="sha512-86chars==" data-cf-beacon='{"rayId":"6767676767676767","token":"1bd18b8f692121212121212121212121","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html class="signed-in" lang="de">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Garmin Connect</title>
<link rel="shortcut icon" href="/modern/images/favicon.ico" />
<!-- Connect Styles -->
<link rel="stylesheet" type="text/css" href="/modern/css/dropzone.min.css?bust=4.49.4.0" />
<link rel="stylesheet" type="text/css" href="/web-react/styles/global.css?bust=4.49.4.0" />
<!-- to be modify the google fonts in cdn here -->
<!--garmin.cn-->
<!-- FONTS -->
<link rel='stylesheet' type='text/css' href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;subset=latin,cyrillic-ext,greek-ext,vietnamese" />
<title>Connect</title>
</head>
<body>
<a href="connectagent://launch" id="notify-agent" style="display: none" tabindex="-1"><!-- dummy comment --></a>
<div class="connect-container">
<nav class="main-nav hide"><!-- main navigation --></nav>
<div class="react-global-modal"><!-- react-global-modal --></div>
<div class="main-body">
<!-- Header -->
<header class="header hide">
<!-- placeholder -->
</header>
<section class="beta-testers-survey-banner takeover-container">
<!-- placeholder -->
</section>
<div class="main-header"></div>
<!-- Content Container -->
<div class="content clearfix">
<script>
window.VIEWER_USERPREFERENCES = {"heartRateFormat":{"formatKey":"bpm","formatId":21,"maxFraction":0,"displayFormat":null,"groupingUsed":false,"minFraction":0},"golfSpeedUnit":null,"dateFormat":{"formatKey":"ddmmyyyy","formatId":24,"maxFraction":0,"displayFormat":"EEE, d MMM yyyy","groupingUsed":false,"minFraction":0},"displayName":"John.Doe","golfDistanceUnit":"statute_us","timeZone":"Europe/Paris","hydrationContainers":[],"hydrationMeasurementUnit":"milliliter","powerFormat":{"formatKey":"watt","formatId":30,"maxFraction":0,"displayFormat":null,"groupingUsed":true,"minFraction":0},"numberFormat":"decimal_period","firstDayOfWeek":{"dayName":"monday","isPossibleFirstDay":true,"sortOrder":3,"dayId":3},"timeFormat":{"formatKey":"time_twenty_four_hr","formatId":33,"maxFraction":0,"displayFormat":"H:mm","groupingUsed":false,"minFraction":0},"measurementSystem":"metric","golfElevationUnit":null,"preferredLocale":"de"};
window.VIEWER_SOCIAL_PROFILE = {"runningTrainingSpeed":0,"swimmingTrainingSpeed":0,"showRecentDevice":false,"twitterUrl":null,"levelIsViewed":false,"bio":null,"activityStartVisibility":"private","cyclingTrainingSpeed":0,"showHeight":false,"showBadges":true,"levelUpdateDate":"2001-01-01T18:20:08.0","id":2999999,"showRecentFavorites":false,"makeGolfScorecardsPrivate":false,"activityHeartRateVisibility":"public","profileVisibility":"following","nameApproved":true,"garminGUID":"00000000-5555-4444-8888-333333333333","otherMotivation":null,"showAgeRange":false,"showLifetimeTotals":true,"favoriteCyclingActivityTypes":[],"cyclingClassification":null,"otherPrimaryActivity":null,"userPointOffset":1,"userRoles":["ROLE_OUTDOOR_USER","ROLE_CONNECTUSER","ROLE_FITNESS_USER","ROLE_WELLNESS_USER","ROLE_CONNECT_2_USER"],"profileId":2888888,"showActivityClass":false,"profileImageUrlSmall":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/ccccccc-aaaa-4444-8888-bbbbbbbbbbbb-2888888.png","showRecentGear":false,"showLast12Months":false,"showGender":false,"displayName":"John.Doe","personalWebsite":null,"motivation":null,"primaryActivity":null,"facebookUrl":null,"userLevel":5,"userPro":false,"favoriteActivityTypes":[],"courseVisibility":"public","userPoint":408,"badgeVisibility":"following","fullName":"John Doe","showWeightClass":false,"allowGolfScoringByConnections":true,"levelPointThreshold":0,"userName":"johndoe","showVO2Max":false,"allowGolfLiveScoring":false,"profileImageUrlMedium":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/11111111-2222-4444-aaaa-999999999999-2888888.png","otherActivity":null,"showUpcomingEvents":false,"showAge":false,"profileImageUrlLarge":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/55555555-2222-4444-8888-888888888888-2888888.png","location":"","showPersonalRecords":false,"activityMapVisibility":"public","userProfileFullName":"John Doe","cyclingMaxAvgPower":0,"showWeight":false,"activityPowerVisibility":"public"};
window.VIEWER_DASHBOARDS = [{"dashboardTitle":"","dashboardId":61111,"dashboardOrder":0,"ownerId":2888888,"dashboardTitleKey":"fitness_dashboard"},{"dashboardTitle":"","dashboardId":19999999,"dashboardOrder":1,"ownerId":2888888,"dashboardTitleKey":"wellness_dashboard"}];
window.queueNotificationTimeout = 600000;
window.queuePollRate = 600000;
window.ERROR_VIEW = null;
window.USER_PROFILE = null;
window.viewerIsAuthenticated = true;
window.SYSTEM_TIME_GMT = 1640367355945;
window.SESSION_LENGTH = 2700000;
window.GAUTH_HOST = "https:\/\/sso.garmin.com\/sso";
window.GARMIN_APP_URL = "https:\/\/apps.garmin.com\/connect?locale={locale}";
window.WEB_TOKEN = "";
window.URL_BUST_VALUE = "4.49.4.0";
window.JS_ERROR = true;
window.DI_OAUTH = true;
window.DI_BACKENDS = {"gcapi":"connectapi.garmin.com","ghs":""};
</script>
<script src="/web-react/static/js/vendor.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/backbone-lib.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/bundle.js?bust=4.49.4.0"></script>
</div>
<!-- END .content -->
<!-- Footer -->
<div class="main-footer"></div>
<!-- END .footer -->
<p style="display: none;" id="garmin-connect-version">4.49.4.0</p>
</div>
<!-- END .container -->
</div>
<style>
.privacy-overlay {
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
background-color: #fff;
z-index: 9999; /* Specify a stack order in case you're using a different order for other elements */
}
</style>
<div id="overlay" class="privacy-overlay">
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652ea1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a" integrity="sha512-86chars==" data-cf-beacon='{"rayId":"6767676767676767","token":"1bd18b8f692121212121212121212121","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html class="signed-in" lang="de">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Garmin Connect</title>
<link rel="shortcut icon" href="/modern/images/favicon.ico" />
<!-- Connect Styles -->
<link rel="stylesheet" type="text/css" href="/modern/css/dropzone.min.css?bust=4.49.4.0" />
<link rel="stylesheet" type="text/css" href="/web-react/styles/global.css?bust=4.49.4.0" />
<!-- to be modify the google fonts in cdn here -->
<!--garmin.cn-->
<!-- FONTS -->
<link rel='stylesheet' type='text/css' href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;subset=latin,cyrillic-ext,greek-ext,vietnamese" />
<title>Connect</title>
</head>
<body>
<a href="connectagent://launch" id="notify-agent" style="display: none" tabindex="-1"><!-- dummy comment --></a>
<div class="connect-container">
<nav class="main-nav hide"><!-- main navigation --></nav>
<div class="react-global-modal"><!-- react-global-modal --></div>
<div class="main-body">
<!-- Header -->
<header class="header hide">
<!-- placeholder -->
</header>
<section class="beta-testers-survey-banner takeover-container">
<!-- placeholder -->
</section>
<div class="main-header"></div>
<!-- Content Container -->
<div class="content clearfix">
<script>
window.VIEWER_USERPREFERENCES = {"heartRateFormat":{"formatKey":"bpm","formatId":21,"maxFraction":0,"displayFormat":null,"groupingUsed":false,"minFraction":0},"golfSpeedUnit":null,"dateFormat":{"formatKey":"ddmmyyyy","formatId":24,"maxFraction":0,"displayFormat":"EEE, d MMM yyyy","groupingUsed":false,"minFraction":0},"displayName":"36e29d65-715c-456b-9115-84f0b9a0c0ba","golfDistanceUnit":"statute_us","timeZone":"Europe/Paris","hydrationContainers":[],"hydrationMeasurementUnit":"milliliter","powerFormat":{"formatKey":"watt","formatId":30,"maxFraction":0,"displayFormat":null,"groupingUsed":true,"minFraction":0},"numberFormat":"decimal_period","firstDayOfWeek":{"dayName":"monday","isPossibleFirstDay":true,"sortOrder":3,"dayId":3},"timeFormat":{"formatKey":"time_twenty_four_hr","formatId":33,"maxFraction":0,"displayFormat":"H:mm","groupingUsed":false,"minFraction":0},"measurementSystem":"metric","golfElevationUnit":null,"preferredLocale":"de"};
window.VIEWER_SOCIAL_PROFILE = {"runningTrainingSpeed":0,"swimmingTrainingSpeed":0,"showRecentDevice":false,"twitterUrl":null,"levelIsViewed":false,"bio":null,"activityStartVisibility":"private","cyclingTrainingSpeed":0,"showHeight":false,"showBadges":true,"levelUpdateDate":"2001-01-01T18:20:08.0","id":2999999,"showRecentFavorites":false,"makeGolfScorecardsPrivate":false,"activityHeartRateVisibility":"public","profileVisibility":"following","nameApproved":true,"garminGUID":"00000000-5555-4444-8888-333333333333","otherMotivation":null,"showAgeRange":false,"showLifetimeTotals":true,"favoriteCyclingActivityTypes":[],"cyclingClassification":null,"otherPrimaryActivity":null,"userPointOffset":1,"userRoles":["ROLE_OUTDOOR_USER","ROLE_CONNECTUSER","ROLE_FITNESS_USER","ROLE_WELLNESS_USER","ROLE_CONNECT_2_USER"],"profileId":2888888,"showActivityClass":false,"profileImageUrlSmall":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/ccccccc-aaaa-4444-8888-bbbbbbbbbbbb-2888888.png","showRecentGear":false,"showLast12Months":false,"showGender":false,"displayName":"36e29d65-715c-456b-9115-84f0b9a0c0ba","personalWebsite":null,"motivation":null,"primaryActivity":null,"facebookUrl":null,"userLevel":5,"userPro":false,"favoriteActivityTypes":[],"courseVisibility":"public","userPoint":408,"badgeVisibility":"following","fullName":"John Doe","showWeightClass":false,"allowGolfScoringByConnections":true,"levelPointThreshold":0,"userName":"johndoe","showVO2Max":false,"allowGolfLiveScoring":false,"profileImageUrlMedium":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/11111111-2222-4444-aaaa-999999999999-2888888.png","otherActivity":null,"showUpcomingEvents":false,"showAge":false,"profileImageUrlLarge":"https://s3.amazonaws.com/garmin-connect-prod/profile_images/55555555-2222-4444-8888-888888888888-2888888.png","location":"","showPersonalRecords":false,"activityMapVisibility":"public","userProfileFullName":"John Doe","cyclingMaxAvgPower":0,"showWeight":false,"activityPowerVisibility":"public"};
window.VIEWER_DASHBOARDS = [{"dashboardTitle":"","dashboardId":61111,"dashboardOrder":0,"ownerId":2888888,"dashboardTitleKey":"fitness_dashboard"},{"dashboardTitle":"","dashboardId":19999999,"dashboardOrder":1,"ownerId":2888888,"dashboardTitleKey":"wellness_dashboard"}];
window.queueNotificationTimeout = 600000;
window.queuePollRate = 600000;
window.ERROR_VIEW = null;
window.USER_PROFILE = null;
window.viewerIsAuthenticated = true;
window.SYSTEM_TIME_GMT = 1640367355945;
window.SESSION_LENGTH = 2700000;
window.GAUTH_HOST = "https:\/\/sso.garmin.com\/sso";
window.GARMIN_APP_URL = "https:\/\/apps.garmin.com\/connect?locale={locale}";
window.WEB_TOKEN = "";
window.URL_BUST_VALUE = "4.49.4.0";
window.JS_ERROR = true;
window.DI_OAUTH = true;
window.DI_BACKENDS = {"gcapi":"connectapi.garmin.com","ghs":""};
</script>
<script src="/web-react/static/js/vendor.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/backbone-lib.js?bust=4.49.4.0"></script>
<script src="/web-react/static/js/bundle.js?bust=4.49.4.0"></script>
</div>
<!-- END .content -->
<!-- Footer -->
<div class="main-footer"></div>
<!-- END .footer -->
<p style="display: none;" id="garmin-connect-version">4.49.4.0</p>
</div>
<!-- END .container -->
</div>
<style>
.privacy-overlay {
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
background-color: #fff;
z-index: 9999; /* Specify a stack order in case you're using a different order for other elements */
}
</style>
<div id="overlay" class="privacy-overlay">
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652ea1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a" integrity="sha512-86chars==" data-cf-beacon='{"rayId":"6767676767676767","token":"1bd18b8f692121212121212121212121","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -0,0 +1,5 @@
JSON Examples
=============
This directory contains some sample JSON output retrieved from Garmin Connect,
it allows to better understand the code ;-)

View File

@@ -0,0 +1,632 @@
[
{
"activityId": 6609987243,
"activityName": "Walk",
"description": null,
"startTimeLocal": "2021-04-15 11:44:05",
"startTimeGMT": "2021-04-15 09:44:05",
"activityType": {
"typeId": 9,
"typeKey": "walking",
"parentTypeId": 17,
"sortOrder": 27,
"isHidden": false,
"restricted": false
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 3385.43994140625,
"duration": 2702.589111328125,
"elapsedDuration": 2702589.111328125,
"movingDuration": 2335.0,
"elevationGain": 37.0,
"elevationLoss": 36.0,
"averageSpeed": 1.253000020980835,
"maxSpeed": 2.3610000610351562,
"startLatitude": 46.77777777777777,
"startLongitude": 7.1111111111111111,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/5979a7d6-2502-4869-8f57-86a28ab7eab3-2836200.png",
"calories": 225.0,
"averageHR": 78.0,
"maxHR": 104.0,
"averageRunningCadenceInStepsPerMinute": 68.53125,
"maxRunningCadenceInStepsPerMinute": 158.0,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": 3274,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"activityLikeProfileImageUrls": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_OUTDOOR_USER",
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 2,
"typeKey": "private"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": 1618479845000,
"sportTypeId": 11,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 0.5,
"anaerobicTrainingEffect": 0.0,
"strokes": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": 113.10710304272114,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": 43.0,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": null,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": 21.0,
"maxTemperature": null,
"minElevation": 62040.00244140625,
"maxElevation": 65540.00244140625,
"avgDoubleCadence": null,
"maxDoubleCadence": 158.0,
"summarizedExerciseSets": null,
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": null
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": 0.5,
"floorsClimbed": null,
"floorsDescended": null,
"manufacturer": "GARMIN",
"diveNumber": null,
"locationName": "Plasselb",
"bottomTime": null,
"lapCount": 3,
"endLatitude": 46.88888888888888,
"endLongitude": 7.222222222222222,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"flow": null,
"grit": null,
"jumpCount": null,
"caloriesEstimated": null,
"caloriesConsumed": null,
"waterEstimated": null,
"waterConsumed": null,
"maxAvgPower_1": null,
"maxAvgPower_2": null,
"maxAvgPower_5": null,
"maxAvgPower_10": null,
"maxAvgPower_20": null,
"maxAvgPower_30": null,
"maxAvgPower_60": null,
"maxAvgPower_120": null,
"maxAvgPower_300": null,
"maxAvgPower_600": null,
"maxAvgPower_1200": null,
"maxAvgPower_1800": null,
"maxAvgPower_3600": null,
"maxAvgPower_7200": null,
"maxAvgPower_18000": null,
"excludeFromPowerCurveReports": null,
"totalSets": null,
"activeSets": null,
"totalReps": null,
"minRespirationRate": null,
"maxRespirationRate": null,
"avgRespirationRate": null,
"trainingEffectLabel": null,
"activityTrainingLoad": null,
"avgFlow": null,
"avgGrit": null,
"minActivityLapDuration": 138.91900634765625,
"avgStress": null,
"startStress": null,
"endStress": null,
"differenceStress": null,
"maxStress": null,
"aerobicTrainingEffectMessage": "NO_AEROBIC_BENEFIT_18",
"anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0",
"splitSummaries": [],
"hasSplits": false,
"hasSeedFirstbeatProfile": null,
"favorite": false,
"decoDive": null,
"purposeful": false,
"pr": false,
"autoCalcCalories": false,
"parent": false,
"atpActivity": false,
"manualActivity": false,
"elevationCorrected": false
},
{
"activityId": 6588349056,
"activityName": "Bike-Walk-Bike",
"description": null,
"startTimeLocal": "2021-04-11 11:50:49",
"startTimeGMT": "2021-04-11 09:50:49",
"activityType": {
"typeId": 89,
"typeKey": "multi_sport",
"parentTypeId": 17,
"sortOrder": 58,
"isHidden": false,
"restricted": false
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 38351.40899467468,
"duration": 10226.370854377747,
"elapsedDuration": 11183693.120002747,
"movingDuration": null,
"elevationGain": 991.0,
"elevationLoss": 994.0,
"averageSpeed": 3.7502462545896287,
"maxSpeed": null,
"startLatitude": 46.66666666666666,
"startLongitude": 7.111111111111111,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/5979a7d6-2502-4869-8f57-86a28ab7eab3-2836200.png",
"calories": 1139.0,
"averageHR": null,
"maxHR": 175.0,
"averageRunningCadenceInStepsPerMinute": null,
"maxRunningCadenceInStepsPerMinute": null,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": null,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"activityLikeProfileImageUrls": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_OUTDOOR_USER",
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 3,
"typeKey": "subscribers"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": null,
"sportTypeId": 18,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 3.4000000953674316,
"anaerobicTrainingEffect": 1.600000023841858,
"strokes": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": null,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": null,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": null,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": null,
"maxTemperature": null,
"minElevation": null,
"maxElevation": null,
"avgDoubleCadence": null,
"maxDoubleCadence": null,
"summarizedExerciseSets": null,
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": null
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": null,
"floorsClimbed": null,
"floorsDescended": null,
"manufacturer": "GARMIN",
"diveNumber": null,
"locationName": "Plasselb",
"bottomTime": null,
"lapCount": 5,
"endLatitude": 46.77777777777777,
"endLongitude": 7.222222222222222,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"flow": null,
"grit": null,
"jumpCount": null,
"caloriesEstimated": null,
"caloriesConsumed": null,
"waterEstimated": null,
"waterConsumed": null,
"maxAvgPower_1": null,
"maxAvgPower_2": null,
"maxAvgPower_5": null,
"maxAvgPower_10": null,
"maxAvgPower_20": null,
"maxAvgPower_30": null,
"maxAvgPower_60": null,
"maxAvgPower_120": null,
"maxAvgPower_300": null,
"maxAvgPower_600": null,
"maxAvgPower_1200": null,
"maxAvgPower_1800": null,
"maxAvgPower_3600": null,
"maxAvgPower_7200": null,
"maxAvgPower_18000": null,
"excludeFromPowerCurveReports": null,
"totalSets": null,
"activeSets": null,
"totalReps": null,
"minRespirationRate": null,
"maxRespirationRate": null,
"avgRespirationRate": null,
"trainingEffectLabel": null,
"activityTrainingLoad": null,
"avgFlow": null,
"avgGrit": null,
"minActivityLapDuration": null,
"avgStress": null,
"startStress": null,
"endStress": null,
"differenceStress": null,
"maxStress": null,
"aerobicTrainingEffectMessage": "IMPROVING_LACTATE_THRESHOLD_12",
"anaerobicTrainingEffectMessage": "MINOR_ANAEROBIC_BENEFIT_15",
"splitSummaries": [],
"hasSplits": false,
"hasSeedFirstbeatProfile": null,
"favorite": false,
"decoDive": null,
"purposeful": false,
"pr": false,
"autoCalcCalories": false,
"parent": true,
"atpActivity": false,
"manualActivity": false,
"elevationCorrected": false
},
{
"activityId": 6585943400,
"activityName": "Run",
"description": null,
"startTimeLocal": "2021-04-11 07:48:33",
"startTimeGMT": "2021-04-11 05:48:33",
"activityType": {
"typeId": 1,
"typeKey": "running",
"parentTypeId": 17,
"sortOrder": 3,
"isHidden": false,
"restricted": false
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 7287.759765625,
"duration": 3459.342041015625,
"elapsedDuration": 4677150.87890625,
"movingDuration": 3108.290008544922,
"elevationGain": 187.0,
"elevationLoss": 175.0,
"averageSpeed": 2.1070001125335693,
"maxSpeed": 3.5179998874664307,
"startLatitude": 46.77777777777777,
"startLongitude": 7.111111111111111,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/5979a7d6-2502-4869-8f57-86a28ab7eab3-2836200.png",
"calories": 571.0,
"averageHR": 133.0,
"maxHR": 188.0,
"averageRunningCadenceInStepsPerMinute": 134.59375,
"maxRunningCadenceInStepsPerMinute": 241.0,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": 7862,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"activityLikeProfileImageUrls": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_OUTDOOR_USER",
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 3,
"typeKey": "subscribers"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": 1618120113000,
"sportTypeId": 1,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 2.9000000953674316,
"anaerobicTrainingEffect": 0.4000000059604645,
"strokes": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": 94.47436351638775,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": 43.0,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": null,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": 11.0,
"maxTemperature": null,
"minElevation": 56320.001220703125,
"maxElevation": 65459.99755859375,
"avgDoubleCadence": null,
"maxDoubleCadence": 241.0,
"summarizedExerciseSets": null,
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": null
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": 0.60003662109375,
"floorsClimbed": null,
"floorsDescended": null,
"manufacturer": "GARMIN",
"diveNumber": null,
"locationName": "Plasselb",
"bottomTime": null,
"lapCount": 8,
"endLatitude": 46.888888888888888,
"endLongitude": 7.222222222222222,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"flow": null,
"grit": null,
"jumpCount": null,
"caloriesEstimated": null,
"caloriesConsumed": null,
"waterEstimated": null,
"waterConsumed": null,
"maxAvgPower_1": null,
"maxAvgPower_2": null,
"maxAvgPower_5": null,
"maxAvgPower_10": null,
"maxAvgPower_20": null,
"maxAvgPower_30": null,
"maxAvgPower_60": null,
"maxAvgPower_120": null,
"maxAvgPower_300": null,
"maxAvgPower_600": null,
"maxAvgPower_1200": null,
"maxAvgPower_1800": null,
"maxAvgPower_3600": null,
"maxAvgPower_7200": null,
"maxAvgPower_18000": null,
"excludeFromPowerCurveReports": null,
"totalSets": null,
"activeSets": null,
"totalReps": null,
"minRespirationRate": null,
"maxRespirationRate": null,
"avgRespirationRate": null,
"trainingEffectLabel": null,
"activityTrainingLoad": null,
"avgFlow": null,
"avgGrit": null,
"minActivityLapDuration": 104.4000015258789,
"avgStress": null,
"startStress": null,
"endStress": null,
"differenceStress": null,
"maxStress": null,
"aerobicTrainingEffectMessage": "MAINTAINING_AEROBIC_BASE_7",
"anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0",
"splitSummaries": [],
"hasSplits": false,
"hasSeedFirstbeatProfile": null,
"favorite": false,
"decoDive": null,
"purposeful": false,
"pr": false,
"autoCalcCalories": false,
"parent": false,
"atpActivity": false,
"manualActivity": false,
"elevationCorrected": false
}
]

View File

@@ -0,0 +1,822 @@
{"results": {
"activities": [
{
"activity": {
"activityId": 2541953812,
"activityName": "Reckingen Augenstern-Ulrichen Langlauf",
"activityDescription": "",
"activityVideoUrl": "",
"locationName": "",
"isTitled": true,
"isElevationCorrected": false,
"isBarometricCapable": true,
"isSwimAlgorithmCapable": true,
"isVideoCapable": false,
"isActivityEdited": false,
"favorite": false,
"ispr": false,
"isAutoCalcCalories": false,
"isParent": false,
"parentId": 0,
"userId": 2836200,
"username": "eschep",
"displayname": "eschep",
"uploadDate": {
"@class": "org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl",
"display": "Thu, 8 Mar 2018 7:09",
"value": "2018-03-08",
"withDay": "Thu, 8 Mar 2018",
"abbr": "8 Mar 2018",
"millis": "1520489394000"
},
"uploadApplication": {
"display": "Unknown",
"key": "unknown",
"version": "18.4.4.0"
},
"device": {
"display": "fēnix 5",
"key": "fenix5",
"version": "8.0.0.0"
},
"deviceId": "3946806421",
"deviceImageUrl": "https://static.garmincdn.com/com.garmin.connect/content/images/device-images/fenix-5.png",
"isDeviceReleased": true,
"externalId": "889442603",
"privacy": {
"display": "Subscriber",
"key": "subscribers",
"fieldNameDisplay": "Privacy"
},
"numTrackpoints": -1,
"activityType": {
"display": "Cross Country Skiing",
"key": "cross_country_skiing",
"fieldNameDisplay": "Activity Type",
"parent": {
"display": "Other",
"key": "other",
"fieldNameDisplay": "Activity Type"
}
},
"eventType": {
"display": "Uncategorized",
"key": "uncategorized",
"fieldNameDisplay": "Event Type"
},
"activityTimeZone": {
"display": "(GMT+01:00) Central European Time",
"key": "Europe/Paris",
"fieldNameDisplay": "Time Zone",
"abbr": "Central European Time"
},
"localizedSpeedLabel": "Speed",
"localizedPaceLabel": "Pace",
"activitySummary": {
"SumSampleCountDuration": {
"fieldDisplayName": "SumSampleCountDuration",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"SumSampleCountElevation": {
"fieldDisplayName": "SumSampleCountElevation",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"SumSampleCountDistance": {
"fieldDisplayName": "SumSampleCountDistance",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"GainUncorrectedElevation": {
"fieldDisplayName": "GainUncorrectedElevation",
"display": "10,600",
"displayUnit": "Centimeters",
"value": "10600.0",
"unitAbbr": "cm",
"withUnit": "10,600 Centimeters",
"withUnitAbbr": "10,600 cm",
"uom": "centimeter"
},
"GainCorrectedElevation": {
"fieldDisplayName": "GainCorrectedElevation",
"display": "8,353",
"displayUnit": "Centimeters",
"value": "8353.0",
"unitAbbr": "cm",
"withUnit": "8,353 Centimeters",
"withUnitAbbr": "8,353 cm",
"uom": "centimeter"
},
"SumSampleCountSpeed": {
"fieldDisplayName": "SumSampleCountSpeed",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"LossUncorrectedElevation": {
"fieldDisplayName": "LossUncorrectedElevation",
"display": "7,300",
"displayUnit": "Centimeters",
"value": "7300.0",
"unitAbbr": "cm",
"withUnit": "7,300 Centimeters",
"withUnitAbbr": "7,300 cm",
"uom": "centimeter"
},
"SumSampleCountHeartRate": {
"fieldDisplayName": "SumSampleCountHeartRate",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"DirectFunctionalThresholdPower": {
"fieldDisplayName": "DirectFunctionalThresholdPower",
"display": "244",
"displayUnit": "Watts",
"value": "244.0",
"unitAbbr": "W",
"withUnit": "244 Watts",
"withUnitAbbr": "244 W",
"uom": "watt"
},
"EndLongitude": {
"fieldDisplayName": "EndLongitude",
"display": "8.2481",
"displayUnit": "Decimal Degrees",
"value": "8.248067228123546",
"unitAbbr": "dd",
"withUnit": "8.2481 Decimal Degrees",
"withUnitAbbr": "8.2481 dd",
"uom": "dd"
},
"WeightedMeanMovingSpeed": {
"fieldDisplayName": "Avg Moving Speed",
"display": "11.3",
"displayUnit": "Kilometers per Hour",
"value": "11.328197775200842",
"unitAbbr": "km/h",
"withUnit": "11.3 Kilometers per Hour",
"withUnitAbbr": "11.3 km/h",
"uom": "kph"
},
"WeightedMeanMovingPace": {
"fieldDisplayName": "Avg Moving Pace",
"display": "05:18",
"displayUnit": "Minutes per Kilometer",
"value": "5.296517697753228",
"unitAbbr": "min/km",
"withUnit": "05:18 Minutes per Kilometer",
"withUnitAbbr": "05:18 min/km",
"uom": "minperkm"
},
"MaxHeartRate": {
"fieldDisplayName": "Max HR",
"display": "146",
"displayUnit": "Beats per Minute",
"value": "146.0",
"unitAbbr": "bpm",
"withUnit": "146 Beats per Minute",
"withUnitAbbr": "146 bpm",
"uom": "bpm",
"percentMax": {
"fieldDisplayName": "Max HR",
"display": "79",
"displayUnit": "Percent of Max",
"value": "78.91891891891892",
"unitAbbr": "% of Max",
"withUnit": "79 Percent of Max",
"withUnitAbbr": "79 % of Max",
"uom": "bpm"
},
"zones": {
"fieldDisplayName": "Max HR",
"display": "3.9",
"displayUnit": "Zones",
"value": "3.8947368421052633",
"unitAbbr": "z",
"withUnit": "3.9 Zones",
"withUnitAbbr": "3.9 z",
"uom": "bpm"
}
},
"WeightedMeanHeartRate": {
"fieldDisplayName": "Avg HR",
"display": "110",
"displayUnit": "Beats per Minute",
"value": "110.0",
"unitAbbr": "bpm",
"withUnit": "110 Beats per Minute",
"withUnitAbbr": "110 bpm",
"uom": "bpm",
"percentMax": {
"fieldDisplayName": "Avg HR",
"display": "59",
"displayUnit": "Percent of Max",
"value": "59.45945945945946",
"unitAbbr": "% of Max",
"withUnit": "59 Percent of Max",
"withUnitAbbr": "59 % of Max",
"uom": "bpm"
},
"zones": {
"fieldDisplayName": "Avg HR",
"display": "1.9",
"displayUnit": "Zones",
"value": "1.9473684210526314",
"unitAbbr": "z",
"withUnit": "1.9 Zones",
"withUnitAbbr": "1.9 z",
"uom": "bpm"
}
},
"MinSpeed": {
"fieldDisplayName": "Min Speed",
"display": "0.3",
"displayUnit": "Kilometers per Hour",
"value": "0.30960001051425934",
"unitAbbr": "km/h",
"withUnit": "0.3 Kilometers per Hour",
"withUnitAbbr": "0.3 km/h",
"uom": "kph"
},
"MinPace": {
"fieldDisplayName": "MinPace",
"display": "--:--",
"displayUnit": "Minutes per Kilometer",
"value": "-Infinity",
"unitAbbr": "min/km",
"withUnit": "--:-- Minutes per Kilometer",
"withUnitAbbr": "--:-- min/km",
"uom": "minperkm"
},
"MaxSpeed": {
"fieldDisplayName": "Max Speed",
"display": "37.8",
"displayUnit": "Kilometers per Hour",
"value": "37.84320030212403",
"unitAbbr": "km/h",
"withUnit": "37.8 Kilometers per Hour",
"withUnitAbbr": "37.8 km/h",
"uom": "kph"
},
"MaxPace": {
"fieldDisplayName": "Best Pace",
"display": "01:35",
"displayUnit": "Minutes per Kilometer",
"value": "1.5854895865303542",
"unitAbbr": "min/km",
"withUnit": "01:35 Minutes per Kilometer",
"withUnitAbbr": "01:35 min/km",
"uom": "minperkm"
},
"SumEnergy": {
"fieldDisplayName": "Calories",
"display": "319",
"displayUnit": "Calories",
"value": "319.0915556488991",
"unitAbbr": "C",
"withUnit": "319 Calories",
"withUnitAbbr": "319 C",
"uom": "kilocalorie"
},
"SumElapsedDuration": {
"fieldDisplayName": "Elapsed Time",
"display": "00:43:47",
"displayUnit": "Hours:Minutes:Seconds",
"value": "2627.38",
"unitAbbr": "h:m:s",
"withUnit": "00:43:47 Hours:Minutes:Seconds",
"withUnitAbbr": "00:43:47 h:m:s",
"uom": "second"
},
"MaxRunCadence": {
"fieldDisplayName": "Max Run Cadence",
"display": "110",
"displayUnit": "Steps per Minute",
"value": "110.0",
"unitAbbr": "spm",
"withUnit": "110 Steps per Minute",
"withUnitAbbr": "110 spm",
"uom": "stepsPerMinute"
},
"MaxDoubleCadence": {
"fieldDisplayName": "Max Run Cadence",
"display": "220",
"displayUnit": "Steps per Minute",
"value": "220.0",
"unitAbbr": "spm",
"withUnit": "220 Steps per Minute",
"withUnitAbbr": "220 spm",
"uom": "stepsPerMinute"
},
"WeightedMeanRunCadence": {
"fieldDisplayName": "Avg Run Cadence",
"display": "17",
"displayUnit": "Steps per Minute",
"value": "17.0",
"unitAbbr": "spm",
"withUnit": "17 Steps per Minute",
"withUnitAbbr": "17 spm",
"uom": "stepsPerMinute"
},
"WeightedMeanDoubleCadence": {
"fieldDisplayName": "Avg Run Cadence",
"display": "35",
"displayUnit": "Steps per Minute",
"value": "34.765625",
"unitAbbr": "spm",
"withUnit": "35 Steps per Minute",
"withUnitAbbr": "35 spm",
"uom": "stepsPerMinute"
},
"BeginLatitude": {
"fieldDisplayName": "Beginning Latitude",
"display": "46.4668",
"displayUnit": "Decimal Degrees",
"value": "46.46675166673958",
"unitAbbr": "dd",
"withUnit": "46.4668 Decimal Degrees",
"withUnitAbbr": "46.4668 dd",
"uom": "dd"
},
"SumMovingDuration": {
"fieldDisplayName": "Moving Time",
"display": "00:43:34",
"displayUnit": "Hours:Minutes:Seconds",
"value": "2614.0",
"unitAbbr": "h:m:s",
"withUnit": "00:43:34 Hours:Minutes:Seconds",
"withUnitAbbr": "00:43:34 h:m:s",
"uom": "second"
},
"WeightedMeanSpeed": {
"fieldDisplayName": "Avg Speed",
"display": "11.3",
"displayUnit": "Kilometers per Hour",
"value": "11.271600151062014",
"unitAbbr": "km/h",
"withUnit": "11.3 Kilometers per Hour",
"withUnitAbbr": "11.3 km/h",
"uom": "kph"
},
"WeightedMeanPace": {
"fieldDisplayName": "Avg Pace",
"display": "05:19",
"displayUnit": "Minutes per Kilometer",
"value": "5.323112885116562",
"unitAbbr": "min/km",
"withUnit": "05:19 Minutes per Kilometer",
"withUnitAbbr": "05:19 min/km",
"uom": "minperkm"
},
"SumDuration": {
"fieldDisplayName": "Time",
"display": "00:43:47",
"displayUnit": "Hours:Minutes:Seconds",
"value": "2627.38",
"unitAbbr": "h:m:s",
"withUnit": "00:43:47 Hours:Minutes:Seconds",
"withUnitAbbr": "00:43:47 h:m:s",
"uom": "second"
},
"SumDistance": {
"fieldDisplayName": "Distance",
"display": "8.23",
"displayUnit": "Kilometers",
"value": "8.22553",
"unitAbbr": "km",
"withUnit": "8.23 Kilometers",
"withUnitAbbr": "8.23 km",
"uom": "kilometer"
},
"BeginLongitude": {
"fieldDisplayName": "Beginning Longitude",
"display": "8.2435",
"displayUnit": "Decimal Degrees",
"value": "8.243478052318096",
"unitAbbr": "dd",
"withUnit": "8.2435 Decimal Degrees",
"withUnitAbbr": "8.2435 dd",
"uom": "dd"
},
"EndTrainingEffectIndices": {
"fieldDisplayName": "EndTrainingEffectIndices",
"display": "0.00",
"displayUnit": "",
"value": "0.0",
"unitAbbr": "",
"withUnit": "0.00 ",
"withUnitAbbr": "0.00 ",
"uom": "dimensionless"
},
"SumSampleCountTimestamp": {
"fieldDisplayName": "SumSampleCountTimestamp",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"BeginTrainingEffectIndices": {
"fieldDisplayName": "BeginTrainingEffectIndices",
"display": "0.00",
"displayUnit": "",
"value": "0.0",
"unitAbbr": "",
"withUnit": "0.00 ",
"withUnitAbbr": "0.00 ",
"uom": "dimensionless"
},
"MaxCorrectedElevation": {
"fieldDisplayName": "MaxCorrectedElevation",
"display": "135,848",
"displayUnit": "Centimeters",
"value": "135848.0",
"unitAbbr": "cm",
"withUnit": "135,848 Centimeters",
"withUnitAbbr": "135,848 cm",
"uom": "centimeter"
},
"MinCorrectedElevation": {
"fieldDisplayName": "MinCorrectedElevation",
"display": "130,817",
"displayUnit": "Centimeters",
"value": "130817.0",
"unitAbbr": "cm",
"withUnit": "130,817 Centimeters",
"withUnitAbbr": "130,817 cm",
"uom": "centimeter"
},
"MinHeartRate": {
"fieldDisplayName": "MinHeartRate",
"display": "83",
"displayUnit": "Beats per Minute",
"value": "83.0",
"unitAbbr": "bpm",
"withUnit": "83 Beats per Minute",
"withUnitAbbr": "83 bpm",
"uom": "bpm",
"percentMax": {
"fieldDisplayName": "MinHeartRate",
"display": "45",
"displayUnit": "Percent of Max",
"value": "44.86486486486487",
"unitAbbr": "% of Max",
"withUnit": "45 Percent of Max",
"withUnitAbbr": "45 % of Max",
"uom": "bpm"
},
"zones": {
"fieldDisplayName": "MinHeartRate",
"display": "0.9",
"displayUnit": "Zones",
"value": "0.9021739130434783",
"unitAbbr": "z",
"withUnit": "0.9 Zones",
"withUnitAbbr": "0.9 z",
"uom": "bpm"
}
},
"MaxUncorrectedElevation": {
"fieldDisplayName": "MaxUncorrectedElevation",
"display": "137,480",
"displayUnit": "Centimeters",
"value": "137480.0",
"unitAbbr": "cm",
"withUnit": "137,480 Centimeters",
"withUnitAbbr": "137,480 cm",
"uom": "centimeter"
},
"MinUncorrectedElevation": {
"fieldDisplayName": "MinUncorrectedElevation",
"display": "132,600",
"displayUnit": "Centimeters",
"value": "132600.0",
"unitAbbr": "cm",
"withUnit": "132,600 Centimeters",
"withUnitAbbr": "132,600 cm",
"uom": "centimeter"
},
"LossCorrectedElevation": {
"fieldDisplayName": "LossCorrectedElevation",
"display": "5,207",
"displayUnit": "Centimeters",
"value": "5207.0",
"unitAbbr": "cm",
"withUnit": "5,207 Centimeters",
"withUnitAbbr": "5,207 cm",
"uom": "centimeter"
},
"GainElevation": {
"fieldDisplayName": "Elevation Gain",
"display": "106",
"displayUnit": "Meters",
"value": "106.0",
"unitAbbr": "m",
"withUnit": "106 Meters",
"withUnitAbbr": "106 m",
"uom": "meter"
},
"SumStep": {
"fieldDisplayName": "Steps",
"display": "3,522",
"displayUnit": "Steps",
"value": "3522.0",
"unitAbbr": "s",
"withUnit": "3,522 Steps",
"withUnitAbbr": "3,522 s",
"uom": "step"
},
"SumSampleCountLongitude": {
"fieldDisplayName": "SumSampleCountLongitude",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"BeginTimestamp": {
"fieldDisplayName": "Start",
"display": "Thu, 8 Mar 2018 12:23",
"displayUnit": "",
"value": "2018-03-08T11:23:22.000Z",
"unitAbbr": "Central European Time",
"withUnit": "Thu, 8 Mar 2018 12:23 ",
"withUnitAbbr": "Thu, 8 Mar 2018 12:23 Central European Time",
"uom": "Europe/Paris"
},
"EndTimestamp": {
"fieldDisplayName": "EndTimestamp",
"display": "Thu, 8 Mar 2018 13:07",
"displayUnit": "",
"value": "2018-03-08T12:07:09.000Z",
"unitAbbr": "Central European Time",
"withUnit": "Thu, 8 Mar 2018 13:07 ",
"withUnitAbbr": "Thu, 8 Mar 2018 13:07 Central European Time",
"uom": "Europe/Paris"
},
"SumSampleCountLatitude": {
"fieldDisplayName": "SumSampleCountLatitude",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"LossElevation": {
"fieldDisplayName": "Elevation Loss",
"display": "73",
"displayUnit": "Meters",
"value": "73.0",
"unitAbbr": "m",
"withUnit": "73 Meters",
"withUnitAbbr": "73 m",
"uom": "meter"
},
"SumSampleCountAirTemperature": {
"fieldDisplayName": "SumSampleCountAirTemperature",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"SumAnaerobicTrainingEffect": {
"fieldDisplayName": "SumAnaerobicTrainingEffect",
"display": "0.10",
"displayUnit": "",
"value": "0.10000000149011612",
"unitAbbr": "",
"withUnit": "0.10 ",
"withUnitAbbr": "0.10 ",
"uom": "dimensionless"
},
"SumSampleCountMovingDuration": {
"fieldDisplayName": "SumSampleCountMovingDuration",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"MaxVerticalSpeed": {
"fieldDisplayName": "MaxVerticalSpeed",
"display": "0.60",
"displayUnit": "Meters per Second",
"value": "0.5999755859375",
"unitAbbr": "mps",
"withUnit": "0.60 Meters per Second",
"withUnitAbbr": "0.60 mps",
"uom": "mps"
},
"WeightedMeanStrideLength": {
"fieldDisplayName": "Avg Stride Length",
"display": "6.15",
"displayUnit": "Meters",
"value": "6.151658983791259",
"unitAbbr": "m",
"withUnit": "6.15 Meters",
"withUnitAbbr": "6.15 m",
"uom": "meter"
},
"SumSampleCountElapsedDuration": {
"fieldDisplayName": "SumSampleCountElapsedDuration",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"MaxElevation": {
"fieldDisplayName": "Max Elevation",
"display": "1,375",
"displayUnit": "Meters",
"value": "1374.8",
"unitAbbr": "m",
"withUnit": "1,375 Meters",
"withUnitAbbr": "1,375 m",
"uom": "meter"
},
"SumSampleCountMovingSpeed": {
"fieldDisplayName": "SumSampleCountMovingSpeed",
"display": "922",
"displayUnit": "Samples",
"value": "922.0",
"unitAbbr": "Samples",
"withUnit": "922 Samples",
"withUnitAbbr": "922 Samples",
"uom": "sampleCount"
},
"MinAirTemperature": {
"fieldDisplayName": "Min Temperature",
"display": "21.0",
"displayUnit": "",
"value": "21.0",
"unitAbbr": "°C",
"withUnit": "21.0 ",
"withUnitAbbr": "21.0 °C",
"uom": "celcius"
},
"MaxFractionalCadence": {
"fieldDisplayName": "Max Run Cadence",
"display": "0.00",
"displayUnit": "Revolutions per Minute",
"value": "0.0",
"unitAbbr": "rpm",
"withUnit": "0.00 Revolutions per Minute",
"withUnitAbbr": "0.00 rpm",
"uom": "rpm"
},
"WeightedMeanFractionalCadence": {
"fieldDisplayName": "Avg Run Cadence",
"display": "0.38",
"displayUnit": "Revolutions per Minute",
"value": "0.3828125",
"unitAbbr": "rpm",
"withUnit": "0.38 Revolutions per Minute",
"withUnitAbbr": "0.38 rpm",
"uom": "rpm"
},
"MaxAirTemperature": {
"fieldDisplayName": "Max Temperature",
"display": "28.0",
"displayUnit": "",
"value": "28.0",
"unitAbbr": "°C",
"withUnit": "28.0 ",
"withUnitAbbr": "28.0 °C",
"uom": "celcius"
},
"EndLatitude": {
"fieldDisplayName": "EndLatitude",
"display": "46.4699",
"displayUnit": "Decimal Degrees",
"value": "46.469942070543766",
"unitAbbr": "dd",
"withUnit": "46.4699 Decimal Degrees",
"withUnitAbbr": "46.4699 dd",
"uom": "dd"
},
"SumTrainingEffect": {
"fieldDisplayName": "Training Effect",
"display": "1.40",
"displayUnit": "",
"value": "1.399999976158142",
"unitAbbr": "",
"withUnit": "1.40 ",
"withUnitAbbr": "1.40 ",
"uom": "dimensionless"
},
"WeightedMeanAirTemperature": {
"fieldDisplayName": "Avg Temperature",
"display": "24.8",
"displayUnit": "",
"value": "24.846973734297677",
"unitAbbr": "°C",
"withUnit": "24.8 ",
"withUnitAbbr": "24.8 °C",
"uom": "celcius"
},
"SumSampleCountDoubleCadence": {
"fieldDisplayName": "SumSampleCountDoubleCadence",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"SumSampleCountFractionalCadence": {
"fieldDisplayName": "SumSampleCountFractionalCadence",
"display": "926",
"displayUnit": "Samples",
"value": "926.0",
"unitAbbr": "Samples",
"withUnit": "926 Samples",
"withUnitAbbr": "926 Samples",
"uom": "sampleCount"
},
"MinElevation": {
"fieldDisplayName": "Min Elevation",
"display": "1,326",
"displayUnit": "Meters",
"value": "1326.0",
"unitAbbr": "m",
"withUnit": "1,326 Meters",
"withUnitAbbr": "1,326 m",
"uom": "meter"
}
},
"totalLaps": {},
"garminSwimAlgorithm": false,
"updatedDate": {
"@class": "sql-timestamp",
"$": "2018-03-08 11:35:20.0"
},
"updatedDateFormatted": "2018-03-08 11:35:20.0 GMT",
"userRoles": [
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_OUTDOOR_USER",
"ROLE_CONNECT_2_USER"
]
}
}
],
"totalFound": 861,
"currentPage": 1,
"totalPages": 87,
"query": {
"filters": {
"parent_id": "",
"parent_id_oper": "is",
"userId": "2836200",
"userId_oper": "="
},
"sortOrder": "DESC",
"sortField": "activitySummaryBeginTimestampGmt",
"activityStart": "0",
"activitiesPerPage": "10",
"explore": "false",
"ignoreUntitled": "false",
"ignoreNonGPS": "false"
}
}}

View File

@@ -0,0 +1,94 @@
{
"activityId": 154105348,
"activityName": "Stechelberg-Lauterbrunnen",
"userProfileId": 2836200,
"isMultiSportParent": false,
"activityTypeDTO": {
"typeId": 81,
"typeKey": "cross_country_skiing",
"parentTypeId": 4,
"sortOrder": 39
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 1,
"typeKey": "public"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 80,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 2,
"formatKey": "gpx"
},
"associatedCourseId": null,
"lastUpdateDate": "2012-03-02T11:09:30.0",
"uploadedDate": "2012-03-02T10:49:45.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": false,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {
"showElevation": true,
"showMovingSpeed": true,
"showSpeed": true,
"showTimestamp": true
},
"childIds": [],
"sensors": null,
"activityImages": [],
"manufacturer": "",
"diveNumber": null,
"lapCount": 1,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": null,
"deviceTypePk": 19,
"deviceVersionPk": 80
},
"gcj02": false,
"favorite": false,
"autoCalcCalories": false,
"elevationCorrected": false,
"manualActivity": false,
"personalRecord": false
},
"summaryDTO": {
"startTimeLocal": "2012-02-27T10:10:06.0",
"startTimeGMT": "2012-02-27T09:10:06.0",
"distance": 11610.0,
"duration": 4177.0,
"movingDuration": 3887.0,
"elapsedDuration": 4177.0,
"elevationGain": 137.0,
"elevationLoss": 138.0,
"maxElevation": 907.91,
"minElevation": 793.9,
"averageSpeed": 2.7777777777777777,
"averageMovingSpeed": 2.986575184492859,
"maxSpeed": 15.722222222222221
}
}

View File

@@ -0,0 +1,148 @@
{
"activityId": 2541953812,
"activityName": "Reckingen Augenstern-Ulrichen Langlauf",
"userProfileId": 2836200,
"isMultiSportParent": false,
"activityTypeDTO": {
"typeId": 81,
"typeKey": "cross_country_skiing",
"parentTypeId": 4,
"sortOrder": 39
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 3,
"typeKey": "subscribers"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 845288,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 7,
"formatKey": "fit"
},
"associatedCourseId": null,
"lastUpdateDate": "2018-03-08T11:35:20.0",
"uploadedDate": "2018-03-08T06:09:54.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": true,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {
"showAirTemperature": true,
"showDistance": true,
"showDuration": true,
"showElevation": true,
"showHeartRate": true,
"showMovingDuration": true,
"showMovingSpeed": true,
"showSpeed": true,
"showTimestamp": true
},
"childIds": [],
"sensors": [
{
"sku": "006-B2697-00",
"sourceType": "LOCAL",
"softwareVersion": 8.0
},
{
"sku": "006-B2697-00",
"sourceType": "LOCAL",
"localDeviceType": "BAROMETER",
"softwareVersion": 8.0
},
{
"sku": "006-B1621-00",
"sourceType": "LOCAL",
"localDeviceType": "GPS",
"softwareVersion": 4.3
},
{
"sourceType": "LOCAL",
"localDeviceType": "ACCELEROMETER"
},
{
"sku": "006-B0000-00",
"sourceType": "LOCAL",
"localDeviceType": "BLUETOOTH_LOW_ENERGY_CHIPSET",
"softwareVersion": 606.72
},
{
"sourceType": "LOCAL",
"localDeviceType": "WHR",
"softwareVersion": 3.23
}
],
"activityImages": [],
"manufacturer": "GARMIN",
"diveNumber": null,
"lapCount": 9,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": "3946806421",
"deviceTypePk": 34236,
"deviceVersionPk": 845288
},
"gcj02": false,
"favorite": false,
"autoCalcCalories": false,
"elevationCorrected": false,
"manualActivity": false,
"personalRecord": false
},
"summaryDTO": {
"startTimeLocal": "2018-03-08T12:23:22.0",
"startTimeGMT": "2018-03-08T11:23:22.0",
"startLatitude": 46.46675166673958,
"startLongitude": 8.243478052318096,
"distance": 8225.53,
"duration": 2627.38,
"movingDuration": 2614.0,
"elapsedDuration": 2627.38,
"elevationGain": 106.0,
"elevationLoss": 73.0,
"maxElevation": 1374.8,
"minElevation": 1326.0,
"averageSpeed": 3.13100004196167,
"averageMovingSpeed": 3.146721604222456,
"maxSpeed": 10.51200008392334,
"calories": 319.0915556488991,
"averageHR": 110.0,
"maxHR": 146.0,
"averageTemperature": 24.846973734297677,
"maxTemperature": 28.0,
"minTemperature": 21.0,
"trainingEffect": 1.399999976158142,
"anaerobicTrainingEffect": 0.10000000149011612,
"aerobicTrainingEffectMessage": "MINOR_AEROBIC_BENEFIT_0",
"anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0",
"endLatitude": 46.469942070543766,
"endLongitude": 8.248067228123546,
"maxVerticalSpeed": 0.5999755859375
},
"locationName": "Goms"
}

View File

@@ -0,0 +1,210 @@
{
"activityId": 2541953812,
"activityName": "Reckingen Augenstern-Ulrichen Langlauf",
"description": null,
"startTimeLocal": "2018-03-08 12:23:22",
"startTimeGMT": "2018-03-08 11:23:22",
"activityType": {
"typeId": 171,
"typeKey": "cross_country_skiing_ws",
"parentTypeId": 165,
"sortOrder": 101,
"isHidden": false,
"restricted": false
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 8225.5302734375,
"duration": 2627.3798828125,
"elapsedDuration": 2627379.8828125,
"movingDuration": 2614.0,
"elevationGain": 106.0,
"elevationLoss": 73.0,
"averageSpeed": 3.13100004196167,
"maxSpeed": 10.51200008392334,
"startLatitude": 46.46675166673958,
"startLongitude": 8.243478052318096,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/5979a7d6-2502-4869-8f57-86a28ab7eab3-2836200.png",
"calories": 319.0,
"averageHR": 110.0,
"maxHR": 146.0,
"averageRunningCadenceInStepsPerMinute": 34.765625,
"maxRunningCadenceInStepsPerMinute": 220.0,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": 3522,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"activityLikeProfileImageUrls": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_OUTDOOR_USER",
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 3,
"typeKey": "subscribers"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": 1520508202000,
"sportTypeId": 0,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 1.399999976158142,
"anaerobicTrainingEffect": 0.10000000149011612,
"strokes": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": 615.1658983791259,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": null,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": 244.0,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": 21.0,
"maxTemperature": null,
"minElevation": 132600.0,
"maxElevation": 137480.0048828125,
"avgDoubleCadence": null,
"maxDoubleCadence": 220.0,
"summarizedExerciseSets": null,
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": 0
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": 0.5999755859375,
"floorsClimbed": null,
"floorsDescended": null,
"manufacturer": null,
"diveNumber": null,
"locationName": "Goms",
"bottomTime": null,
"lapCount": 9,
"endLatitude": 46.469942070543766,
"endLongitude": 8.248067228123546,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"flow": null,
"grit": null,
"jumpCount": null,
"caloriesEstimated": null,
"caloriesConsumed": null,
"waterEstimated": null,
"waterConsumed": null,
"maxAvgPower_1": null,
"maxAvgPower_2": null,
"maxAvgPower_5": null,
"maxAvgPower_10": null,
"maxAvgPower_20": null,
"maxAvgPower_30": null,
"maxAvgPower_60": null,
"maxAvgPower_120": null,
"maxAvgPower_300": null,
"maxAvgPower_600": null,
"maxAvgPower_1200": null,
"maxAvgPower_1800": null,
"maxAvgPower_3600": null,
"maxAvgPower_7200": null,
"maxAvgPower_18000": null,
"excludeFromPowerCurveReports": null,
"totalSets": null,
"activeSets": null,
"totalReps": null,
"minRespirationRate": null,
"maxRespirationRate": null,
"avgRespirationRate": null,
"trainingEffectLabel": null,
"activityTrainingLoad": null,
"avgFlow": null,
"avgGrit": null,
"minActivityLapDuration": null,
"avgStress": null,
"startStress": null,
"endStress": null,
"differenceStress": null,
"maxStress": null,
"aerobicTrainingEffectMessage": null,
"anaerobicTrainingEffectMessage": null,
"splitSummaries": [],
"hasSplits": null,
"hasSeedFirstbeatProfile": null,
"favorite": false,
"decoDive": null,
"purposeful": false,
"pr": false,
"autoCalcCalories": false,
"parent": false,
"atpActivity": null,
"manualActivity": false,
"elevationCorrected": false
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
[
{
"zoneNumber": 3,
"secsInZone": 567.662,
"zoneLowBoundary": 148
},
{
"zoneNumber": 1,
"secsInZone": 2462.848,
"zoneLowBoundary": 100
},
{
"zoneNumber": 2,
"secsInZone": 1689.269,
"zoneLowBoundary": 138
},
{
"zoneNumber": 4,
"secsInZone": 0.0,
"zoneLowBoundary": 168
},
{
"zoneNumber": 5,
"secsInZone": 0.0,
"zoneLowBoundary": 182
}
]

View File

@@ -0,0 +1,100 @@
{
"activityId": 995784118,
"activityName": "Cournillens (Runkeeper)",
"userProfileId": 2836200,
"isMultiSportParent": false,
"activityTypeDTO": {
"typeId": 12,
"typeKey": "uncategorized",
"parentTypeId": 17,
"sortOrder": 2
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 4,
"typeKey": "groups"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 756265,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 2,
"formatKey": "gpx"
},
"associatedCourseId": null,
"lastUpdateDate": "2016-02-06T17:42:12.0",
"uploadedDate": "2015-12-28T23:18:11.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": false,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {
"showDistance": true,
"showDuration": true,
"showElevation": true,
"showHeartRate": true,
"showMovingDuration": true,
"showMovingSpeed": true,
"showSpeed": true,
"showTimestamp": true
},
"childIds": [],
"sensors": null,
"activityImages": [],
"manufacturer": "",
"diveNumber": null,
"lapCount": 1,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": "0",
"deviceTypePk": 19,
"deviceVersionPk": 756265
},
"gcj02": false,
"favorite": false,
"autoCalcCalories": false,
"elevationCorrected": true,
"personalRecord": false,
"manualActivity": false
},
"summaryDTO": {
"startTimeLocal": "2015-12-27T13:05:44.0",
"startTimeGMT": "2015-12-27T12:05:44.0",
"distance": 9943.03,
"duration": 3620.0,
"movingDuration": 3543.0,
"elapsedDuration": 3620.0,
"elevationGain": 104.05,
"elevationLoss": 108.5,
"maxElevation": 646.57,
"minElevation": 570.99,
"averageSpeed": 2.746692120858901,
"averageMovingSpeed": 2.806385965991877,
"maxSpeed": 7.874701976886471,
"averageHR": 149.0,
"maxHR": 182.0
}
}

View File

@@ -0,0 +1,153 @@
{
"activityId": 2958378924,
"activityName": "Biel 🏛 Pavillon",
"userProfileId": 2836200,
"isMultiSportParent": false,
"activityTypeDTO": {
"typeId": 1,
"typeKey": "running",
"parentTypeId": 17,
"sortOrder": 3
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 3,
"typeKey": "subscribers"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 856399,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 7,
"formatKey": "fit"
},
"associatedCourseId": null,
"lastUpdateDate": "2018-08-24T05:54:31.0",
"uploadedDate": "2018-08-24T05:38:55.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": true,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {
"showAirTemperature": true,
"showDistance": true,
"showDuration": true,
"showElevation": true,
"showHeartRate": true,
"showMovingDuration": true,
"showMovingSpeed": true,
"showRunCadence": true,
"showSpeed": true,
"showTimestamp": true
},
"childIds": [],
"sensors": [
{
"sku": "006-B2697-00",
"sourceType": "LOCAL",
"softwareVersion": 10.0
},
{
"sku": "006-B2697-00",
"sourceType": "LOCAL",
"localDeviceType": "BAROMETER",
"softwareVersion": 10.0
},
{
"sku": "006-B1621-00",
"sourceType": "LOCAL",
"localDeviceType": "GPS",
"softwareVersion": 4.4
},
{
"sourceType": "LOCAL",
"localDeviceType": "ACCELEROMETER",
"softwareVersion": 0.0
},
{
"sku": "006-B0000-00",
"sourceType": "LOCAL",
"localDeviceType": "BLUETOOTH_LOW_ENERGY_CHIPSET",
"softwareVersion": 606.72
},
{
"sourceType": "LOCAL",
"localDeviceType": "WHR",
"softwareVersion": 3.31
}
],
"activityImages": [],
"manufacturer": "GARMIN",
"diveNumber": null,
"lapCount": 5,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": "3946806421",
"deviceTypePk": 34236,
"deviceVersionPk": 856399
},
"gcj02": false,
"autoCalcCalories": false,
"elevationCorrected": false,
"favorite": false,
"manualActivity": false,
"personalRecord": false
},
"summaryDTO": {
"startTimeLocal": "2018-08-24T12:01:50.0",
"startTimeGMT": "2018-08-24T10:01:50.0",
"startLatitude": 47.13532981462777,
"startLongitude": 7.243065973743796,
"distance": 4146.45,
"duration": 2147.244,
"movingDuration": 1844.0,
"elapsedDuration": 2147.244,
"elevationGain": 101.0,
"elevationLoss": 99.0,
"maxElevation": 545.6,
"minElevation": 444.2,
"averageSpeed": 1.9309999942779543,
"averageMovingSpeed": 2.2486172425772777,
"maxSpeed": 3.6579999923706055,
"calories": 357.0388685495535,
"averageHR": 132.0,
"maxHR": 160.0,
"averageRunCadence": 124.03125,
"maxRunCadence": 187.0,
"averageTemperature": 26.007921714818266,
"maxTemperature": 29.0,
"minTemperature": 24.0,
"strideLength": 92.05550090389445,
"trainingEffect": 2.4000000953674316,
"anaerobicTrainingEffect": 0.10000000149011612,
"aerobicTrainingEffectMessage": "MAINTAINING_AEROBIC_FITNESS_1",
"anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0",
"endLatitude": 47.133489567786455,
"endLongitude": 7.231966909021139,
"maxVerticalSpeed": 0.600006103515625
},
"locationName": "Biel/Bienne"
}

View File

@@ -0,0 +1,118 @@
{
"activityId": 6588349076,
"activityUUID": {
"uuid": "925e94a1-1044-463d-98ec-5dfc631b34ee"
},
"activityName": "Bike-Walk-Bike - Gehen",
"userProfileId": 2836200,
"parentId": 6588349056,
"isMultiSportParent": false,
"activityTypeDTO": {
"typeId": 9,
"typeKey": "walking",
"parentTypeId": 17,
"sortOrder": 27,
"isHidden": false,
"restricted": false
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 3,
"typeKey": "subscribers"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 880836,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 7,
"formatKey": "fit"
},
"associatedCourseId": null,
"lastUpdateDate": "2021-04-11T13:48:04.0",
"uploadedDate": "2021-04-11T12:59:56.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": true,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {},
"childIds": [],
"childActivityTypes": [],
"sensors": [],
"activityImages": [],
"manufacturer": "GARMIN",
"diveNumber": null,
"lapCount": 3,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": "3946806421",
"deviceTypePk": 34236,
"deviceVersionPk": 880836
},
"hasIntensityIntervals": false,
"hasSplits": false,
"manualActivity": false,
"autoCalcCalories": false,
"favorite": false,
"trimmed": false,
"personalRecord": false,
"gcj02": false,
"elevationCorrected": false
},
"summaryDTO": {
"startTimeLocal": "2021-04-11T12:36:16.0",
"startTimeGMT": "2021-04-11T10:36:16.0",
"startLatitude": 46.70255539007485,
"startLongitude": 7.202448779717088,
"distance": 4036.26,
"duration": 4375.461,
"movingDuration": 4020.0,
"elapsedDuration": 5332.783,
"elevationGain": 162.0,
"elevationLoss": 160.0,
"maxElevation": 1457.8,
"minElevation": 1362.2,
"averageSpeed": 0.921999990940094,
"averageMovingSpeed": 1.004044778548663,
"maxSpeed": 1.5399999618530273,
"calories": 385.0,
"averageHR": 125.0,
"maxHR": 152.0,
"averageRunCadence": 67.65625,
"maxRunCadence": 176.0,
"averageTemperature": 21.299496217983616,
"maxTemperature": 24.0,
"minTemperature": 17.0,
"trainingEffect": 3.4000000953674316,
"anaerobicTrainingEffect": 1.600000023841858,
"aerobicTrainingEffectMessage": "IMPROVING_LACTATE_THRESHOLD_12",
"anaerobicTrainingEffectMessage": "MINOR_ANAEROBIC_BENEFIT_15",
"endLatitude": 46.69704956933856,
"endLongitude": 7.196000078693032,
"maxVerticalSpeed": 0.5999755859375,
"minActivityLapDuration": 663.623
},
"locationName": "Plasselb"
}

View File

@@ -0,0 +1,112 @@
{
"activityId": 6588349056,
"activityUUID": {
"uuid": "35ac0d3f-e43a-40c1-88de-c9c664998afd"
},
"activityName": "Bike-Walk-Bike",
"userProfileId": 2836200,
"isMultiSportParent": true,
"activityTypeDTO": {
"typeId": 89,
"typeKey": "multi_sport",
"parentTypeId": 17,
"sortOrder": 58,
"isHidden": false,
"restricted": false
},
"eventTypeDTO": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"accessControlRuleDTO": {
"typeId": 3,
"typeKey": "subscribers"
},
"timeZoneUnitDTO": {
"unitId": 124,
"unitKey": "Europe/Paris",
"factor": 0.0,
"timeZone": "Europe/Paris"
},
"metadataDTO": {
"isOriginal": true,
"deviceApplicationInstallationId": 880836,
"agentApplicationInstallationId": null,
"agentString": null,
"fileFormat": {
"formatId": 7,
"formatKey": "fit"
},
"associatedCourseId": null,
"lastUpdateDate": "2021-04-11T13:48:04.0",
"uploadedDate": "2021-04-11T12:59:56.0",
"videoUrl": null,
"hasPolyline": true,
"hasChartData": true,
"hasHrTimeInZones": false,
"hasPowerTimeInZones": false,
"userInfoDto": {
"userProfilePk": 2836200,
"displayname": "eschep",
"fullname": "Peter Steiner",
"profileImageUrlLarge": null,
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"userPro": false
},
"chartAvailability": {},
"childIds": [
6588349067,
6588349072,
6588349076,
6588349079,
6588349081
],
"childActivityTypes": [
"cycling",
"transition",
"walking",
"transition",
"cycling"
],
"sensors": null,
"activityImages": [],
"manufacturer": "GARMIN",
"diveNumber": null,
"lapCount": 5,
"associatedWorkoutId": null,
"isAtpActivity": null,
"deviceMetaDataDTO": {
"deviceId": "3946806421",
"deviceTypePk": 34236,
"deviceVersionPk": 880836
},
"hasIntensityIntervals": false,
"hasSplits": false,
"manualActivity": false,
"autoCalcCalories": false,
"favorite": false,
"personalRecord": false,
"trimmed": false,
"gcj02": false,
"elevationCorrected": false
},
"summaryDTO": {
"startTimeLocal": "2021-04-11T11:50:49.0",
"startTimeGMT": "2021-04-11T09:50:49.0",
"distance": 38351.41,
"duration": 10226.371,
"elapsedDuration": 11183.693,
"elevationGain": 991.0,
"elevationLoss": 994.0,
"averageSpeed": 3.7502462545896287,
"calories": 1139.0,
"maxHR": 175.0,
"trainingEffect": 3.4000000953674316,
"anaerobicTrainingEffect": 1.600000023841858,
"aerobicTrainingEffectMessage": "IMPROVING_LACTATE_THRESHOLD_12",
"anaerobicTrainingEffectMessage": "MINOR_ANAEROBIC_BENEFIT_15"
},
"locationName": "Plasselb"
}

View File

@@ -0,0 +1,210 @@
{
"activityId": 6588349056,
"activityName": "Bike-Walk-Bike",
"description": null,
"startTimeLocal": "2021-04-11 11:50:49",
"startTimeGMT": "2021-04-11 09:50:49",
"activityType": {
"typeId": 89,
"typeKey": "multi_sport",
"parentTypeId": 17,
"sortOrder": 58,
"isHidden": false,
"restricted": false
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 38351.40899467468,
"duration": 10226.370854377747,
"elapsedDuration": 11183693.120002747,
"movingDuration": null,
"elevationGain": 991.0,
"elevationLoss": 994.0,
"averageSpeed": 3.7502462545896287,
"maxSpeed": null,
"startLatitude": 46.66666666666666,
"startLongitude": 7.111111111111111,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/c957e6a9-adb2-4cdb-8105-bf0739323504-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/1a8b37ca-2cd1-47bf-a191-9326dd26949f-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/5979a7d6-2502-4869-8f57-86a28ab7eab3-2836200.png",
"calories": 1139.0,
"averageHR": null,
"maxHR": 175.0,
"averageRunningCadenceInStepsPerMinute": null,
"maxRunningCadenceInStepsPerMinute": null,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": null,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"activityLikeProfileImageUrls": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_OUTDOOR_USER",
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 3,
"typeKey": "subscribers"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": null,
"sportTypeId": 18,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 3.4000000953674316,
"anaerobicTrainingEffect": 1.600000023841858,
"strokes": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": null,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": null,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": null,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": null,
"maxTemperature": null,
"minElevation": null,
"maxElevation": null,
"avgDoubleCadence": null,
"maxDoubleCadence": null,
"summarizedExerciseSets": null,
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": null
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": null,
"floorsClimbed": null,
"floorsDescended": null,
"manufacturer": "GARMIN",
"diveNumber": null,
"locationName": "Plasselb",
"bottomTime": null,
"lapCount": 5,
"endLatitude": 46.77777777777777,
"endLongitude": 7.222222222222222,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"flow": null,
"grit": null,
"jumpCount": null,
"caloriesEstimated": null,
"caloriesConsumed": null,
"waterEstimated": null,
"waterConsumed": null,
"maxAvgPower_1": null,
"maxAvgPower_2": null,
"maxAvgPower_5": null,
"maxAvgPower_10": null,
"maxAvgPower_20": null,
"maxAvgPower_30": null,
"maxAvgPower_60": null,
"maxAvgPower_120": null,
"maxAvgPower_300": null,
"maxAvgPower_600": null,
"maxAvgPower_1200": null,
"maxAvgPower_1800": null,
"maxAvgPower_3600": null,
"maxAvgPower_7200": null,
"maxAvgPower_18000": null,
"excludeFromPowerCurveReports": null,
"totalSets": null,
"activeSets": null,
"totalReps": null,
"minRespirationRate": null,
"maxRespirationRate": null,
"avgRespirationRate": null,
"trainingEffectLabel": null,
"activityTrainingLoad": null,
"avgFlow": null,
"avgGrit": null,
"minActivityLapDuration": null,
"avgStress": null,
"startStress": null,
"endStress": null,
"differenceStress": null,
"maxStress": null,
"aerobicTrainingEffectMessage": "IMPROVING_LACTATE_THRESHOLD_12",
"anaerobicTrainingEffectMessage": "MINOR_ANAEROBIC_BENEFIT_15",
"splitSummaries": [],
"hasSplits": false,
"hasSeedFirstbeatProfile": null,
"favorite": false,
"decoDive": null,
"purposeful": false,
"pr": false,
"autoCalcCalories": false,
"parent": true,
"atpActivity": false,
"manualActivity": false,
"elevationCorrected": false
}

View File

@@ -0,0 +1,123 @@
activity_type_all=All Activities
activity_type_any=Any Activity Type
activity_type_atv=ATV
activity_type_backcountry_skiing_snowboarding=Backcountry Skiing/Snowboarding
activity_type_breathwork=Breathwork
activity_type_bikeToRunTransition=Bike to Run Transition
activity_type_bmx=BMX
activity_type_boating=Boating
activity_type_casual_walking=Casual Walking
activity_type_cross_country_skiing=Cross Country Classic Skiing
cross_country_skiing=Cross Country Skiing
activity_type_cycling=Cycling
activity_type_cyclocross=Cyclocross
activity_type_downhill_biking=Downhill Biking
activity_type_driving_general=Driving
activity_type_elliptical=Elliptical
activity_type_fitness_equipment=Gym & Fitness Equipment
activity_type_flying=Flying
activity_type_golf=Golf
activity_type_gravel_cycling=Gravel/Unpaved Cycling
activity_type_hang_gliding=Hang Gliding
activity_type_hiking=Hiking
activity_type_horseback_riding=Horseback Riding
activity_type_hunting_fishing=Hunting/Fishing
activity_type_indoor_cardio=Cardio
activity_type_indoor_cycling=Indoor Cycling
activity_type_indoor_rowing=Indoor Rowing
activity_type_inline_skating=Inline Skating
activity_type_lap_swimming=Pool Swimming
activity_type_motocross=Motocross
activity_type_motorcycling=Motorcycling
activity_type_mountain_biking=Mountain Biking
activity_type_mountaineering=Mountaineering
activity_type_multi_sport=Multisport
activity_type_open_water_swimming=Open Water Swimming
open_water_swimming=Swim
activity_type_other=Other
activity_type_paddling=Paddling
activity_type_rc_drone=RC/Drone
activity_type_recumbent_cycling=Recumbent Cycling
activity_type_resort_skiing_snowboarding=Resort Skiing/Snowboarding
activity_type_road_biking=Road Cycling
activity_type_road_cycling=Road Cycling
activity_type_rock_climbing=Rock Climbing
activity_type_rowing=Rowing
activity_type_runToBikeTransition=Run to Bike Transition
activity_type_running=Running
activity_type_sailing=Sailing
activity_type_skate_skiing=Cross Country Skate Skiing
activity_type_skating=Skating
activity_type_sky_diving=Sky Diving
activity_type_snow_shoe=Snowshoeing
activity_type_snowmobiling=Snowmobiling
activity_type_speed_walking=Speed Walking
activity_type_stair_climbing=Stair Stepper
activity_type_stand_up_paddleboarding=Stand Up Paddleboarding
activity_type_step_tracking_and_walking=Step Tracking and Walking
activity_type_steps=Steps
activity_type_street_running=Street Running
activity_type_strength_training=Strength Training
activity_type_surfing=Surfing
activity_type_swimToBikeTransition=Swim to Bike Transition
activity_type_swimming=Swimming
activity_type_tennis=Tennis
activity_type_track_cycling=Track Cycling
activity_type_track_running=Track Running
activity_type_trail_running=Trail Running
activity_type_transition=Transition
activity_type_treadmill_running=Treadmill Running
activity_type_treadmill=Treadmill
activity_type_indoor_track=Indoor Track
activity_type_indoor_bike=Bike Indoor
activity_type_indoor_walk=Walk Indoor
activity_type_triathlon=Triathlon
activity_type_uncategorized=Uncategorized
activity_type_wakeboarding=Wakeboarding
activity_type_walking=Walking
activity_type_whitewater_rafting_kayaking=Whitewater Kayaking/Rafting
activity_type_wind_kite_surfing=Wind/Kite Surfing
activity_type_wingsuit_flying=Wingsuit Flying
activity_type_yoga=Yoga
activity_type_toe_to_toe=Toe-to-Toe&trade;
activity_type_toe_to_toe_no_tm=Toe-to-Toe
activity_type_floor_climbing=Floor Climbing
activity_type_emergency=Emergency
activity_type_safety=Safety
activity_type_safety_event=Safety Event
activity_type_incident_detected=Incident Detected
select_one=Select one...
any_activity_type=Any Activity Type
uncategorized=Uncategorized
calories_burned=Calories Burned
activity_type_cardio_training=Cardio Training
activity_type_diving=Diving
activity_type_multi_gas_diving=Multi-Gas Dive
activity_type_single_gas_diving=Single-Gas Dive
activity_type_apnea_diving=Apnea
activity_type_gauge_diving=Gauge Dive
activity_type_apnea_hunting=Apnea Hunt
activity_type_ccr_diving=CCR Dive
activity_type_obstacle_run=Obstacle Running
activity_type_virtual_run=Virtual Running
activity_type_virtual_ride=Virtual Cycling
activity_type_stop_watch=Stopwatch
activity_type_indoor_running=Indoor Running
activity_type_indoor_walking=Indoor Walking
activity_type_pilates=Pilates
activity_type_auto_racing=Auto Racing
activity_type_winter_sports=Winter Sports
activity_type_backcountry_skiing_snowboarding_ws=Backcountry Skiing/Snowboarding
activity_type_cross_country_skiing_ws=Cross Country Classic Skiing
activity_type_resort_skiing_snowboarding_ws=Resort Skiing/Snowboarding
activity_type_skate_skiing_ws=Cross Country Skate Skiing
activity_type_skating_ws=Skating
activity_type_snow_shoe_ws=Snowshoeing
activity_type_snowmobiling_ws=Snowmobiling
activity_type_indoor_climbing=Indoor Climbing
activity_type_bouldering=Bouldering
activity_type_offshore_grinding=Offshore Grinding
activity_type_onshore_grinding=Onshore Grinding
activity_type_ultra_run=Ultra Running
activity_type_hiit=HIIT
activity_type_e_sport=Esports

View File

@@ -0,0 +1,165 @@
[
{
"activityId": 2541953812,
"activityName": "Biel 🏛 Pavillon",
"description": null,
"startTimeLocal": "2018-03-08 12:23:22",
"startTimeGMT": "2018-03-08 11:23:22",
"activityType": {
"typeId": 81,
"typeKey": "cross_country_skiing",
"parentTypeId": 4,
"sortOrder": 39
},
"eventType": {
"typeId": 9,
"typeKey": "uncategorized",
"sortOrder": 10
},
"comments": null,
"parentId": null,
"distance": 8225.5302734375,
"duration": 2627.3798828125,
"elapsedDuration": 2627379.8828125,
"movingDuration": 2614.0,
"elevationGain": 106.0,
"elevationLoss": 73.0,
"averageSpeed": 3.13100004196167,
"maxSpeed": 10.51200008392334,
"startLatitude": 46.46675166673958,
"startLongitude": 8.243478052318096,
"hasPolyline": true,
"ownerId": 2836200,
"ownerDisplayName": "eschep",
"ownerFullName": "Peter Steiner",
"ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/773876c5-f1fe-4f94-9acd-991eeeb69c24-2836200.png",
"ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/92900e93-d959-4a73-bab0-6d18a21b6f76-2836200.png",
"ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/eea51d41-c67c-437c-a4c9-dc76f637fe68-2836200.png",
"ownerProfilePk": null,
"calories": 319.0,
"averageHR": 110.0,
"maxHR": 146.0,
"averageRunningCadenceInStepsPerMinute": 34.765625,
"maxRunningCadenceInStepsPerMinute": 220.0,
"averageBikingCadenceInRevPerMinute": null,
"maxBikingCadenceInRevPerMinute": null,
"averageSwimCadenceInStrokesPerMinute": null,
"maxSwimCadenceInStrokesPerMinute": null,
"averageSwolf": null,
"activeLengths": null,
"steps": 3522,
"conversationUuid": null,
"conversationPk": null,
"numberOfActivityLikes": null,
"numberOfActivityComments": null,
"likedByUser": null,
"commentedByUser": null,
"activityLikeDisplayNames": null,
"activityLikeFullNames": null,
"requestorRelationship": null,
"userRoles": [
"ROLE_CONNECTUSER",
"ROLE_FITNESS_USER",
"ROLE_WELLNESS_USER",
"ROLE_OUTDOOR_USER",
"ROLE_CONNECT_2_USER"
],
"privacy": {
"typeId": 3,
"typeKey": "subscribers"
},
"userPro": false,
"courseId": null,
"poolLength": null,
"unitOfPoolLength": null,
"hasVideo": false,
"videoUrl": null,
"timeZoneId": 124,
"beginTimestamp": 1520508202000,
"sportTypeId": 0,
"avgPower": null,
"maxPower": null,
"aerobicTrainingEffect": 1.399999976158142,
"anaerobicTrainingEffect": 0.10000000149011612,
"strokes": null,
"avgEfficiency": null,
"minEfficiency": null,
"normPower": null,
"leftBalance": null,
"rightBalance": null,
"avgLeftBalance": null,
"max20MinPower": null,
"avgVerticalOscillation": null,
"avgGroundContactTime": null,
"avgStrideLength": 615.1658983791259,
"avgFractionalCadence": null,
"maxFractionalCadence": null,
"trainingStressScore": null,
"intensityFactor": null,
"vO2MaxValue": null,
"avgVerticalRatio": null,
"avgGroundContactBalance": null,
"lactateThresholdBpm": null,
"lactateThresholdSpeed": null,
"maxFtp": null,
"avgStrokeDistance": null,
"avgStrokeCadence": null,
"maxStrokeCadence": null,
"workoutId": null,
"avgStrokes": null,
"minStrokes": null,
"deviceId": 3946806421,
"minTemperature": 21.0,
"maxTemperature": null,
"minElevation": 132600.0,
"maxElevation": 137480.0048828125,
"avgDoubleCadence": null,
"maxDoubleCadence": 220.0,
"summarizedExerciseSets": [],
"maxDepth": null,
"avgDepth": null,
"surfaceInterval": null,
"startN2": null,
"endN2": null,
"startCns": null,
"endCns": null,
"summarizedDiveInfo": {
"weight": null,
"weightUnit": null,
"visibility": null,
"visibilityUnit": null,
"surfaceCondition": null,
"current": null,
"waterType": null,
"waterDensity": null,
"summarizedDiveGases": [],
"totalSurfaceTime": 0
},
"activityLikeAuthors": null,
"avgVerticalSpeed": null,
"maxVerticalSpeed": 0.5999755859375,
"floorsClimbed": null,
"floorsDescended": null,
"diveNumber": null,
"locationName": "Goms",
"bottomTime": null,
"lapCount": 9,
"endLatitude": 46.469942070543766,
"endLongitude": 8.248067228123546,
"minAirSpeed": null,
"maxAirSpeed": null,
"avgAirSpeed": null,
"avgWindYawAngle": null,
"minCda": null,
"maxCda": null,
"avgCda": null,
"avgWattsPerCda": null,
"favorite": false,
"decoDive": null,
"pr": false,
"autoCalcCalories": false,
"parent": false,
"elevationCorrected": false,
"purposeful": false
}
]

View File

@@ -0,0 +1,35 @@
{
"applicationKey" : "fenix5",
"partNumber" : "006-B2697-00",
"productDisplayName" : "fēnix 5",
"productSku" : "010-01688-00",
"imageUrl" : "https://static.garmincdn.com/com.garmin.connect/content/images/device-images/fenix-5.png",
"deviceEmbedVideoLink" : null,
"deviceVideoPageLink" : null,
"wifi" : false,
"bluetoothClassicDevice" : false,
"bluetoothLowEnergyDevice" : true,
"wellness" : false,
"wasp" : false,
"primary" : true,
"minGCMiOSVersion" : 200,
"minGCMAndroidVersion" : 1400,
"minGCMWindowsVersion" : 0,
"hybrid" : true,
"appSupport" : false,
"weightScale" : false,
"hasOpticalHeartRate" : true,
"hasSecondaryUsers" : false,
"unitId" : null,
"highlighted" : false,
"displayOrder" : null,
"bestInClassVideoLink" : null,
"deviceSettingsFile" : null,
"deviceCategories" : [ ],
"versionMajor" : "10",
"versionMinor" : "0",
"buildMajor" : "0",
"buildMinor" : "0",
"versionString" : "10.0.0.0",
"released" : true
}

View File

@@ -0,0 +1,35 @@
{
"applicationKey" : "fenix5",
"partNumber" : "006-B2697-00",
"productDisplayName" : "fēnix 5",
"productSku" : "010-01688-00",
"imageUrl" : "https://static.garmincdn.com/com.garmin.connect/content/images/device-images/fenix-5.png",
"deviceEmbedVideoLink" : null,
"deviceVideoPageLink" : null,
"wifi" : false,
"bluetoothClassicDevice" : false,
"bluetoothLowEnergyDevice" : true,
"wellness" : false,
"wasp" : false,
"primary" : true,
"minGCMiOSVersion" : 200,
"minGCMAndroidVersion" : 1400,
"minGCMWindowsVersion" : 0,
"hybrid" : true,
"appSupport" : false,
"weightScale" : false,
"hasOpticalHeartRate" : true,
"hasSecondaryUsers" : false,
"unitId" : 3946806421,
"highlighted" : false,
"displayOrder" : null,
"bestInClassVideoLink" : null,
"deviceSettingsFile" : null,
"deviceCategories" : [ ],
"versionMajor" : "8",
"versionMinor" : "0",
"buildMajor" : "0",
"buildMinor" : "0",
"versionString" : "8.0.0.0",
"released" : true
}

View File

@@ -0,0 +1,7 @@
all=Any Event Type
geocaching=Geocaching
race=Race
specialEvent=Special Event
training=Training
transportation=Transportation
uncategorized=Uncategorized

View File

@@ -0,0 +1,26 @@
{
"userProfileId": 2836200,
"statisticsStartDate": null,
"statisticsEndDate": null,
"userMetrics": [
{
"activityType": {
"typeId": 17,
"typeKey": "all",
"parentTypeId": 0,
"sortOrder": 1
},
"parentActivityType": {
"typeId": 17,
"typeKey": "all",
"parentTypeId": 0,
"sortOrder": 1
},
"totalActivities": 1028,
"totalDistance": 123.9,
"totalDuration": 123.724,
"totalCalories": 123.0,
"totalElevationGain": 123.51
}
]
}