diff --git a/README.md b/README.md index da41ea2..2179622 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ data: See the action template for other available values to add. -**Full Automation Example (Withings to Garmin):** +**Withings scale data to Garmin** ```yaml alias: WithingsToGarmin @@ -229,7 +229,7 @@ mode: single ```yaml action: garmin_connect.set_active_gear target: - entity_id: sensor.garmin_connect_adidas_running_shoes + entity_id: sensor.garmin_connect_adidas data: activity_type: running setting: set as default @@ -247,7 +247,7 @@ data: notes: Measured with Beurer BC54 ``` -### Create Activity +**Create Activity** Creates an activity in Garmin Connect: @@ -261,14 +261,43 @@ data: distance_km: 5.0 ``` -### Upload Activity +**Upload Activity** Uploads an activity file (FIT, GPX, TCX) to Garmin Connect: ```yaml action: garmin_connect.upload_activity data: - file_path: "/config/activities/run.fit" + file_path: "morning_run.fit" +``` + +**Add Gear to Activity** + +Associates gear (shoes, bike, etc.) with a specific activity: + +```yaml +action: garmin_connect.add_gear_to_activity +data: + activity_id: 12345678901 + gear_uuid: "abc12345-def6-7890-ghij-klmn12345678" +``` + +**Automatically assign alternate running shoes after a run** + +```yaml +automation: + - alias: "Assign alternate shoes to last running activity" + trigger: + - platform: state + entity_id: sensor.garmin_connect_last_activity + condition: + - condition: template + value_template: "{{ state_attr('sensor.garmin_connect_last_activity', 'activityType') == 'running' }}" + action: + - service: garmin_connect.add_gear_to_activity + data: + activity_id: "{{ state_attr('sensor.garmin_connect_last_activity', 'activityId') }}" + gear_uuid: "{{ state_attr('sensor.garmnin_connect_adidas', 'gear_uuid') }}" ``` ### Enable Debug Logging diff --git a/custom_components/garmin_connect/sensor.py b/custom_components/garmin_connect/sensor.py index 1007aff..5988da3 100644 --- a/custom_components/garmin_connect/sensor.py +++ b/custom_components/garmin_connect/sensor.py @@ -267,6 +267,7 @@ class GarminConnectGearSensor(CoordinatorEntity, SensorEntity): return {} attributes = { + "gear_uuid": self._uuid, "last_synced": self.coordinator.data["lastSyncTimestampGMT"], "total_activities": stats["totalActivities"], "create_date": stats["createDate"], diff --git a/custom_components/garmin_connect/services.py b/custom_components/garmin_connect/services.py index f993f54..8671471 100644 --- a/custom_components/garmin_connect/services.py +++ b/custom_components/garmin_connect/services.py @@ -68,6 +68,14 @@ UPLOAD_ACTIVITY_SCHEMA = vol.Schema( } ) +SERVICE_ADD_GEAR_TO_ACTIVITY = "add_gear_to_activity" +ADD_GEAR_TO_ACTIVITY_SCHEMA = vol.Schema( + { + vol.Required("activity_id"): vol.Coerce(int), + vol.Required("gear_uuid"): cv.string, + } +) + def _get_coordinator(hass: HomeAssistant) -> GarminConnectDataUpdateCoordinator: """Get the first available coordinator from config entries.""" @@ -243,6 +251,32 @@ async def async_setup_services(hass: HomeAssistant) -> None: translation_placeholders={"error": str(err)}, ) from err + async def handle_add_gear_to_activity(call: ServiceCall) -> None: + """Handle add_gear_to_activity service call.""" + coordinator = _get_coordinator(hass) + + activity_id = call.data.get("activity_id") + gear_uuid = call.data.get("gear_uuid") + + if not await coordinator.async_login(): + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key="login_failed", + ) + + try: + await hass.async_add_executor_job( + coordinator.api.add_gear_to_activity, + gear_uuid, + activity_id, + ) + except Exception as err: + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key="add_gear_to_activity_failed", + translation_placeholders={"error": str(err)}, + ) from err + # Register services hass.services.async_register( DOMAIN, @@ -272,6 +306,13 @@ async def async_setup_services(hass: HomeAssistant) -> None: schema=UPLOAD_ACTIVITY_SCHEMA, ) + hass.services.async_register( + DOMAIN, + SERVICE_ADD_GEAR_TO_ACTIVITY, + handle_add_gear_to_activity, + schema=ADD_GEAR_TO_ACTIVITY_SCHEMA, + ) + async def async_unload_services(hass: HomeAssistant) -> None: """Unload Garmin Connect services.""" @@ -279,3 +320,4 @@ async def async_unload_services(hass: HomeAssistant) -> None: hass.services.async_remove(DOMAIN, SERVICE_ADD_BLOOD_PRESSURE) hass.services.async_remove(DOMAIN, SERVICE_CREATE_ACTIVITY) hass.services.async_remove(DOMAIN, SERVICE_UPLOAD_ACTIVITY) + hass.services.async_remove(DOMAIN, SERVICE_ADD_GEAR_TO_ACTIVITY) diff --git a/custom_components/garmin_connect/services.yaml b/custom_components/garmin_connect/services.yaml index 48ad532..6c0fc9f 100644 --- a/custom_components/garmin_connect/services.yaml +++ b/custom_components/garmin_connect/services.yaml @@ -299,5 +299,26 @@ upload_activity: description: Path to the activity file on the Home Assistant system. required: true example: "/config/activities/run.fit" + selector: + text: + +add_gear_to_activity: + name: Add gear to activity + description: Associate gear (shoes, bike, etc.) with a specific activity. + fields: + activity_id: + name: Activity ID + description: The ID of the activity to add the gear to. + required: true + example: 12345678901 + selector: + number: + min: 1 + mode: box + gear_uuid: + name: Gear UUID + description: The UUID of the gear to add. Find this in the gear sensor attributes. + required: true + example: "abc12345-def6-7890-ghij-klmn12345678" selector: text: \ No newline at end of file diff --git a/custom_components/garmin_connect/strings.json b/custom_components/garmin_connect/strings.json index d359b7b..9672b21 100644 --- a/custom_components/garmin_connect/strings.json +++ b/custom_components/garmin_connect/strings.json @@ -61,6 +61,9 @@ }, "file_not_found": { "message": "File not found: {file_path}" + }, + "add_gear_to_activity_failed": { + "message": "Failed to add gear to activity: {error}" } } } \ No newline at end of file diff --git a/custom_components/garmin_connect/translations/en.json b/custom_components/garmin_connect/translations/en.json index 8c9c90e..de37c12 100644 --- a/custom_components/garmin_connect/translations/en.json +++ b/custom_components/garmin_connect/translations/en.json @@ -423,6 +423,9 @@ }, "file_not_found": { "message": "File not found: {file_path}" + }, + "add_gear_to_activity_failed": { + "message": "Failed to add gear to activity: {error}" } } } \ No newline at end of file