%global _empty_manifest_terminate_build 0 Name: python-garminconnect Version: 0.1.55 Release: 1 Summary: Python 3 API wrapper for Garmin Connect License: MIT license URL: https://github.com/cyberjunky/python-garminconnect Source0: https://mirrors.aliyun.com/pypi/web/packages/87/7f/ff45ac4ed757230bc7945e06c6dfc0f3598ce08d1c431914d58da712d33e/garminconnect-0.1.55.tar.gz BuildArch: noarch %description [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) # Python: Garmin Connect Python 3 API wrapper for Garmin Connect to get your statistics. ## About This package allows you to request garmin device, activity and health data from your Garmin Connect account. See ## Installation ```bash pip3 install garminconnect ``` ## API Demo Program I wrote this for testing and playing with all available/known API calls. If you run it from the python-garmin connect directory it will use the library code beneath it, so you can develop without reinstalling the package. The code also demonstrates how to implement session saving and re-using of the cookies. You can set environment variables with your credentials like so, this is optional: ```bash export EMAIL= export PASSWORD= ``` Install the pre-requisites for the example program (not all are needed for using the library package): ```bash pip3 install cloudscraper readchar requests pwinput ``` Or you can just run the program and enter your credentials when asked, it will create and save a session file and use that until it's outdated/invalid. ``` python3 ./example.py *** Garmin Connect API Demo by cyberjunky *** 1 -- Get full name 2 -- Get unit system 3 -- Get activity data for '2023-03-10' 4 -- Get activity data for '2023-03-10' (compatible with garminconnect-ha) 5 -- Get body composition data for '2023-03-10' (compatible with garminconnect-ha) 6 -- Get body composition data for from '2023-03-03' to '2023-03-10' (to be compatible with garminconnect-ha) 7 -- Get stats and body composition data for '2023-03-10' 8 -- Get steps data for '2023-03-10' 9 -- Get heart rate data for '2023-03-10' 0 -- Get training readiness data for '2023-03-10' - -- Get daily step data for '2023-03-03' to '2023-03-10' / -- Get body battery data for '2023-03-03' to '2023-03-10' ! -- Get floors data for '2023-03-03' ? -- Get blood pressure data for '2023-03-03' to '2023-03-10' . -- Get training status data for '2023-03-10' a -- Get resting heart rate data for 2023-03-10' b -- Get hydration data for '2023-03-10' c -- Get sleep data for '2023-03-10' d -- Get stress data for '2023-03-10' e -- Get respiration data for '2023-03-10' f -- Get SpO2 data for '2023-03-10' g -- Get max metric data (like vo2MaxValue and fitnessAge) for '2023-03-10' h -- Get personal record for user i -- Get earned badges for user j -- Get adhoc challenges data from start '0' and limit '100' k -- Get available badge challenges data from '1' and limit '100' l -- Get badge challenges data from '1' and limit '100' m -- Get non completed badge challenges data from '1' and limit '100' n -- Get activities data from start '0' and limit '100' o -- Get last activity p -- Download activities data by date from '2023-03-03' to '2023-03-10' r -- Get all kinds of activities data from '0' s -- Upload activity data from file 'MY_ACTIVITY.fit' t -- Get all kinds of Garmin device info u -- Get active goals v -- Get future goals w -- Get past goals y -- Get all Garmin device alarms x -- Get Heart Rate Variability data (HRV) for '2023-03-10' z -- Get progress summary from '2023-03-03' to '2023-03-10' for all metrics A -- Get gear, the defaults, activity types and statistics Z -- Logout Garmin Connect portal q -- Exit Make your selection: ``` This is some example code, and probably older than the latest code which can be found in 'example.py'. ```python #!/usr/bin/env python3 """ pip3 install cloudscraper requests readchar pwinput export EMAIL= export PASSWORD= """ import datetime import json import logging import os import sys import requests import pwinput import readchar from garminconnect import ( Garmin, GarminConnectAuthenticationError, GarminConnectConnectionError, GarminConnectTooManyRequestsError, ) # Configure debug logging # logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Load environment variables if defined email = os.getenv("EMAIL") password = os.getenv("PASSWORD") api = None # Example selections and settings today = datetime.date.today() startdate = today - datetime.timedelta(days=7) # Select past week start = 0 limit = 100 start_badge = 1 # Badge related calls calls start counting at 1 activitytype = "" # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activityfile = "MY_ACTIVITY.fit" # Supported file types are: .fit .gpx .tcx menu_options = { "1": "Get full name", "2": "Get unit system", "3": f"Get activity data for '{today.isoformat()}'", "4": f"Get activity data for '{today.isoformat()}' (compatible with garminconnect-ha)", "5": f"Get body composition data for '{today.isoformat()}' (compatible with garminconnect-ha)", "6": f"Get body composition data for from '{startdate.isoformat()}' to '{today.isoformat()}' (to be compatible with garminconnect-ha)", "7": f"Get stats and body composition data for '{today.isoformat()}'", "8": f"Get steps data for '{today.isoformat()}'", "9": f"Get heart rate data for '{today.isoformat()}'", "0": f"Get training readiness data for '{today.isoformat()}'", "-": f"Get daily step data for '{startdate.isoformat()}' to '{today.isoformat()}'", "/": f"Get body battery data for '{startdate.isoformat()}' to '{today.isoformat()}'", "!": f"Get floors data for '{startdate.isoformat()}'", "?": f"Get blood pressure data for '{startdate.isoformat()}' to '{today.isoformat()}'", ".": f"Get training status data for '{today.isoformat()}'", "a": f"Get resting heart rate data for {today.isoformat()}'", "b": f"Get hydration data for '{today.isoformat()}'", "c": f"Get sleep data for '{today.isoformat()}'", "d": f"Get stress data for '{today.isoformat()}'", "e": f"Get respiration data for '{today.isoformat()}'", "f": f"Get SpO2 data for '{today.isoformat()}'", "g": f"Get max metric data (like vo2MaxValue and fitnessAge) for '{today.isoformat()}'", "h": "Get personal record for user", "i": "Get earned badges for user", "j": f"Get adhoc challenges data from start '{start}' and limit '{limit}'", "k": f"Get available badge challenges data from '{start_badge}' and limit '{limit}'", "l": f"Get badge challenges data from '{start_badge}' and limit '{limit}'", "m": f"Get non completed badge challenges data from '{start_badge}' and limit '{limit}'", "n": f"Get activities data from start '{start}' and limit '{limit}'", "o": "Get last activity", "p": f"Download activities data by date from '{startdate.isoformat()}' to '{today.isoformat()}'", "r": f"Get all kinds of activities data from '{start}'", "s": f"Upload activity data from file '{activityfile}'", "t": "Get all kinds of Garmin device info", "u": "Get active goals", "v": "Get future goals", "w": "Get past goals", "y": "Get all Garmin device alarms", "x": f"Get Heart Rate Variability data (HRV) for '{today.isoformat()}'", "z": f"Get progress summary from '{startdate.isoformat()}' to '{today.isoformat()}' for all metrics", "A": "Get gear, the defaults, activity types and statistics", "Z": "Logout Garmin Connect portal", "q": "Exit", } def display_json(api_call, output): """Format API output for better readability.""" dashed = "-"*20 header = f"{dashed} {api_call} {dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def display_text(output): """Format API output for better readability.""" dashed = "-"*60 header = f"{dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def get_credentials(): """Get user credentials.""" email = input("Login e-mail: ") password = pwinput.pwinput(prompt='Password: ') return email, password def init_api(email, password): """Initialize Garmin API with your credentials.""" try: ## Try to load the previous session with open("session.json") as f: saved_session = json.load(f) print( "Login to Garmin Connect using session loaded from 'session.json'...\n" ) # Use the loaded session for initializing the API (without need for credentials) api = Garmin(session_data=saved_session) # Login using the api.login() except (FileNotFoundError, GarminConnectAuthenticationError): # Login to Garmin Connect portal with credentials since session is invalid or not present. print( "Session file not present or turned invalid, login with your Garmin Connect credentials.\n" "NOTE: Credentials will not be stored, the session cookies will be stored in 'session.json' for future use.\n" ) try: # Ask for credentials if not set as environment variables if not email or not password: email, password = get_credentials() api = Garmin(email, password) api.login() # Save session dictionary to json file for future use with open("session.json", "w", encoding="utf-8") as f: json.dump(api.session_data, f, ensure_ascii=False, indent=4) except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred during Garmin Connect communication: %s", err) return None return api def print_menu(): """Print examples menu.""" for key in menu_options.keys(): print(f"{key} -- {menu_options[key]}") print("Make your selection: ", end="", flush=True) def switch(api, i): """Run selected API call.""" # Exit example program if i == "q": print("Bye!") sys.exit() # Skip requests if login failed if api: try: print(f"\n\nExecuting: {menu_options[i]}\n") # USER BASICS if i == "1": # Get full name from profile display_json("api.get_full_name()", api.get_full_name()) elif i == "2": # Get unit system from profile display_json("api.get_unit_system()", api.get_unit_system()) # USER STATISTIC SUMMARIES elif i == "3": # Get activity data for 'YYYY-MM-DD' display_json(f"api.get_stats('{today.isoformat()}')", api.get_stats(today.isoformat())) elif i == "4": # Get activity data (to be compatible with garminconnect-ha) display_json(f"api.get_user_summary('{today.isoformat()}')", api.get_user_summary(today.isoformat())) elif i == "5": # Get body composition data for 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{today.isoformat()}')", api.get_body_composition(today.isoformat())) elif i == "6": # Get body composition data for multiple days 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{startdate.isoformat()}', '{today.isoformat()}')", api.get_body_composition(startdate.isoformat(), today.isoformat()) ) elif i == "7": # Get stats and body composition data for 'YYYY-MM-DD' display_json(f"api.get_stats_and_body('{today.isoformat()}')", api.get_stats_and_body(today.isoformat())) # USER STATISTICS LOGGED elif i == "8": # Get steps data for 'YYYY-MM-DD' display_json(f"api.get_steps_data('{today.isoformat()}')", api.get_steps_data(today.isoformat())) elif i == "9": # Get heart rate data for 'YYYY-MM-DD' display_json(f"api.get_heart_rates('{today.isoformat()}')", api.get_heart_rates(today.isoformat())) elif i == "0": # Get training readiness data for 'YYYY-MM-DD' display_json(f"api.get_training_readiness('{today.isoformat()}')", api.get_training_readiness(today.isoformat())) elif i == "/": # Get daily body battery data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_body_battery('{startdate.isoformat()}, {today.isoformat()}')", api.get_body_battery(startdate.isoformat(), today.isoformat())) elif i == "?": # Get daily blood pressure data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_blood_pressure('{startdate.isoformat()}, {today.isoformat()}')", api.get_blood_pressure(startdate.isoformat(), today.isoformat())) elif i == "-": # Get daily step data for 'YYYY-MM-DD' display_json(f"api.get_daily_steps('{startdate.isoformat()}, {today.isoformat()}')", api.get_daily_steps(startdate.isoformat(), today.isoformat())) elif i == "!": # Get daily floors data for 'YYYY-MM-DD' display_json(f"api.get_floors('{today.isoformat()}')", api.get_floors(today.isoformat())) elif i == ".": # Get training status data for 'YYYY-MM-DD' display_json(f"api.get_training_status('{today.isoformat()}')", api.get_training_status(today.isoformat())) elif i == "a": # Get resting heart rate data for 'YYYY-MM-DD' display_json(f"api.get_rhr_day('{today.isoformat()}')", api.get_rhr_day(today.isoformat())) elif i == "b": # Get hydration data 'YYYY-MM-DD' display_json(f"api.get_hydration_data('{today.isoformat()}')", api.get_hydration_data(today.isoformat())) elif i == "c": # Get sleep data for 'YYYY-MM-DD' display_json(f"api.get_sleep_data('{today.isoformat()}')", api.get_sleep_data(today.isoformat())) elif i == "d": # Get stress data for 'YYYY-MM-DD' display_json(f"api.get_stress_data('{today.isoformat()}')", api.get_stress_data(today.isoformat())) elif i == "e": # Get respiration data for 'YYYY-MM-DD' display_json(f"api.get_respiration_data('{today.isoformat()}')", api.get_respiration_data(today.isoformat())) elif i == "f": # Get SpO2 data for 'YYYY-MM-DD' display_json(f"api.get_spo2_data('{today.isoformat()}')", api.get_spo2_data(today.isoformat())) elif i == "g": # Get max metric data (like vo2MaxValue and fitnessAge) for 'YYYY-MM-DD' display_json(f"api.get_max_metrics('{today.isoformat()}')", api.get_max_metrics(today.isoformat())) elif i == "h": # Get personal record for user display_json("api.get_personal_record()", api.get_personal_record()) elif i == "i": # Get earned badges for user display_json("api.get_earned_badges()", api.get_earned_badges()) elif i == "j": # Get adhoc challenges data from start and limit display_json( f"api.get_adhoc_challenges({start},{limit})", api.get_adhoc_challenges(start, limit) ) # 1=start, 100=limit elif i == "k": # Get available badge challenges data from start and limit display_json( f"api.get_available_badge_challenges({start_badge}, {limit})", api.get_available_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "l": # Get badge challenges data from start and limit display_json( f"api.get_badge_challenges({start_badge}, {limit})", api.get_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "m": # Get non completed badge challenges data from start and limit display_json( f"api.get_non_completed_badge_challenges({start_badge}, {limit})", api.get_non_completed_badge_challenges(start_badge, limit) ) # 1=start, 100=limit # ACTIVITIES elif i == "n": # Get activities data from start and limit display_json(f"api.get_activities({start}, {limit})", api.get_activities(start, limit)) # 0=start, 1=limit elif i == "o": # Get last activity display_json("api.get_last_activity()", api.get_last_activity()) elif i == "p": # Get activities data from startdate 'YYYY-MM-DD' to enddate 'YYYY-MM-DD', with (optional) activitytype # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activities = api.get_activities_by_date( startdate.isoformat(), today.isoformat(), activitytype ) # Download activities for activity in activities: activity_id = activity["activityId"] display_text(activity) print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.GPX)") gpx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.GPX ) output_file = f"./{str(activity_id)}.gpx" with open(output_file, "wb") as fb: fb.write(gpx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.TCX)") tcx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.TCX ) output_file = f"./{str(activity_id)}.tcx" with open(output_file, "wb") as fb: fb.write(tcx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.ORIGINAL)") zip_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.ORIGINAL ) output_file = f"./{str(activity_id)}.zip" with open(output_file, "wb") as fb: fb.write(zip_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.CSV)") csv_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.CSV ) output_file = f"./{str(activity_id)}.csv" with open(output_file, "wb") as fb: fb.write(csv_data) print(f"Activity data downloaded to file {output_file}") elif i == "r": # Get activities data from start and limit activities = api.get_activities(start, limit) # 0=start, 1=limit # Get activity splits first_activity_id = activities[0].get("activityId") display_json(f"api.get_activity_splits({first_activity_id})", api.get_activity_splits(first_activity_id)) # Get activity split summaries for activity id display_json(f"api.get_activity_split_summaries({first_activity_id})", api.get_activity_split_summaries(first_activity_id)) # Get activity weather data for activity display_json(f"api.get_activity_weather({first_activity_id})", api.get_activity_weather(first_activity_id)) # Get activity hr timezones id display_json(f"api.get_activity_hr_in_timezones({first_activity_id})", api.get_activity_hr_in_timezones(first_activity_id)) # Get activity details for activity id display_json(f"api.get_activity_details({first_activity_id})", api.get_activity_details(first_activity_id)) # Get gear data for activity id display_json(f"api.get_activity_gear({first_activity_id})", api.get_activity_gear(first_activity_id)) # Activity self evaluation data for activity id display_json(f"api.get_activity_evaluation({first_activity_id})", api.get_activity_evaluation(first_activity_id)) # Get exercise sets in case the activity is a strength_training if activities[0]["activityType"]["typeKey"] == "strength_training": display_json(f"api.get_activity_exercise_sets({first_activity_id})", api.get_activity_exercise_sets(first_activity_id)) elif i == "s": # Upload activity from file display_json(f"api.upload_activity({activityfile})", api.upload_activity(activityfile)) # DEVICES elif i == "t": # Get Garmin devices devices = api.get_devices() display_json("api.get_devices()", devices) # Get device last used device_last_used = api.get_device_last_used() display_json("api.get_device_last_used()", device_last_used) # Get settings per device for device in devices: device_id = device["deviceId"] display_json(f"api.get_device_settings({device_id})", api.get_device_settings(device_id)) # GOALS elif i == "u": # Get active goals goals = api.get_goals("active") display_json("api.get_goals(\"active\")", goals) elif i == "v": # Get future goals goals = api.get_goals("future") display_json("api.get_goals(\"future\")", goals) elif i == "w": # Get past goals goals = api.get_goals("past") display_json("api.get_goals(\"past\")", goals) # ALARMS elif i == "y": # Get Garmin device alarms alarms = api.get_device_alarms() for alarm in alarms: alarm_id = alarm["alarmId"] display_json(f"api.get_device_alarms({alarm_id})", alarm) elif i == "x": # Get Heart Rate Variability (hrv) data display_json(f"api.get_hrv_data({today.isoformat()})", api.get_hrv_data(today.isoformat())) elif i == "z": # Get progress summary for metric in ["elevationGain", "duration", "distance", "movingDuration"]: display_json( f"api.get_progress_summary_between_dates({today.isoformat()})", api.get_progress_summary_between_dates( startdate.isoformat(), today.isoformat(), metric )) # Gear elif i == "A": last_used_device = api.get_device_last_used() display_json(f"api.get_device_last_used()", last_used_device) userProfileNumber = last_used_device["userProfileNumber"] gear = api.get_gear(userProfileNumber) display_json(f"api.get_gear()", gear) display_json(f"api.get_gear_defaults()", api.get_gear_defaults(userProfileNumber)) display_json(f"api.get()", api.get_activity_types()) for gear in gear: uuid=gear["uuid"] name=gear["displayName"] display_json(f"api.get_gear_stats({uuid}) / {name}", api.get_gear_stats(uuid)) elif i == "Z": # Logout Garmin Connect portal display_json("api.logout()", api.logout()) api = None except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred: %s", err) except KeyError: # Invalid menu option chosen pass else: print("Could not login to Garmin Connect, try again later.") # Main program loop while True: # Display header and login print("\n*** Garmin Connect API Demo by cyberjunky ***\n") # Init API if not api: api = init_api(email, password) # Display menu print_menu() option = readchar.readkey() switch(api, option) ``` ## Donations [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) %package -n python3-garminconnect Summary: Python 3 API wrapper for Garmin Connect Provides: python-garminconnect BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-garminconnect [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) # Python: Garmin Connect Python 3 API wrapper for Garmin Connect to get your statistics. ## About This package allows you to request garmin device, activity and health data from your Garmin Connect account. See ## Installation ```bash pip3 install garminconnect ``` ## API Demo Program I wrote this for testing and playing with all available/known API calls. If you run it from the python-garmin connect directory it will use the library code beneath it, so you can develop without reinstalling the package. The code also demonstrates how to implement session saving and re-using of the cookies. You can set environment variables with your credentials like so, this is optional: ```bash export EMAIL= export PASSWORD= ``` Install the pre-requisites for the example program (not all are needed for using the library package): ```bash pip3 install cloudscraper readchar requests pwinput ``` Or you can just run the program and enter your credentials when asked, it will create and save a session file and use that until it's outdated/invalid. ``` python3 ./example.py *** Garmin Connect API Demo by cyberjunky *** 1 -- Get full name 2 -- Get unit system 3 -- Get activity data for '2023-03-10' 4 -- Get activity data for '2023-03-10' (compatible with garminconnect-ha) 5 -- Get body composition data for '2023-03-10' (compatible with garminconnect-ha) 6 -- Get body composition data for from '2023-03-03' to '2023-03-10' (to be compatible with garminconnect-ha) 7 -- Get stats and body composition data for '2023-03-10' 8 -- Get steps data for '2023-03-10' 9 -- Get heart rate data for '2023-03-10' 0 -- Get training readiness data for '2023-03-10' - -- Get daily step data for '2023-03-03' to '2023-03-10' / -- Get body battery data for '2023-03-03' to '2023-03-10' ! -- Get floors data for '2023-03-03' ? -- Get blood pressure data for '2023-03-03' to '2023-03-10' . -- Get training status data for '2023-03-10' a -- Get resting heart rate data for 2023-03-10' b -- Get hydration data for '2023-03-10' c -- Get sleep data for '2023-03-10' d -- Get stress data for '2023-03-10' e -- Get respiration data for '2023-03-10' f -- Get SpO2 data for '2023-03-10' g -- Get max metric data (like vo2MaxValue and fitnessAge) for '2023-03-10' h -- Get personal record for user i -- Get earned badges for user j -- Get adhoc challenges data from start '0' and limit '100' k -- Get available badge challenges data from '1' and limit '100' l -- Get badge challenges data from '1' and limit '100' m -- Get non completed badge challenges data from '1' and limit '100' n -- Get activities data from start '0' and limit '100' o -- Get last activity p -- Download activities data by date from '2023-03-03' to '2023-03-10' r -- Get all kinds of activities data from '0' s -- Upload activity data from file 'MY_ACTIVITY.fit' t -- Get all kinds of Garmin device info u -- Get active goals v -- Get future goals w -- Get past goals y -- Get all Garmin device alarms x -- Get Heart Rate Variability data (HRV) for '2023-03-10' z -- Get progress summary from '2023-03-03' to '2023-03-10' for all metrics A -- Get gear, the defaults, activity types and statistics Z -- Logout Garmin Connect portal q -- Exit Make your selection: ``` This is some example code, and probably older than the latest code which can be found in 'example.py'. ```python #!/usr/bin/env python3 """ pip3 install cloudscraper requests readchar pwinput export EMAIL= export PASSWORD= """ import datetime import json import logging import os import sys import requests import pwinput import readchar from garminconnect import ( Garmin, GarminConnectAuthenticationError, GarminConnectConnectionError, GarminConnectTooManyRequestsError, ) # Configure debug logging # logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Load environment variables if defined email = os.getenv("EMAIL") password = os.getenv("PASSWORD") api = None # Example selections and settings today = datetime.date.today() startdate = today - datetime.timedelta(days=7) # Select past week start = 0 limit = 100 start_badge = 1 # Badge related calls calls start counting at 1 activitytype = "" # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activityfile = "MY_ACTIVITY.fit" # Supported file types are: .fit .gpx .tcx menu_options = { "1": "Get full name", "2": "Get unit system", "3": f"Get activity data for '{today.isoformat()}'", "4": f"Get activity data for '{today.isoformat()}' (compatible with garminconnect-ha)", "5": f"Get body composition data for '{today.isoformat()}' (compatible with garminconnect-ha)", "6": f"Get body composition data for from '{startdate.isoformat()}' to '{today.isoformat()}' (to be compatible with garminconnect-ha)", "7": f"Get stats and body composition data for '{today.isoformat()}'", "8": f"Get steps data for '{today.isoformat()}'", "9": f"Get heart rate data for '{today.isoformat()}'", "0": f"Get training readiness data for '{today.isoformat()}'", "-": f"Get daily step data for '{startdate.isoformat()}' to '{today.isoformat()}'", "/": f"Get body battery data for '{startdate.isoformat()}' to '{today.isoformat()}'", "!": f"Get floors data for '{startdate.isoformat()}'", "?": f"Get blood pressure data for '{startdate.isoformat()}' to '{today.isoformat()}'", ".": f"Get training status data for '{today.isoformat()}'", "a": f"Get resting heart rate data for {today.isoformat()}'", "b": f"Get hydration data for '{today.isoformat()}'", "c": f"Get sleep data for '{today.isoformat()}'", "d": f"Get stress data for '{today.isoformat()}'", "e": f"Get respiration data for '{today.isoformat()}'", "f": f"Get SpO2 data for '{today.isoformat()}'", "g": f"Get max metric data (like vo2MaxValue and fitnessAge) for '{today.isoformat()}'", "h": "Get personal record for user", "i": "Get earned badges for user", "j": f"Get adhoc challenges data from start '{start}' and limit '{limit}'", "k": f"Get available badge challenges data from '{start_badge}' and limit '{limit}'", "l": f"Get badge challenges data from '{start_badge}' and limit '{limit}'", "m": f"Get non completed badge challenges data from '{start_badge}' and limit '{limit}'", "n": f"Get activities data from start '{start}' and limit '{limit}'", "o": "Get last activity", "p": f"Download activities data by date from '{startdate.isoformat()}' to '{today.isoformat()}'", "r": f"Get all kinds of activities data from '{start}'", "s": f"Upload activity data from file '{activityfile}'", "t": "Get all kinds of Garmin device info", "u": "Get active goals", "v": "Get future goals", "w": "Get past goals", "y": "Get all Garmin device alarms", "x": f"Get Heart Rate Variability data (HRV) for '{today.isoformat()}'", "z": f"Get progress summary from '{startdate.isoformat()}' to '{today.isoformat()}' for all metrics", "A": "Get gear, the defaults, activity types and statistics", "Z": "Logout Garmin Connect portal", "q": "Exit", } def display_json(api_call, output): """Format API output for better readability.""" dashed = "-"*20 header = f"{dashed} {api_call} {dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def display_text(output): """Format API output for better readability.""" dashed = "-"*60 header = f"{dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def get_credentials(): """Get user credentials.""" email = input("Login e-mail: ") password = pwinput.pwinput(prompt='Password: ') return email, password def init_api(email, password): """Initialize Garmin API with your credentials.""" try: ## Try to load the previous session with open("session.json") as f: saved_session = json.load(f) print( "Login to Garmin Connect using session loaded from 'session.json'...\n" ) # Use the loaded session for initializing the API (without need for credentials) api = Garmin(session_data=saved_session) # Login using the api.login() except (FileNotFoundError, GarminConnectAuthenticationError): # Login to Garmin Connect portal with credentials since session is invalid or not present. print( "Session file not present or turned invalid, login with your Garmin Connect credentials.\n" "NOTE: Credentials will not be stored, the session cookies will be stored in 'session.json' for future use.\n" ) try: # Ask for credentials if not set as environment variables if not email or not password: email, password = get_credentials() api = Garmin(email, password) api.login() # Save session dictionary to json file for future use with open("session.json", "w", encoding="utf-8") as f: json.dump(api.session_data, f, ensure_ascii=False, indent=4) except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred during Garmin Connect communication: %s", err) return None return api def print_menu(): """Print examples menu.""" for key in menu_options.keys(): print(f"{key} -- {menu_options[key]}") print("Make your selection: ", end="", flush=True) def switch(api, i): """Run selected API call.""" # Exit example program if i == "q": print("Bye!") sys.exit() # Skip requests if login failed if api: try: print(f"\n\nExecuting: {menu_options[i]}\n") # USER BASICS if i == "1": # Get full name from profile display_json("api.get_full_name()", api.get_full_name()) elif i == "2": # Get unit system from profile display_json("api.get_unit_system()", api.get_unit_system()) # USER STATISTIC SUMMARIES elif i == "3": # Get activity data for 'YYYY-MM-DD' display_json(f"api.get_stats('{today.isoformat()}')", api.get_stats(today.isoformat())) elif i == "4": # Get activity data (to be compatible with garminconnect-ha) display_json(f"api.get_user_summary('{today.isoformat()}')", api.get_user_summary(today.isoformat())) elif i == "5": # Get body composition data for 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{today.isoformat()}')", api.get_body_composition(today.isoformat())) elif i == "6": # Get body composition data for multiple days 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{startdate.isoformat()}', '{today.isoformat()}')", api.get_body_composition(startdate.isoformat(), today.isoformat()) ) elif i == "7": # Get stats and body composition data for 'YYYY-MM-DD' display_json(f"api.get_stats_and_body('{today.isoformat()}')", api.get_stats_and_body(today.isoformat())) # USER STATISTICS LOGGED elif i == "8": # Get steps data for 'YYYY-MM-DD' display_json(f"api.get_steps_data('{today.isoformat()}')", api.get_steps_data(today.isoformat())) elif i == "9": # Get heart rate data for 'YYYY-MM-DD' display_json(f"api.get_heart_rates('{today.isoformat()}')", api.get_heart_rates(today.isoformat())) elif i == "0": # Get training readiness data for 'YYYY-MM-DD' display_json(f"api.get_training_readiness('{today.isoformat()}')", api.get_training_readiness(today.isoformat())) elif i == "/": # Get daily body battery data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_body_battery('{startdate.isoformat()}, {today.isoformat()}')", api.get_body_battery(startdate.isoformat(), today.isoformat())) elif i == "?": # Get daily blood pressure data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_blood_pressure('{startdate.isoformat()}, {today.isoformat()}')", api.get_blood_pressure(startdate.isoformat(), today.isoformat())) elif i == "-": # Get daily step data for 'YYYY-MM-DD' display_json(f"api.get_daily_steps('{startdate.isoformat()}, {today.isoformat()}')", api.get_daily_steps(startdate.isoformat(), today.isoformat())) elif i == "!": # Get daily floors data for 'YYYY-MM-DD' display_json(f"api.get_floors('{today.isoformat()}')", api.get_floors(today.isoformat())) elif i == ".": # Get training status data for 'YYYY-MM-DD' display_json(f"api.get_training_status('{today.isoformat()}')", api.get_training_status(today.isoformat())) elif i == "a": # Get resting heart rate data for 'YYYY-MM-DD' display_json(f"api.get_rhr_day('{today.isoformat()}')", api.get_rhr_day(today.isoformat())) elif i == "b": # Get hydration data 'YYYY-MM-DD' display_json(f"api.get_hydration_data('{today.isoformat()}')", api.get_hydration_data(today.isoformat())) elif i == "c": # Get sleep data for 'YYYY-MM-DD' display_json(f"api.get_sleep_data('{today.isoformat()}')", api.get_sleep_data(today.isoformat())) elif i == "d": # Get stress data for 'YYYY-MM-DD' display_json(f"api.get_stress_data('{today.isoformat()}')", api.get_stress_data(today.isoformat())) elif i == "e": # Get respiration data for 'YYYY-MM-DD' display_json(f"api.get_respiration_data('{today.isoformat()}')", api.get_respiration_data(today.isoformat())) elif i == "f": # Get SpO2 data for 'YYYY-MM-DD' display_json(f"api.get_spo2_data('{today.isoformat()}')", api.get_spo2_data(today.isoformat())) elif i == "g": # Get max metric data (like vo2MaxValue and fitnessAge) for 'YYYY-MM-DD' display_json(f"api.get_max_metrics('{today.isoformat()}')", api.get_max_metrics(today.isoformat())) elif i == "h": # Get personal record for user display_json("api.get_personal_record()", api.get_personal_record()) elif i == "i": # Get earned badges for user display_json("api.get_earned_badges()", api.get_earned_badges()) elif i == "j": # Get adhoc challenges data from start and limit display_json( f"api.get_adhoc_challenges({start},{limit})", api.get_adhoc_challenges(start, limit) ) # 1=start, 100=limit elif i == "k": # Get available badge challenges data from start and limit display_json( f"api.get_available_badge_challenges({start_badge}, {limit})", api.get_available_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "l": # Get badge challenges data from start and limit display_json( f"api.get_badge_challenges({start_badge}, {limit})", api.get_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "m": # Get non completed badge challenges data from start and limit display_json( f"api.get_non_completed_badge_challenges({start_badge}, {limit})", api.get_non_completed_badge_challenges(start_badge, limit) ) # 1=start, 100=limit # ACTIVITIES elif i == "n": # Get activities data from start and limit display_json(f"api.get_activities({start}, {limit})", api.get_activities(start, limit)) # 0=start, 1=limit elif i == "o": # Get last activity display_json("api.get_last_activity()", api.get_last_activity()) elif i == "p": # Get activities data from startdate 'YYYY-MM-DD' to enddate 'YYYY-MM-DD', with (optional) activitytype # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activities = api.get_activities_by_date( startdate.isoformat(), today.isoformat(), activitytype ) # Download activities for activity in activities: activity_id = activity["activityId"] display_text(activity) print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.GPX)") gpx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.GPX ) output_file = f"./{str(activity_id)}.gpx" with open(output_file, "wb") as fb: fb.write(gpx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.TCX)") tcx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.TCX ) output_file = f"./{str(activity_id)}.tcx" with open(output_file, "wb") as fb: fb.write(tcx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.ORIGINAL)") zip_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.ORIGINAL ) output_file = f"./{str(activity_id)}.zip" with open(output_file, "wb") as fb: fb.write(zip_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.CSV)") csv_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.CSV ) output_file = f"./{str(activity_id)}.csv" with open(output_file, "wb") as fb: fb.write(csv_data) print(f"Activity data downloaded to file {output_file}") elif i == "r": # Get activities data from start and limit activities = api.get_activities(start, limit) # 0=start, 1=limit # Get activity splits first_activity_id = activities[0].get("activityId") display_json(f"api.get_activity_splits({first_activity_id})", api.get_activity_splits(first_activity_id)) # Get activity split summaries for activity id display_json(f"api.get_activity_split_summaries({first_activity_id})", api.get_activity_split_summaries(first_activity_id)) # Get activity weather data for activity display_json(f"api.get_activity_weather({first_activity_id})", api.get_activity_weather(first_activity_id)) # Get activity hr timezones id display_json(f"api.get_activity_hr_in_timezones({first_activity_id})", api.get_activity_hr_in_timezones(first_activity_id)) # Get activity details for activity id display_json(f"api.get_activity_details({first_activity_id})", api.get_activity_details(first_activity_id)) # Get gear data for activity id display_json(f"api.get_activity_gear({first_activity_id})", api.get_activity_gear(first_activity_id)) # Activity self evaluation data for activity id display_json(f"api.get_activity_evaluation({first_activity_id})", api.get_activity_evaluation(first_activity_id)) # Get exercise sets in case the activity is a strength_training if activities[0]["activityType"]["typeKey"] == "strength_training": display_json(f"api.get_activity_exercise_sets({first_activity_id})", api.get_activity_exercise_sets(first_activity_id)) elif i == "s": # Upload activity from file display_json(f"api.upload_activity({activityfile})", api.upload_activity(activityfile)) # DEVICES elif i == "t": # Get Garmin devices devices = api.get_devices() display_json("api.get_devices()", devices) # Get device last used device_last_used = api.get_device_last_used() display_json("api.get_device_last_used()", device_last_used) # Get settings per device for device in devices: device_id = device["deviceId"] display_json(f"api.get_device_settings({device_id})", api.get_device_settings(device_id)) # GOALS elif i == "u": # Get active goals goals = api.get_goals("active") display_json("api.get_goals(\"active\")", goals) elif i == "v": # Get future goals goals = api.get_goals("future") display_json("api.get_goals(\"future\")", goals) elif i == "w": # Get past goals goals = api.get_goals("past") display_json("api.get_goals(\"past\")", goals) # ALARMS elif i == "y": # Get Garmin device alarms alarms = api.get_device_alarms() for alarm in alarms: alarm_id = alarm["alarmId"] display_json(f"api.get_device_alarms({alarm_id})", alarm) elif i == "x": # Get Heart Rate Variability (hrv) data display_json(f"api.get_hrv_data({today.isoformat()})", api.get_hrv_data(today.isoformat())) elif i == "z": # Get progress summary for metric in ["elevationGain", "duration", "distance", "movingDuration"]: display_json( f"api.get_progress_summary_between_dates({today.isoformat()})", api.get_progress_summary_between_dates( startdate.isoformat(), today.isoformat(), metric )) # Gear elif i == "A": last_used_device = api.get_device_last_used() display_json(f"api.get_device_last_used()", last_used_device) userProfileNumber = last_used_device["userProfileNumber"] gear = api.get_gear(userProfileNumber) display_json(f"api.get_gear()", gear) display_json(f"api.get_gear_defaults()", api.get_gear_defaults(userProfileNumber)) display_json(f"api.get()", api.get_activity_types()) for gear in gear: uuid=gear["uuid"] name=gear["displayName"] display_json(f"api.get_gear_stats({uuid}) / {name}", api.get_gear_stats(uuid)) elif i == "Z": # Logout Garmin Connect portal display_json("api.logout()", api.logout()) api = None except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred: %s", err) except KeyError: # Invalid menu option chosen pass else: print("Could not login to Garmin Connect, try again later.") # Main program loop while True: # Display header and login print("\n*** Garmin Connect API Demo by cyberjunky ***\n") # Init API if not api: api = init_api(email, password) # Display menu print_menu() option = readchar.readkey() switch(api, option) ``` ## Donations [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) %package help Summary: Development documents and examples for garminconnect Provides: python3-garminconnect-doc %description help [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) # Python: Garmin Connect Python 3 API wrapper for Garmin Connect to get your statistics. ## About This package allows you to request garmin device, activity and health data from your Garmin Connect account. See ## Installation ```bash pip3 install garminconnect ``` ## API Demo Program I wrote this for testing and playing with all available/known API calls. If you run it from the python-garmin connect directory it will use the library code beneath it, so you can develop without reinstalling the package. The code also demonstrates how to implement session saving and re-using of the cookies. You can set environment variables with your credentials like so, this is optional: ```bash export EMAIL= export PASSWORD= ``` Install the pre-requisites for the example program (not all are needed for using the library package): ```bash pip3 install cloudscraper readchar requests pwinput ``` Or you can just run the program and enter your credentials when asked, it will create and save a session file and use that until it's outdated/invalid. ``` python3 ./example.py *** Garmin Connect API Demo by cyberjunky *** 1 -- Get full name 2 -- Get unit system 3 -- Get activity data for '2023-03-10' 4 -- Get activity data for '2023-03-10' (compatible with garminconnect-ha) 5 -- Get body composition data for '2023-03-10' (compatible with garminconnect-ha) 6 -- Get body composition data for from '2023-03-03' to '2023-03-10' (to be compatible with garminconnect-ha) 7 -- Get stats and body composition data for '2023-03-10' 8 -- Get steps data for '2023-03-10' 9 -- Get heart rate data for '2023-03-10' 0 -- Get training readiness data for '2023-03-10' - -- Get daily step data for '2023-03-03' to '2023-03-10' / -- Get body battery data for '2023-03-03' to '2023-03-10' ! -- Get floors data for '2023-03-03' ? -- Get blood pressure data for '2023-03-03' to '2023-03-10' . -- Get training status data for '2023-03-10' a -- Get resting heart rate data for 2023-03-10' b -- Get hydration data for '2023-03-10' c -- Get sleep data for '2023-03-10' d -- Get stress data for '2023-03-10' e -- Get respiration data for '2023-03-10' f -- Get SpO2 data for '2023-03-10' g -- Get max metric data (like vo2MaxValue and fitnessAge) for '2023-03-10' h -- Get personal record for user i -- Get earned badges for user j -- Get adhoc challenges data from start '0' and limit '100' k -- Get available badge challenges data from '1' and limit '100' l -- Get badge challenges data from '1' and limit '100' m -- Get non completed badge challenges data from '1' and limit '100' n -- Get activities data from start '0' and limit '100' o -- Get last activity p -- Download activities data by date from '2023-03-03' to '2023-03-10' r -- Get all kinds of activities data from '0' s -- Upload activity data from file 'MY_ACTIVITY.fit' t -- Get all kinds of Garmin device info u -- Get active goals v -- Get future goals w -- Get past goals y -- Get all Garmin device alarms x -- Get Heart Rate Variability data (HRV) for '2023-03-10' z -- Get progress summary from '2023-03-03' to '2023-03-10' for all metrics A -- Get gear, the defaults, activity types and statistics Z -- Logout Garmin Connect portal q -- Exit Make your selection: ``` This is some example code, and probably older than the latest code which can be found in 'example.py'. ```python #!/usr/bin/env python3 """ pip3 install cloudscraper requests readchar pwinput export EMAIL= export PASSWORD= """ import datetime import json import logging import os import sys import requests import pwinput import readchar from garminconnect import ( Garmin, GarminConnectAuthenticationError, GarminConnectConnectionError, GarminConnectTooManyRequestsError, ) # Configure debug logging # logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Load environment variables if defined email = os.getenv("EMAIL") password = os.getenv("PASSWORD") api = None # Example selections and settings today = datetime.date.today() startdate = today - datetime.timedelta(days=7) # Select past week start = 0 limit = 100 start_badge = 1 # Badge related calls calls start counting at 1 activitytype = "" # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activityfile = "MY_ACTIVITY.fit" # Supported file types are: .fit .gpx .tcx menu_options = { "1": "Get full name", "2": "Get unit system", "3": f"Get activity data for '{today.isoformat()}'", "4": f"Get activity data for '{today.isoformat()}' (compatible with garminconnect-ha)", "5": f"Get body composition data for '{today.isoformat()}' (compatible with garminconnect-ha)", "6": f"Get body composition data for from '{startdate.isoformat()}' to '{today.isoformat()}' (to be compatible with garminconnect-ha)", "7": f"Get stats and body composition data for '{today.isoformat()}'", "8": f"Get steps data for '{today.isoformat()}'", "9": f"Get heart rate data for '{today.isoformat()}'", "0": f"Get training readiness data for '{today.isoformat()}'", "-": f"Get daily step data for '{startdate.isoformat()}' to '{today.isoformat()}'", "/": f"Get body battery data for '{startdate.isoformat()}' to '{today.isoformat()}'", "!": f"Get floors data for '{startdate.isoformat()}'", "?": f"Get blood pressure data for '{startdate.isoformat()}' to '{today.isoformat()}'", ".": f"Get training status data for '{today.isoformat()}'", "a": f"Get resting heart rate data for {today.isoformat()}'", "b": f"Get hydration data for '{today.isoformat()}'", "c": f"Get sleep data for '{today.isoformat()}'", "d": f"Get stress data for '{today.isoformat()}'", "e": f"Get respiration data for '{today.isoformat()}'", "f": f"Get SpO2 data for '{today.isoformat()}'", "g": f"Get max metric data (like vo2MaxValue and fitnessAge) for '{today.isoformat()}'", "h": "Get personal record for user", "i": "Get earned badges for user", "j": f"Get adhoc challenges data from start '{start}' and limit '{limit}'", "k": f"Get available badge challenges data from '{start_badge}' and limit '{limit}'", "l": f"Get badge challenges data from '{start_badge}' and limit '{limit}'", "m": f"Get non completed badge challenges data from '{start_badge}' and limit '{limit}'", "n": f"Get activities data from start '{start}' and limit '{limit}'", "o": "Get last activity", "p": f"Download activities data by date from '{startdate.isoformat()}' to '{today.isoformat()}'", "r": f"Get all kinds of activities data from '{start}'", "s": f"Upload activity data from file '{activityfile}'", "t": "Get all kinds of Garmin device info", "u": "Get active goals", "v": "Get future goals", "w": "Get past goals", "y": "Get all Garmin device alarms", "x": f"Get Heart Rate Variability data (HRV) for '{today.isoformat()}'", "z": f"Get progress summary from '{startdate.isoformat()}' to '{today.isoformat()}' for all metrics", "A": "Get gear, the defaults, activity types and statistics", "Z": "Logout Garmin Connect portal", "q": "Exit", } def display_json(api_call, output): """Format API output for better readability.""" dashed = "-"*20 header = f"{dashed} {api_call} {dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def display_text(output): """Format API output for better readability.""" dashed = "-"*60 header = f"{dashed}" footer = "-"*len(header) print(header) print(json.dumps(output, indent=4)) print(footer) def get_credentials(): """Get user credentials.""" email = input("Login e-mail: ") password = pwinput.pwinput(prompt='Password: ') return email, password def init_api(email, password): """Initialize Garmin API with your credentials.""" try: ## Try to load the previous session with open("session.json") as f: saved_session = json.load(f) print( "Login to Garmin Connect using session loaded from 'session.json'...\n" ) # Use the loaded session for initializing the API (without need for credentials) api = Garmin(session_data=saved_session) # Login using the api.login() except (FileNotFoundError, GarminConnectAuthenticationError): # Login to Garmin Connect portal with credentials since session is invalid or not present. print( "Session file not present or turned invalid, login with your Garmin Connect credentials.\n" "NOTE: Credentials will not be stored, the session cookies will be stored in 'session.json' for future use.\n" ) try: # Ask for credentials if not set as environment variables if not email or not password: email, password = get_credentials() api = Garmin(email, password) api.login() # Save session dictionary to json file for future use with open("session.json", "w", encoding="utf-8") as f: json.dump(api.session_data, f, ensure_ascii=False, indent=4) except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred during Garmin Connect communication: %s", err) return None return api def print_menu(): """Print examples menu.""" for key in menu_options.keys(): print(f"{key} -- {menu_options[key]}") print("Make your selection: ", end="", flush=True) def switch(api, i): """Run selected API call.""" # Exit example program if i == "q": print("Bye!") sys.exit() # Skip requests if login failed if api: try: print(f"\n\nExecuting: {menu_options[i]}\n") # USER BASICS if i == "1": # Get full name from profile display_json("api.get_full_name()", api.get_full_name()) elif i == "2": # Get unit system from profile display_json("api.get_unit_system()", api.get_unit_system()) # USER STATISTIC SUMMARIES elif i == "3": # Get activity data for 'YYYY-MM-DD' display_json(f"api.get_stats('{today.isoformat()}')", api.get_stats(today.isoformat())) elif i == "4": # Get activity data (to be compatible with garminconnect-ha) display_json(f"api.get_user_summary('{today.isoformat()}')", api.get_user_summary(today.isoformat())) elif i == "5": # Get body composition data for 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{today.isoformat()}')", api.get_body_composition(today.isoformat())) elif i == "6": # Get body composition data for multiple days 'YYYY-MM-DD' (to be compatible with garminconnect-ha) display_json(f"api.get_body_composition('{startdate.isoformat()}', '{today.isoformat()}')", api.get_body_composition(startdate.isoformat(), today.isoformat()) ) elif i == "7": # Get stats and body composition data for 'YYYY-MM-DD' display_json(f"api.get_stats_and_body('{today.isoformat()}')", api.get_stats_and_body(today.isoformat())) # USER STATISTICS LOGGED elif i == "8": # Get steps data for 'YYYY-MM-DD' display_json(f"api.get_steps_data('{today.isoformat()}')", api.get_steps_data(today.isoformat())) elif i == "9": # Get heart rate data for 'YYYY-MM-DD' display_json(f"api.get_heart_rates('{today.isoformat()}')", api.get_heart_rates(today.isoformat())) elif i == "0": # Get training readiness data for 'YYYY-MM-DD' display_json(f"api.get_training_readiness('{today.isoformat()}')", api.get_training_readiness(today.isoformat())) elif i == "/": # Get daily body battery data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_body_battery('{startdate.isoformat()}, {today.isoformat()}')", api.get_body_battery(startdate.isoformat(), today.isoformat())) elif i == "?": # Get daily blood pressure data for 'YYYY-MM-DD' to 'YYYY-MM-DD' display_json(f"api.get_blood_pressure('{startdate.isoformat()}, {today.isoformat()}')", api.get_blood_pressure(startdate.isoformat(), today.isoformat())) elif i == "-": # Get daily step data for 'YYYY-MM-DD' display_json(f"api.get_daily_steps('{startdate.isoformat()}, {today.isoformat()}')", api.get_daily_steps(startdate.isoformat(), today.isoformat())) elif i == "!": # Get daily floors data for 'YYYY-MM-DD' display_json(f"api.get_floors('{today.isoformat()}')", api.get_floors(today.isoformat())) elif i == ".": # Get training status data for 'YYYY-MM-DD' display_json(f"api.get_training_status('{today.isoformat()}')", api.get_training_status(today.isoformat())) elif i == "a": # Get resting heart rate data for 'YYYY-MM-DD' display_json(f"api.get_rhr_day('{today.isoformat()}')", api.get_rhr_day(today.isoformat())) elif i == "b": # Get hydration data 'YYYY-MM-DD' display_json(f"api.get_hydration_data('{today.isoformat()}')", api.get_hydration_data(today.isoformat())) elif i == "c": # Get sleep data for 'YYYY-MM-DD' display_json(f"api.get_sleep_data('{today.isoformat()}')", api.get_sleep_data(today.isoformat())) elif i == "d": # Get stress data for 'YYYY-MM-DD' display_json(f"api.get_stress_data('{today.isoformat()}')", api.get_stress_data(today.isoformat())) elif i == "e": # Get respiration data for 'YYYY-MM-DD' display_json(f"api.get_respiration_data('{today.isoformat()}')", api.get_respiration_data(today.isoformat())) elif i == "f": # Get SpO2 data for 'YYYY-MM-DD' display_json(f"api.get_spo2_data('{today.isoformat()}')", api.get_spo2_data(today.isoformat())) elif i == "g": # Get max metric data (like vo2MaxValue and fitnessAge) for 'YYYY-MM-DD' display_json(f"api.get_max_metrics('{today.isoformat()}')", api.get_max_metrics(today.isoformat())) elif i == "h": # Get personal record for user display_json("api.get_personal_record()", api.get_personal_record()) elif i == "i": # Get earned badges for user display_json("api.get_earned_badges()", api.get_earned_badges()) elif i == "j": # Get adhoc challenges data from start and limit display_json( f"api.get_adhoc_challenges({start},{limit})", api.get_adhoc_challenges(start, limit) ) # 1=start, 100=limit elif i == "k": # Get available badge challenges data from start and limit display_json( f"api.get_available_badge_challenges({start_badge}, {limit})", api.get_available_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "l": # Get badge challenges data from start and limit display_json( f"api.get_badge_challenges({start_badge}, {limit})", api.get_badge_challenges(start_badge, limit) ) # 1=start, 100=limit elif i == "m": # Get non completed badge challenges data from start and limit display_json( f"api.get_non_completed_badge_challenges({start_badge}, {limit})", api.get_non_completed_badge_challenges(start_badge, limit) ) # 1=start, 100=limit # ACTIVITIES elif i == "n": # Get activities data from start and limit display_json(f"api.get_activities({start}, {limit})", api.get_activities(start, limit)) # 0=start, 1=limit elif i == "o": # Get last activity display_json("api.get_last_activity()", api.get_last_activity()) elif i == "p": # Get activities data from startdate 'YYYY-MM-DD' to enddate 'YYYY-MM-DD', with (optional) activitytype # Possible values are: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other activities = api.get_activities_by_date( startdate.isoformat(), today.isoformat(), activitytype ) # Download activities for activity in activities: activity_id = activity["activityId"] display_text(activity) print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.GPX)") gpx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.GPX ) output_file = f"./{str(activity_id)}.gpx" with open(output_file, "wb") as fb: fb.write(gpx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.TCX)") tcx_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.TCX ) output_file = f"./{str(activity_id)}.tcx" with open(output_file, "wb") as fb: fb.write(tcx_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.ORIGINAL)") zip_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.ORIGINAL ) output_file = f"./{str(activity_id)}.zip" with open(output_file, "wb") as fb: fb.write(zip_data) print(f"Activity data downloaded to file {output_file}") print(f"api.download_activity({activity_id}, dl_fmt=api.ActivityDownloadFormat.CSV)") csv_data = api.download_activity( activity_id, dl_fmt=api.ActivityDownloadFormat.CSV ) output_file = f"./{str(activity_id)}.csv" with open(output_file, "wb") as fb: fb.write(csv_data) print(f"Activity data downloaded to file {output_file}") elif i == "r": # Get activities data from start and limit activities = api.get_activities(start, limit) # 0=start, 1=limit # Get activity splits first_activity_id = activities[0].get("activityId") display_json(f"api.get_activity_splits({first_activity_id})", api.get_activity_splits(first_activity_id)) # Get activity split summaries for activity id display_json(f"api.get_activity_split_summaries({first_activity_id})", api.get_activity_split_summaries(first_activity_id)) # Get activity weather data for activity display_json(f"api.get_activity_weather({first_activity_id})", api.get_activity_weather(first_activity_id)) # Get activity hr timezones id display_json(f"api.get_activity_hr_in_timezones({first_activity_id})", api.get_activity_hr_in_timezones(first_activity_id)) # Get activity details for activity id display_json(f"api.get_activity_details({first_activity_id})", api.get_activity_details(first_activity_id)) # Get gear data for activity id display_json(f"api.get_activity_gear({first_activity_id})", api.get_activity_gear(first_activity_id)) # Activity self evaluation data for activity id display_json(f"api.get_activity_evaluation({first_activity_id})", api.get_activity_evaluation(first_activity_id)) # Get exercise sets in case the activity is a strength_training if activities[0]["activityType"]["typeKey"] == "strength_training": display_json(f"api.get_activity_exercise_sets({first_activity_id})", api.get_activity_exercise_sets(first_activity_id)) elif i == "s": # Upload activity from file display_json(f"api.upload_activity({activityfile})", api.upload_activity(activityfile)) # DEVICES elif i == "t": # Get Garmin devices devices = api.get_devices() display_json("api.get_devices()", devices) # Get device last used device_last_used = api.get_device_last_used() display_json("api.get_device_last_used()", device_last_used) # Get settings per device for device in devices: device_id = device["deviceId"] display_json(f"api.get_device_settings({device_id})", api.get_device_settings(device_id)) # GOALS elif i == "u": # Get active goals goals = api.get_goals("active") display_json("api.get_goals(\"active\")", goals) elif i == "v": # Get future goals goals = api.get_goals("future") display_json("api.get_goals(\"future\")", goals) elif i == "w": # Get past goals goals = api.get_goals("past") display_json("api.get_goals(\"past\")", goals) # ALARMS elif i == "y": # Get Garmin device alarms alarms = api.get_device_alarms() for alarm in alarms: alarm_id = alarm["alarmId"] display_json(f"api.get_device_alarms({alarm_id})", alarm) elif i == "x": # Get Heart Rate Variability (hrv) data display_json(f"api.get_hrv_data({today.isoformat()})", api.get_hrv_data(today.isoformat())) elif i == "z": # Get progress summary for metric in ["elevationGain", "duration", "distance", "movingDuration"]: display_json( f"api.get_progress_summary_between_dates({today.isoformat()})", api.get_progress_summary_between_dates( startdate.isoformat(), today.isoformat(), metric )) # Gear elif i == "A": last_used_device = api.get_device_last_used() display_json(f"api.get_device_last_used()", last_used_device) userProfileNumber = last_used_device["userProfileNumber"] gear = api.get_gear(userProfileNumber) display_json(f"api.get_gear()", gear) display_json(f"api.get_gear_defaults()", api.get_gear_defaults(userProfileNumber)) display_json(f"api.get()", api.get_activity_types()) for gear in gear: uuid=gear["uuid"] name=gear["displayName"] display_json(f"api.get_gear_stats({uuid}) / {name}", api.get_gear_stats(uuid)) elif i == "Z": # Logout Garmin Connect portal display_json("api.logout()", api.logout()) api = None except ( GarminConnectConnectionError, GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, requests.exceptions.HTTPError, ) as err: logger.error("Error occurred: %s", err) except KeyError: # Invalid menu option chosen pass else: print("Could not login to Garmin Connect, try again later.") # Main program loop while True: # Display header and login print("\n*** Garmin Connect API Demo by cyberjunky ***\n") # Init API if not api: api = init_api(email, password) # Display menu print_menu() option = readchar.readkey() switch(api, option) ``` ## Donations [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/cyberjunkynl/) %prep %autosetup -n garminconnect-0.1.55 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-garminconnect -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Tue Jun 20 2023 Python_Bot - 0.1.55-1 - Package Spec generated