diff --git a/README.md b/README.md index 9caa09e..26e022b 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Make your selection: - **Body Composition & Weight**: 8 methods (weight tracking, body composition) - **Goals & Achievements**: 15 methods (challenges, badges, goals) - **Device & Technical**: 7 methods (device info, settings) -- **Gear & Equipment**: 6 methods (gear management, tracking) +- **Gear & Equipment**: 8 methods (gear management, tracking) - **Hydration & Wellness**: 9 methods (hydration, blood pressure, menstrual) - **System & Export**: 4 methods (reporting, logout, GraphQL) diff --git a/demo.py b/demo.py index 5a8a3f2..86b5efc 100755 --- a/demo.py +++ b/demo.py @@ -366,6 +366,10 @@ def __init__(self): "desc": "Track gear usage (total time used)", "key": "track_gear_usage", }, + "7": { + "desc": "Add and remove gear to/from activity (interactive)", + "key": "add_and_remove_gear_to_activity", + }, }, }, "0": { @@ -2394,6 +2398,63 @@ def set_gear_default_data(api: Garmin) -> None: print(f"❌ Error setting gear default: {e}") +def add_and_remove_gear_to_activity(api: Garmin) -> None: + """Add gear to most recent activity, then remove.""" + try: + device_last_used = api.get_device_last_used() + user_profile_number = device_last_used.get("userProfileNumber") + if user_profile_number: + gear_list = api.get_gear(user_profile_number) + if gear_list: + activities = api.get_activities(0, 1) + if activities: + + activity_id = activities[0].get("activityId") + activity_name = activities[0].get("activityName") + for gear in gear_list: + if gear["gearStatusName"] == "active": + break + gear_uuid = gear.get("uuid") + gear_name = gear.get("displayName", "Unknown") + if gear_uuid: + # Add gear to an activity + # Correct method signature: add_gear_to_activity(gearUUID, activity_id) + call_and_display( + api.add_gear_to_activity, + gear_uuid, + activity_id, + method_name="add_gear_to_activity", + api_call_desc=f"api.add_gear_to_activity('{gear_uuid}', {activity_id}) - Add {gear_name} to {activity_name}", + ) + print("✅ Gear added successfully!") + + # Wait for user to check gear, then continue + input( + "Go check Garmin to confirm, then press Enter to continue" + ) + + # Remove gear from an activity + # Correct method signature: remove_gear_from_activity(gearUUID, activity_id) + call_and_display( + api.remove_gear_from_activity, + gear_uuid, + activity_id, + method_name="remove_gear_from_activity", + api_call_desc=f"api.remove_gear_from_activity('{gear_uuid}', {activity_id}) - Remove {gear_name} from {activity_name}", + ) + print("✅ Gear removed successfully!") + else: + print("❌ No activities found") + else: + print("❌ No gear UUID found") + else: + print("ℹ️ No gear found") + else: + print("❌ Could not get user profile number") + except Exception as e: + print(f"❌ Error adding gear: {e}") + + def set_activity_name_data(api: Garmin) -> None: """Set activity name.""" try: @@ -3295,6 +3356,9 @@ def execute_api_call(api: Garmin, key: str) -> None: "get_gear_activities": lambda: get_gear_activities_data(api), "set_gear_default": lambda: set_gear_default_data(api), "track_gear_usage": lambda: track_gear_usage_data(api), + "add_and_remove_gear_to_activity": lambda: add_and_remove_gear_to_activity( + api + ), # Hydration & Wellness "get_hydration_data": lambda: call_and_display( api.get_hydration_data, diff --git a/garminconnect/__init__.py b/garminconnect/__init__.py index 46254b1..5cc20da 100644 --- a/garminconnect/__init__.py +++ b/garminconnect/__init__.py @@ -256,7 +256,7 @@ def __init__( self.garmin_connect_upload = "/upload-service/upload" self.garmin_connect_gear = "/gear-service/gear/filterGear" - self.garmin_connect_gear_baseurl = "/gear-service/gear/" + self.garmin_connect_gear_baseurl = "/gear-service/gear" self.garmin_request_reload_url = "/wellness-service/wellness/epoch/request" @@ -1855,13 +1855,13 @@ def get_gear(self, userProfileNumber: str) -> dict[str, Any]: return self.connectapi(url) def get_gear_stats(self, gearUUID: str) -> dict[str, Any]: - url = f"{self.garmin_connect_gear_baseurl}stats/{gearUUID}" + url = f"{self.garmin_connect_gear_baseurl}/stats/{gearUUID}" logger.debug("Requesting gear stats for gearUUID %s", gearUUID) return self.connectapi(url) def get_gear_defaults(self, userProfileNumber: str) -> dict[str, Any]: url = ( - f"{self.garmin_connect_gear_baseurl}user/" + f"{self.garmin_connect_gear_baseurl}/user/" f"{userProfileNumber}/activityTypes" ) logger.debug("Requesting gear defaults for user %s", userProfileNumber) @@ -1873,7 +1873,7 @@ def set_gear_default( defaultGearString = "/default/true" if defaultGear else "" method_override = "PUT" if defaultGear else "DELETE" url = ( - f"{self.garmin_connect_gear_baseurl}{gearUUID}/" + f"{self.garmin_connect_gear_baseurl}/{gearUUID}/" f"activityType/{activityType}{defaultGearString}" ) return self.garth.request(method_override, "connectapi", url, api=True) @@ -2025,6 +2025,52 @@ def get_gear_activities( return self.connectapi(url) + def add_gear_to_activity( + self, gearUUID: str, activity_id: int | str + ) -> dict[str, Any]: + """ + Associates gear with an activity. Requires a gearUUID and an activity_id + + Args: + gearUUID: UID for gear to add to activity. Findable though the get_gear function + activity_id: Integer ID for the activity to add the gear to + + Returns: + Dictionary containing information for the added gear + """ + + gearUUID = str(gearUUID) + activity_id = _validate_positive_integer(int(activity_id), "activity_id") + + url = ( + f"{self.garmin_connect_gear_baseurl}/link/{gearUUID}/activity/{activity_id}" + ) + logger.debug("Linking gear %s to activity %s", gearUUID, activity_id) + + return self.garth.put("connectapi", url).json() + + def remove_gear_from_activity( + self, gearUUID: str, activity_id: int | str + ) -> dict[str, Any]: + """ + Removes gear from an activity. Requires a gearUUID and an activity_id + + Args: + gearUUID: UID for gear to remove from activity. Findable though the get_gear method. + activity_id: Integer ID for the activity to remove the gear from + + Returns: + Dictionary containing information about the removed gear + """ + + gearUUID = str(gearUUID) + activity_id = _validate_positive_integer(int(activity_id), "activity_id") + + url = f"{self.garmin_connect_gear_baseurl}/unlink/{gearUUID}/activity/{activity_id}" + logger.debug("Unlinking gear %s from activity %s", gearUUID, activity_id) + + return self.garth.put("connectapi", url).json() + def get_user_profile(self) -> dict[str, Any]: """Get all users settings."""