Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for getting gear attached to an activity #99

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ Supported export formats:
any time). Only included since it _may_ contain additional data that could be
useful for developers of analysis tools.</sub>

- `gear`: gear used in an activity (JSON list).

<sub>Provides a list of the gear that's added to an activity (such as tracking
road versus mountain versus gravel bikes or different pairs of running shoes).
Seems to lack a formal schema and should not be counted on as a stable data
format (may change at any time). Only included since it _may_ contain additional
data that could be useful for developers of analysis tools.</sub>

All files are written to the same directory (`activities/` by default). Each
activity file is prefixed by its upload timestamp and its activity id.

Expand Down
17 changes: 16 additions & 1 deletion garminexport/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@

log = logging.getLogger(__name__)

supported_export_formats = ["json_summary", "json_details", "gpx", "tcx", "fit"]
supported_export_formats = [
"json_summary",
"json_details",
"gear",
"gpx",
"tcx",
"fit",
]
"""The range of supported export formats for activities."""

format_suffix = {
"json_summary": "_summary.json",
"json_details": "_details.json",
"gear": "_gear.json",
"gpx": ".gpx",
"tcx": ".tcx",
"fit": ".fit"
Expand Down Expand Up @@ -132,6 +140,13 @@ def download(client, activity, retryer, backup_dir, export_formats=None):
with codecs.open(dest, encoding="utf-8", mode="w") as f:
f.write(json.dumps(activity_details, ensure_ascii=False, indent=4))

if 'gear' in export_formats:
log.debug('getting gear for %s', id)
activity_gear = retryer.call(client.get_activity_gear, id)
dest = os.path.join(backup_dir, export_filename(activity, 'gear'))
with codecs.open(dest, encoding='utf-8', mode='w') as f:
f.write(json.dumps(activity_gear, ensure_ascii=False, indent=4))

not_found_path = os.path.join(backup_dir, not_found_file)
with open(not_found_path, mode="a") as not_found:
if 'gpx' in export_formats:
Expand Down
23 changes: 23 additions & 0 deletions garminexport/garminclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,29 @@ def get_activity_tcx(self, activity_id):
activity_id, response.status_code, response.text))
return response.text

@require_session
def get_activity_gear(self, activity_id):
"""Return a list of JSON objects describing the gear used in an activity,
if any. If there is no gear attached, the result will be an empty list.

:param activity_id: Activity identifier.
:type activity_id: int
:returns: The JSON object describing the gear or ``None`` if there is
no gear attached
:rtype list
"""
response = self.session.get(
f'https://connect.garmin.com/gear-service/gear/filterGear?activityId={activity_id}',
)
if response.status_code == 400:
return None
if response.status_code != 200:
raise Exception(
f'failed to fetch gear for activity {activity_id}: {response.status_code}\n'
f'{response.text}'
)
return response.json()

def get_original_activity(self, activity_id):
"""Return the original file that was uploaded for an activity.
If the activity doesn't have any file source (for example,
Expand Down